> ## Documentation Index
> Fetch the complete documentation index at: https://pulian.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Messaging

> MessageModem, message loader, micro RPC, streaming, and runtime config.

# Messaging

## Copy-Paste Example

Message handler file:

```ts theme={null}
// src/messages/ping.msg.ts
import { defineMessage } from '@hile/message-loader'

export default defineMessage(async ({ data, params }) => {
  return {
    type: 'pong',
    data,
    params,
    timestamp: Date.now(),
  }
})
```

Microservice boot file:

```ts theme={null}
// src/services/app.boot.ts
import { defineService } from '@hile/core'
import { Application } from '@hile/micro'

export default defineService('micro.app', async (shutdown) => {
  const app = new Application({
    namespace: process.env.MICRO_NAMESPACE ?? 'example.service',
    registry: {
      host: process.env.REGISTRY_HOST ?? '127.0.0.1',
      port: Number(process.env.REGISTRY_PORT ?? 9876),
    },
    advertiseHost: process.env.HILE_ADVERTISE_HOST ?? '127.0.0.1',
  })

  await app.load(new URL('../messages', import.meta.url).pathname)
  const stop = await app.listen(Number(process.env.MICRO_PORT ?? 0))
  shutdown(stop)
  return app
})
```

Caller:

```ts theme={null}
const result = await app.call('example.service', '/ping', { hello: 'world' })
```

## More Examples

Streaming handler:

```ts theme={null}
// src/messages/events.msg.ts
import { defineMessage } from '@hile/message-loader'

export default defineMessage(async function* () {
  for (let i = 0; i < 3; i++) {
    yield { seq: i }
  }
})
```

Streaming caller:

```ts theme={null}
const stream = await app.stream('example.service', '/events', {})
for await (const chunk of stream) {
  console.log(chunk)
}
```

Custom WebSocket modem:

```ts theme={null}
import { MessageWs } from '@hile/message-ws'
import type WebSocket from 'ws'

class RpcWs extends MessageWs {
  constructor(ws: WebSocket, private readonly dispatch: (url: string, data: unknown) => Promise<unknown>) {
    super(ws)
  }

  protected exec(data: { url: string; data: unknown }) {
    return this.dispatch(data.url, data.data)
  }

  request<T>(url: string, data: unknown, timeout = 30_000) {
    return this._send<T>({ url, data }, { timeout })
  }
}
```

Notice that `request()` returns a `Promise<T>`. Await it directly.

## Complete Example

Provider handler:

```ts theme={null}
// src/messages/charge.msg.ts
import { defineMessage } from '@hile/message-loader'

export default defineMessage(async ({ data }) => {
  return { charged: true, input: data }
})
```

Provider boot:

```ts theme={null}
// src/services/app.boot.ts
import { defineService } from '@hile/core'
import { Application } from '@hile/micro'

export default defineService('billing.micro', async (shutdown) => {
  const app = new Application({
    namespace: 'billing',
    registry: { host: '127.0.0.1', port: 9876 },
    advertiseHost: '127.0.0.1',
  })

  await app.load(new URL('../messages', import.meta.url).pathname)
  const stop = await app.listen(9101)
  shutdown(stop)
  return app
})
```

Consumer:

```ts theme={null}
const result = await app.call('billing', '/charge', {
  tenantId: 't1',
  amount: 100,
})
```

## Anti-Patterns

* Appending a secondary response getter to `client.request('/x', data)`
* Returning a plain object from a handler called through `stream()`.
* Using pub/sub as a durable queue.
* Forgetting to register `shutdown(await app.listen(...))`.
