1 |
|
2 | import { createError } from 'micro-boom';
|
3 | import { json } from 'micro';
|
4 | import redis from 'redis';
|
5 |
|
6 | import type { CommitConfig } from '../types/Config.type';
|
7 | import { createClient, RedisClientType } from './redis-client';
|
8 | import runLua from './runLua';
|
9 |
|
10 | type Event = {
|
11 | type: string,
|
12 | payload: mixed,
|
13 | };
|
14 |
|
15 | export const commit = async (redisClient: RedisClientType, event: Event, namespc: string) => {
|
16 | const lua = `
|
17 | local event = ARGV[1];
|
18 | local counter = redis.call('INCR', KEYS[1]);
|
19 |
|
20 | redis.call('HSET', KEYS[2], counter, event);
|
21 | redis.call('PUBLISH', ARGV[2]..'::events', counter .. ':' .. event);
|
22 | return counter;
|
23 | `;
|
24 |
|
25 | return runLua(redisClient, lua, {
|
26 | keys: [`${namespc}::id`, `${namespc}::events`],
|
27 | argv: [JSON.stringify(event), namespc],
|
28 | });
|
29 | };
|
30 |
|
31 |
|
32 | export default ({ redis, namespc }: CommitConfig) => {
|
33 | const client = createClient(redis);
|
34 |
|
35 | return async (req: any) => {
|
36 | const event = await json(req);
|
37 |
|
38 | if (typeof event.type !== 'string') {
|
39 | throw createError(422, 'Missing type');
|
40 | }
|
41 |
|
42 | const id = await commit(client, event, namespc);
|
43 |
|
44 | return { ...event, id };
|
45 | };
|
46 |
|
47 | }
|