UNPKG

@aimee-blue/ab-service-kit

Version:
1 lines 11.3 kB
{"version":3,"sources":["../../../src/shared/pubsub/pubsub.ts"],"names":["initializedClient","pubsubClient","PubSub","topicMap","Map","retrySettings","retryCodes","backoffSettings","initialRetryDelayMillis","retryDelayMultiplier","maxRetryDelayMillis","initialRpcTimeoutMillis","rpcTimeoutMultiplier","maxRpcTimeoutMillis","totalTimeoutMillis","addTopicToMap","topic","topicWithOpts","setPublishOptions","batching","maxMessages","maxMilliseconds","maxBytes","gaxOpts","retry","set","get","getTopic","topicPublisher","has","prepareTopics","topics","forEach","TIMEOUT_ERROR","publish","data","logger","Buffer","from","JSON","stringify","err","mesId","message","includes","delete","error","subscriptionNamesByTopic","createTopicAndSubscription","fullName","options","shortName","replace","genName","String","process","env","USER","lastName","autoCreateTopic","subscriptionName","autoCreateSubscription","subscriptionOptions","subOpts","undefined","topicExists","exists","create","subscription","subscribe","optLogger","pipe","name","Observable","subscriber","log","EOL","add","close","then","catch"],"mappings":"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","sourcesContent":["import * as PubSub from '@google-cloud/pubsub';\nimport { fromEvent, defer, from, merge, Observable } from 'rxjs';\nimport { switchMap, map, ignoreElements } from 'rxjs/operators';\nimport { appName } from '../app';\nimport { EOL } from 'os';\nimport { isDevBuild } from '../isTest';\nimport { registerError } from '../registerError';\nimport { BasicLogger, defaultBasicLogger } from '../logging';\nimport { uuid } from '../uuid';\n\nlet initializedClient: PubSub.PubSub | null = null;\n\nexport const pubsubClient = () => {\n return initializedClient || (initializedClient = new PubSub.PubSub());\n};\n\nconst topicMap = new Map<string, PubSub.Topic>();\n\nconst retrySettings = {\n retryCodes: [\n 10, // 'ABORTED'\n 1, // 'CANCELLED',\n 4, // 'DEADLINE_EXCEEDED'\n 13, // 'INTERNAL'\n 8, // 'RESOURCE_EXHAUSTED'\n 14, // 'UNAVAILABLE'\n 2, // 'UNKNOWN'\n ],\n backoffSettings: {\n initialRetryDelayMillis: 5,\n retryDelayMultiplier: 2,\n maxRetryDelayMillis: 60000,\n initialRpcTimeoutMillis: 10000,\n rpcTimeoutMultiplier: 1.0,\n maxRpcTimeoutMillis: 10000,\n totalTimeoutMillis: 10000,\n },\n};\n\nconst addTopicToMap = (topic: string) => {\n const topicWithOpts = pubsubClient().topic(topic);\n\n topicWithOpts.setPublishOptions({\n batching: {\n maxMessages: 1,\n maxMilliseconds: 1,\n maxBytes: 1,\n },\n gaxOpts: {\n retry: retrySettings,\n },\n });\n\n topicMap.set(topic, topicWithOpts);\n\n return topicMap.get(topic) as PubSub.Topic;\n};\n\nexport const getTopic = (topic: string): PubSub.Topic => {\n const topicPublisher = topicMap.has(topic)\n ? topicMap.get(topic)\n : addTopicToMap(topic);\n\n if (!topicPublisher) {\n return addTopicToMap(topic);\n }\n\n return topicPublisher;\n};\n\nexport async function prepareTopics(topics: string[]) {\n topics.forEach((topic) => {\n addTopicToMap(topic);\n });\n}\n\nconst TIMEOUT_ERROR = 'Retry total timeout exceeded before any response';\n\nexport async function publish<T>(\n topic: string,\n data: T,\n logger: BasicLogger = defaultBasicLogger()\n) {\n const topicPublisher = getTopic(topic);\n\n topicPublisher.publish(\n Buffer.from(JSON.stringify(data), 'utf8'),\n (err: Error | null, mesId) => {\n if (err) {\n registerError(err);\n if (err.message.includes(TIMEOUT_ERROR)) {\n topicMap.delete(topic);\n }\n logger.error(\n `💥 Error when publishing to topic ${topic} ${\n mesId ? `with message ${mesId}` : ''\n }`,\n err\n );\n }\n }\n );\n}\n\nexport type Message = PubSub.Message;\n\ntype SubscribeOptions = PubSub.SubscriptionOptions & {\n autoCreateTopic?: boolean;\n subscriptionName?: string;\n autoCreateSubscription?: boolean;\n autoDeleteSubscription?: boolean;\n subscriptionOptions?: PubSub.CreateSubscriptionOptions;\n};\n\nconst subscriptionNamesByTopic = new Map<string, string>();\n\nasync function createTopicAndSubscription(\n topic: string,\n fullName: string,\n options?: SubscribeOptions\n) {\n const shortName = fullName.replace('@aimee-blue/', '');\n\n const genName = isDevBuild()\n ? `${shortName}-${String(process.env.USER)}`\n : `${shortName}-${uuid()}`;\n\n const lastName = subscriptionNamesByTopic.get(topic);\n\n const {\n autoCreateTopic,\n subscriptionName,\n autoCreateSubscription,\n subscriptionOptions,\n ...subOpts\n } = {\n autoCreateTopic: true,\n subscriptionName: lastName || genName,\n autoCreateSubscription: true,\n subscriptionOptions: undefined,\n ...options,\n };\n\n const topicPublisher = getTopic(topic);\n\n if (autoCreateTopic && !lastName) {\n const [topicExists] = await topicPublisher.exists();\n if (!topicExists) {\n await topicPublisher.create();\n }\n }\n\n const subscription = topicPublisher.subscription(subscriptionName, subOpts);\n\n if (autoCreateSubscription && !lastName) {\n const [exists] = await subscription.exists();\n if (!exists) {\n await subscription.create(subscriptionOptions);\n }\n }\n\n // if success, then remember:\n if (!subscriptionNamesByTopic.get(topic)) {\n subscriptionNamesByTopic.set(topic, subscriptionName);\n }\n\n return subscription;\n}\n\nexport function subscribe(\n topic: string,\n options?: SubscribeOptions,\n optLogger?: BasicLogger\n) {\n return defer(() => from(appName())).pipe(\n switchMap((name) => createTopicAndSubscription(topic, name, options)),\n switchMap(\n (subscription) =>\n new Observable<Message>((subscriber) => {\n const name = subscription.name;\n\n const logger = optLogger || defaultBasicLogger();\n\n logger.log(\n `${EOL}🎬 Subscribing to topic \"${topic}\" with subscription \"${name}\"`,\n EOL\n );\n\n subscriber.add(\n merge(\n fromEvent<PubSub.Message>(subscription, 'message'),\n fromEvent<Error>(subscription, 'error').pipe(\n map((err) => {\n throw err;\n }),\n ignoreElements()\n )\n ).subscribe(subscriber)\n );\n subscriber.add(() => {\n subscription\n .close()\n .then(() => {\n logger.log(\n `${EOL}🏁 Unsubscribed from \"${subscription.name}\"`,\n EOL\n );\n })\n .catch((err: Error) => {\n registerError(err);\n logger.error(\n `${EOL}💥 Error when unsubscribing from \"${subscription.name}\"`,\n err,\n EOL\n );\n });\n });\n })\n )\n );\n}\n"],"file":"pubsub.js"}