@codecompose/typed-pubsub
Version:
A type-safe pub/sub abstraction for Google Cloud and Firebase
138 lines (132 loc) • 3.47 kB
JavaScript
// 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