Messages between resources

With kcds.core.Messages, one resource can call another by name, either waiting for a reply or simply notifying it. It suits a dependency that may be absent, because neither side needs the other's functions. Both resources must run on the same side. For server-to-client traffic, use Events.

Receiving

Each message type has one handler in a resource, and the latest handle call for a type wins.

kcds.core.Messages.handle('post', (payload, reply) => {
  const { text } = payload as { text: string };
  reply({ ok: Boolean(text) });
});

A handler should always answer, even when it fails. Otherwise the caller waits with no result, so put reply in a try/finally when the work can throw.

Asking and waiting

To get an answer, call Messages.request(resource, type, payload?) and await it:

const answer = (await kcds.core.Messages.request('blog', 'post', { text: 'hello' })) as {
  ok: boolean;
};
if (answer.ok) {
  console.info('posted');
}
What happensThe promise
The handler calls reply(value)resolves a tick later, and only the first reply counts
The resource has no handlersrejects with Resource is not available
No handler for this typerejects with Resource does not handle this message type
The handler throws firstrejects with that error
The handler never replieskeeps waiting, and rejects only when either resource stops

There is no built-in time limit. If a silent handler must not hold you up, race the request against a timer:

function withTimeout<T>(request: Promise<T>, ms: number): Promise<T> {
  return new Promise<T>((resolve, reject) => {
    const timer = setTimeout(() => reject(new Error('timed out')), ms);
    request.then(
      (value) => {
        clearTimeout(timer);
        resolve(value);
      },
      (problem) => {
        clearTimeout(timer);
        reject(problem);
      },
    );
  });
}

await withTimeout(kcds.core.Messages.request('blog', 'post', { text: 'hello' }), 2000);

Notifying without a reply

Messages.send(resource, type, payload?) does not wait for anything. reply does nothing in this case, and a missing resource or handler causes no error.

kcds.core.Messages.send('audit', 'login', { player: 'Henry' });

Restarts

When a resource stops or restarts, its handlers go, and requests waiting on it reject.