All files tx-outbox.ts

86.36% Statements 19/22
70% Branches 7/10
100% Functions 4/4
86.36% Lines 19/22

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 59 60 61 62 63 64 65    1x 1x                       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;
  isEvent: true;
};
 
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
      if (NewImage) {
        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;
      } else E{
        return batch;
      }
    }, {});
 
    const topicMessages: TopicMessages[] = Object.entries(batch).map(
      ([topic, messages]) => ({
        topic,
        messages,
      })
    );
    if (topicMessages.length > 0) {
      const producer = await producerP;
      await producer.sendBatch({ topicMessages, acks: -1 });
    }
  };