All files tx-outbox.ts

89.47% Statements 17/19
71.42% Branches 5/7
100% Functions 4/4
89.47% Lines 17/19

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58    1x 1x                     1x 1x 1x 1x               1x   1x 1x 1x       1x 1x                     1x     1x 1x         1x 1x    
import { DynamoDBStreamHandler } from "aws-lambda";
import { IHeaders, Producer, TopicMessages } from "kafkajs";
import { unmarshall } from "@aws-sdk/util-dynamodb";
import log from "./logging";
 
export type TxOutboxMessage = {
  topic: string;
  key?: string;
  value: string;
  partition?: number;
  headers?: Record<string, string>;
  timestamp?: string;
};
 
export const _handler =
  (producerP: Promise<Pick<Producer, "sendBatch">>): DynamoDBStreamHandler =>
  async (e) => {
    const batch = e.Records.reduce<{
      [topic: string]: {
        key: Buffer | undefined;
        value: Buffer;
        headers?: IHeaders;
      }[];
    }>((batch, next) => {
      // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
      const { NewImage } = next.dynamodb!;
      // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
      const object = unmarshall(NewImage as any) as TxOutboxMessage;
      const { topic, key, value, headers } = object;
      Iif (!topic || !value) {
        log.error("Invalid outbox messages", object);
        throw new Error("Invalid outbox messages: " + JSON.stringify(object));
      }
      const existingBatch = batch[topic] || [];
      const newBatch = {
        ...batch,
        [topic]: [
          ...existingBatch,
          {
            key: key ? Buffer.from(key, "base64") : undefined,
            value: Buffer.from(value, "base64"),
            headers,
          },
        ],
      };
      return newBatch;
    }, {});
 
    const topicMessages: TopicMessages[] = Object.entries(batch).map(
      ([topic, messages]) => ({
        topic,
        messages,
      })
    );
    const producer = await producerP;
    await producer.sendBatch({ topicMessages, acks: -1 });
  };