@aimee-blue/ab-service-kit
Version:
Aimee Blue Service Template
71 lines (61 loc) • 1.71 kB
text/typescript
import {
ITopicBoundActionCreator,
IActionCreator,
Channels,
IAnyAction,
} from '@aimee-blue/ab-contracts';
import { appName } from '../app';
import { localNow } from '../time';
import { publish } from './pubsub';
import { uuid } from '../uuid';
export const publishAction = async <
C extends ITopicBoundActionCreator<IAnyAction, string, unknown[]>
>(
creator: C,
...args: Parameters<C>
) => {
return publishActionToTopics([creator.topic], creator, ...args);
};
export const multicastAction = async <
C extends IActionCreator<IAnyAction, unknown[]>
>(
topics: string[],
creator: C,
...args: Parameters<C>
) => {
return publishActionToTopics(topics, creator, ...args);
};
const publishActionToTopics = async <
C extends IActionCreator<IAnyAction, unknown[]>
>(
topics: string[],
creator: C,
...args: Parameters<C>
) => {
if (topics.length === 0) {
throw new Error('Need at least one topic to publish to');
}
const app = await appName();
const messagePrototype: Channels.IPubSubMessageShape<ReturnType<C>> = {
channel: topics[0],
senderId: app,
timestamp: localNow(),
messageId: uuid(),
traceId: uuid(),
...(creator(...args) as ReturnType<C>),
};
await Promise.all(
topics.map(async (topic) => {
const message = {
...messagePrototype,
channel: topic,
};
await publish(topic, message);
console.log(
`Published message of type ${message.type} to topic ${message.channel} with id ${message.messageId} (trace id ${message.traceId}) from ${message.senderId}`
);
})
);
// messages only differ by channel, so we shouldn't rely on that
return messagePrototype;
};