UNPKG

@codecompose/typed-pubsub

Version:

A type-safe pub/sub abstraction for Google Cloud and Firebase

138 lines (132 loc) 3.47 kB
// src/factory.ts import { onMessagePublished as firebaseOnMessagePublished2 } from "firebase-functions/v2/pubsub"; // src/constants.ts var MINUTE_MS = 60 * 1e3; var defaultHandlerOptions = { retry: true, retryMaxAgeMinutes: void 0, // No limit on retry age by default memory: "512MiB", markEvent: false, timeoutSeconds: 20, vpcConnector: void 0, maxInstances: 250 }; // src/handler.ts import { onMessagePublished as firebaseOnMessagePublished } from "firebase-functions/v2/pubsub"; import { got } from "get-or-throw"; // src/utils/should-drop-event.ts function shouldDropEvent(event, maxAgeMinutes) { if (maxAgeMinutes === void 0) { return false; } const maxAgeMs = maxAgeMinutes * 60 * 1e3; const eventAge = Date.now() - Date.parse(event.time); if (eventAge > maxAgeMs) { console.error( new Error( `Dropping event ${event.type} for ${event.source} because max age (${String(maxAgeMinutes)} minutes) was reached.` ) ); return true; } return false; } // src/handler.ts function createHandlerFactory(schemas, region, eventMarkingFunctions, defaultOptions = defaultHandlerOptions, onMessagePublished = firebaseOnMessagePublished) { return ({ topic, handler, options = {} }) => { const { retryMaxAgeMinutes, memory, timeoutSeconds, markEvent, vpcConnector, retry } = { ...defaultOptions, ...options }; const canMarkEvents = markEvent && eventMarkingFunctions !== void 0; return onMessagePublished( { topic, region, retry, vpcConnector, cpu: 1, memory, timeoutSeconds }, async (event) => { if (shouldDropEvent(event, retryMaxAgeMinutes)) { return; } if (canMarkEvents && event.id) { if (await eventMarkingFunctions.isEventProcessed(event.id)) { console.error( new Error( `(Not an error) Pubsub event ${event.id} was already processed` ) ); return; } } const schema = got(schemas, topic); const messageData = event.data.message.json; const result = schema.safeParse(messageData); if (!result.success) { console.error( new Error(`Zod validation error for topic ${topic}`), result.error.flatten() ); return; } await handler(result.data); if (canMarkEvents && event.id) { await eventMarkingFunctions.markEventAsProcessed(event.id); } } ); }; } // src/publisher.ts import "@google-cloud/pubsub"; function createPublisherFactory(pubsubClient) { return (topicName) => { return async (data) => { const topic = pubsubClient.topic(topicName); await topic.publishMessage({ json: data }); }; }; } // src/factory.ts function createTypedPubsub({ client, schemas, region, options = {}, onMessagePublished = firebaseOnMessagePublished2 }) { const handlerOptions = { ...defaultHandlerOptions, ...options.defaultHandlerOptions ?? {} }; return { createPublisher: createPublisherFactory(client), createHandler: createHandlerFactory( schemas, region, options.eventMarkingFunctions, handlerOptions, onMessagePublished ) }; } export { createTypedPubsub }; //# sourceMappingURL=index.js.map