@palmetto/pubsub 3.2.2 → 3.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -1
- package/dist/gcppubsub/config.d.ts +6 -6
- package/dist/gcppubsub/config.js +8 -8
- package/dist/gcppubsub/connection.js +3 -6
- package/dist/gcppubsub/gcppubsub-helper.d.ts +8 -0
- package/dist/gcppubsub/gcppubsub-helper.js +29 -0
- package/dist/gcppubsub/subscriber.js +5 -6
- package/dist/interfaces.d.ts +13 -7
- package/dist/interfaces.js +25 -3
- package/dist/publisher.js +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -55,7 +55,7 @@ yarn add @palmetto/pubsub zod @palmetto/trace dd-trace
|
|
|
55
55
|
const publisher = new Publisher(console, [rabbitMqPublisher]);
|
|
56
56
|
|
|
57
57
|
const message: Model = {
|
|
58
|
-
id: undefined,
|
|
58
|
+
id: undefined, // leave id and meta undefined, the publisher will set these
|
|
59
59
|
meta: undefined,
|
|
60
60
|
message: "Hello, world!",
|
|
61
61
|
};
|
|
@@ -145,6 +145,10 @@ For specific details about using RabbitMQ see [RabbitMQ README.md](src/rabbitmq/
|
|
|
145
145
|
|
|
146
146
|
For specific details about using BullMQ see [BullMQ README.md](src/bullmq/README.md)
|
|
147
147
|
|
|
148
|
+
### Google Cloud Pubsub Usage
|
|
149
|
+
|
|
150
|
+
For specific details about using Google Cloud PubSub see [gcppubsub README.md](src/bcppubsub/README.md)
|
|
151
|
+
|
|
148
152
|
### Defining schemas
|
|
149
153
|
|
|
150
154
|
All schemas must be defined using `zod` v4.1+. By convention, all messages should extend the `IdMetaSchema` schema, but it is not strictly required.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import type * as gcppubsub from "@google-cloud/pubsub";
|
|
2
2
|
import { MessageContext, PubSubConfiguration } from "../interfaces.js";
|
|
3
3
|
import { GCP_PUBSUB_TRANSPORT } from "./connection.js";
|
|
4
4
|
export interface GcpPubSubConfiguration extends PubSubConfiguration {
|
|
@@ -36,11 +36,11 @@ export interface GcpPubSubConfiguration extends PubSubConfiguration {
|
|
|
36
36
|
/**
|
|
37
37
|
* Subscription settings to override defaults when creating a new subscription
|
|
38
38
|
*/
|
|
39
|
-
createSubscriptionOptions?: CreateSubscriptionOptions;
|
|
39
|
+
createSubscriptionOptions?: gcppubsub.CreateSubscriptionOptions;
|
|
40
40
|
/**
|
|
41
41
|
* subscription options to override defaults when starting a new subscription
|
|
42
42
|
*/
|
|
43
|
-
subscriptionOptions?: SubscriptionOptions;
|
|
43
|
+
subscriptionOptions?: gcppubsub.SubscriptionOptions;
|
|
44
44
|
/**
|
|
45
45
|
* During shutdown, pending acks will be waited for up to this amount of time (in milliseconds) after the last message is received before the subscription is closed. Default: 1_000 (1 second)
|
|
46
46
|
*/
|
|
@@ -58,9 +58,9 @@ export interface GcpPubSubMessageContext extends MessageContext {
|
|
|
58
58
|
export declare function getTopicName(config: GcpPubSubConfiguration, topicType: TopicType): string;
|
|
59
59
|
export declare function getSubscriptionName(config: GcpPubSubConfiguration): string;
|
|
60
60
|
export declare function isGcpPubSubConfiguration(config: PubSubConfiguration): config is GcpPubSubConfiguration;
|
|
61
|
-
export declare function ensureTopic(client: PubSub, topicName: string): Promise<void>;
|
|
62
|
-
export declare function ensureSubscription(client: PubSub, config: GcpPubSubConfiguration): Promise<{
|
|
63
|
-
deadLetterTopic?: Topic;
|
|
61
|
+
export declare function ensureTopic(client: gcppubsub.PubSub, topicName: string): Promise<void>;
|
|
62
|
+
export declare function ensureSubscription(client: gcppubsub.PubSub, config: GcpPubSubConfiguration): Promise<{
|
|
63
|
+
deadLetterTopic?: gcppubsub.Topic;
|
|
64
64
|
retries: number;
|
|
65
65
|
created: boolean;
|
|
66
66
|
}>;
|
package/dist/gcppubsub/config.js
CHANGED
|
@@ -15,7 +15,6 @@ exports.getSubscriptionName = getSubscriptionName;
|
|
|
15
15
|
exports.isGcpPubSubConfiguration = isGcpPubSubConfiguration;
|
|
16
16
|
exports.ensureTopic = ensureTopic;
|
|
17
17
|
exports.ensureSubscription = ensureSubscription;
|
|
18
|
-
const pubsub_1 = require("@google-cloud/pubsub");
|
|
19
18
|
const connection_js_1 = require("./connection.js");
|
|
20
19
|
exports.RETRY_FOREVER = -1;
|
|
21
20
|
exports.TopicNameExtensions = {
|
|
@@ -48,7 +47,7 @@ function ensureTopic(client, topicName) {
|
|
|
48
47
|
}
|
|
49
48
|
function ensureSubscription(client, config) {
|
|
50
49
|
return __awaiter(this, void 0, void 0, function* () {
|
|
51
|
-
var _a, _b, _c, _d, _e;
|
|
50
|
+
var _a, _b, _c, _d, _e, _f;
|
|
52
51
|
const topic = client.topic(getTopicName(config, "default"));
|
|
53
52
|
const subscriptions = (yield topic.getSubscriptions({
|
|
54
53
|
pageSize: 1000,
|
|
@@ -60,16 +59,17 @@ function ensureSubscription(client, config) {
|
|
|
60
59
|
let deadLetterTopic = undefined;
|
|
61
60
|
let retries;
|
|
62
61
|
if ((_b = meta.deadLetterPolicy) === null || _b === void 0 ? void 0 : _b.deadLetterTopic) {
|
|
63
|
-
const
|
|
62
|
+
const maxDeliveryAttempts = (_c = meta.deadLetterPolicy.maxDeliveryAttempts) !== null && _c !== void 0 ? _c : 0;
|
|
63
|
+
const deadLetterTopicName = meta.deadLetterPolicy.deadLetterTopic || "";
|
|
64
64
|
if (config.retries !== undefined && config.retries < 0) {
|
|
65
65
|
// If retries is negative, we want to retry forever, but GCP Pub/Sub doesn't support that, so we set it to the max allowed by the dead-letter policy
|
|
66
|
-
retries =
|
|
66
|
+
retries = maxDeliveryAttempts - 1;
|
|
67
67
|
}
|
|
68
68
|
else {
|
|
69
69
|
// config.retries can override maxDeliveryAttempts, but it can't exceed the max allowed by the dead-letter policy
|
|
70
|
-
retries = Math.min((
|
|
70
|
+
retries = Math.min((_d = config.retries) !== null && _d !== void 0 ? _d : 0, maxDeliveryAttempts - 1);
|
|
71
71
|
}
|
|
72
|
-
deadLetterTopic = client.topic(
|
|
72
|
+
deadLetterTopic = client.topic(deadLetterTopicName);
|
|
73
73
|
}
|
|
74
74
|
else {
|
|
75
75
|
retries = exports.RETRY_FOREVER;
|
|
@@ -82,9 +82,9 @@ function ensureSubscription(client, config) {
|
|
|
82
82
|
}
|
|
83
83
|
const topicName = getTopicName(config, "default");
|
|
84
84
|
const dlTopicName = getTopicName(config, "dead-letter");
|
|
85
|
-
const minRetryDelay = (
|
|
85
|
+
const minRetryDelay = (_e = config.retryDelay) !== null && _e !== void 0 ? _e : 30000;
|
|
86
86
|
const maxRetryDelay = config.maxRetryDelay;
|
|
87
|
-
const maxDeliveryAttempts = ((
|
|
87
|
+
const maxDeliveryAttempts = ((_f = config.retries) !== null && _f !== void 0 ? _f : 0) + 1;
|
|
88
88
|
const enableDeadLetter = maxDeliveryAttempts > 0;
|
|
89
89
|
if (enableDeadLetter) {
|
|
90
90
|
yield ensureSubscription(client, Object.assign(Object.assign({}, config), { retries: exports.RETRY_FOREVER, name: dlTopicName, topicName: dlTopicName, deadLetterTopicName: undefined, subscriptionName: `${dlTopicName}.sub`, retryDelay: minRetryDelay, maxRetryDelay }));
|
|
@@ -10,16 +10,13 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
exports.GcpPubSubConnection = exports.GCP_PUBSUB_TRANSPORT = void 0;
|
|
13
|
-
const
|
|
13
|
+
const gcppubsub_helper_js_1 = require("./gcppubsub-helper.js");
|
|
14
14
|
exports.GCP_PUBSUB_TRANSPORT = "gcp-pubsub";
|
|
15
15
|
class GcpPubSubConnection {
|
|
16
16
|
static create(config, logger) {
|
|
17
17
|
return __awaiter(this, void 0, void 0, function* () {
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
context: "GcpPubSubConnection",
|
|
21
|
-
});
|
|
22
|
-
const client = new GcpPubSubPackage.PubSub(Object.assign({ projectId: config.projectId }, config.clientConfig));
|
|
18
|
+
const gcppubsubPackage = yield (0, gcppubsub_helper_js_1.lazyLoadGcpPubSubPackage)("GcpPubSubConnection");
|
|
19
|
+
const client = new gcppubsubPackage.PubSub(Object.assign({ projectId: config.projectId }, config.clientConfig));
|
|
23
20
|
return new GcpPubSubConnection(client, logger);
|
|
24
21
|
});
|
|
25
22
|
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type * as gcppubsub from "@google-cloud/pubsub";
|
|
2
|
+
export declare const GCP_PUBSUB_TRANSPORT = "gcp-pubsub";
|
|
3
|
+
export interface GcpPubSubConnectionConfig {
|
|
4
|
+
projectId?: string;
|
|
5
|
+
clientConfig?: gcppubsub.ClientConfig;
|
|
6
|
+
}
|
|
7
|
+
export declare function getGcpPubSubPackage(): typeof gcppubsub | undefined;
|
|
8
|
+
export declare function lazyLoadGcpPubSubPackage(context: string): Promise<typeof gcppubsub>;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.GCP_PUBSUB_TRANSPORT = void 0;
|
|
13
|
+
exports.getGcpPubSubPackage = getGcpPubSubPackage;
|
|
14
|
+
exports.lazyLoadGcpPubSubPackage = lazyLoadGcpPubSubPackage;
|
|
15
|
+
const lazy_load_js_1 = require("../lazy-load.js");
|
|
16
|
+
exports.GCP_PUBSUB_TRANSPORT = "gcp-pubsub";
|
|
17
|
+
let GcpPubSubPackageInstance = undefined;
|
|
18
|
+
function getGcpPubSubPackage() {
|
|
19
|
+
return GcpPubSubPackageInstance;
|
|
20
|
+
}
|
|
21
|
+
function lazyLoadGcpPubSubPackage(context) {
|
|
22
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
23
|
+
GcpPubSubPackageInstance = yield (0, lazy_load_js_1.lazyLoad)({
|
|
24
|
+
packageName: "@google-cloud/pubsub",
|
|
25
|
+
context,
|
|
26
|
+
});
|
|
27
|
+
return GcpPubSubPackageInstance;
|
|
28
|
+
});
|
|
29
|
+
}
|
|
@@ -10,14 +10,13 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
exports.GcpPubSubSubscriber = void 0;
|
|
13
|
-
const pubsub_1 = require("@google-cloud/pubsub");
|
|
14
13
|
const trace_1 = require("@palmetto/trace");
|
|
15
14
|
const interfaces_js_1 = require("../interfaces.js");
|
|
16
15
|
const errors_js_1 = require("../errors.js");
|
|
17
16
|
const create_log_error_payload_js_1 = require("../create-log-error-payload.js");
|
|
18
17
|
const config_js_1 = require("./config.js");
|
|
19
18
|
const connection_js_1 = require("./connection.js");
|
|
20
|
-
const
|
|
19
|
+
const gcppubsub_helper_js_1 = require("./gcppubsub-helper.js");
|
|
21
20
|
const SHUTDOWN_DELAY = 1000;
|
|
22
21
|
class GcpPubSubSubscriber {
|
|
23
22
|
constructor(connection, logger) {
|
|
@@ -29,7 +28,7 @@ class GcpPubSubSubscriber {
|
|
|
29
28
|
}
|
|
30
29
|
startSubscribe(config, onMessage) {
|
|
31
30
|
return __awaiter(this, void 0, void 0, function* () {
|
|
32
|
-
var _a, _b, _c, _d;
|
|
31
|
+
var _a, _b, _c, _d, _e;
|
|
33
32
|
const subscriptionName = (0, config_js_1.getSubscriptionName)(config);
|
|
34
33
|
if (this.subscriptions.has(subscriptionName)) {
|
|
35
34
|
throw new errors_js_1.AlreadySubscribingError(subscriptionName);
|
|
@@ -51,9 +50,9 @@ class GcpPubSubSubscriber {
|
|
|
51
50
|
const subscription = this.connection.client.subscription(subscriptionName, Object.assign({ flowControl: {
|
|
52
51
|
maxMessages: (_c = config.maxMessages) !== null && _c !== void 0 ? _c : 5,
|
|
53
52
|
}, closeOptions: {
|
|
54
|
-
behavior:
|
|
55
|
-
timeout:
|
|
56
|
-
milliseconds: (
|
|
53
|
+
behavior: "WAIT",
|
|
54
|
+
timeout: (_d = (0, gcppubsub_helper_js_1.getGcpPubSubPackage)()) === null || _d === void 0 ? void 0 : _d.Duration.from({
|
|
55
|
+
milliseconds: (_e = config.shutdownDelay) !== null && _e !== void 0 ? _e : SHUTDOWN_DELAY,
|
|
57
56
|
}),
|
|
58
57
|
} }, config.subscriptionOptions));
|
|
59
58
|
const messageHandler = (message) => {
|
package/dist/interfaces.d.ts
CHANGED
|
@@ -1,22 +1,28 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
+
/**
|
|
3
|
+
* The schema for the metadata of a message. This is added by the publisher if not provided, but can also be provided by the publisher if they want to set specific values.
|
|
4
|
+
*/
|
|
2
5
|
export declare const MetaSchema: z.ZodObject<{
|
|
3
|
-
createdAt: z.ZodISODateTime
|
|
4
|
-
schemaId: z.ZodString
|
|
5
|
-
publishedBy: z.ZodString
|
|
6
|
+
createdAt: z.ZodOptional<z.ZodISODateTime>;
|
|
7
|
+
schemaId: z.ZodOptional<z.ZodString>;
|
|
8
|
+
publishedBy: z.ZodOptional<z.ZodString>;
|
|
6
9
|
}, z.core.$strip>;
|
|
10
|
+
/**
|
|
11
|
+
* The id and meta fields that are added to all messages by the publisher if not provided.
|
|
12
|
+
*/
|
|
7
13
|
export declare const IdMetaSchema: z.ZodObject<{
|
|
8
14
|
id: z.ZodOptional<z.ZodString>;
|
|
9
15
|
meta: z.ZodOptional<z.ZodObject<{
|
|
10
|
-
createdAt: z.ZodISODateTime
|
|
11
|
-
schemaId: z.ZodString
|
|
12
|
-
publishedBy: z.ZodString
|
|
16
|
+
createdAt: z.ZodOptional<z.ZodISODateTime>;
|
|
17
|
+
schemaId: z.ZodOptional<z.ZodString>;
|
|
18
|
+
publishedBy: z.ZodOptional<z.ZodString>;
|
|
13
19
|
}, z.core.$strip>>;
|
|
14
20
|
}, z.core.$strip>;
|
|
15
21
|
export type Meta = z.infer<typeof MetaSchema>;
|
|
16
22
|
/**
|
|
17
23
|
* All messages should be based on this schema
|
|
18
24
|
*/
|
|
19
|
-
export type BaseMessage = z.infer<typeof IdMetaSchema>;
|
|
25
|
+
export type BaseMessage = Record<string, unknown> & z.infer<typeof IdMetaSchema>;
|
|
20
26
|
export interface PublishMessageOptions {
|
|
21
27
|
/**
|
|
22
28
|
* The date and time at which the message should be published. Only supported by BullMq at this time.
|
package/dist/interfaces.js
CHANGED
|
@@ -2,13 +2,35 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.MessageResult = exports.IdMetaSchema = exports.MetaSchema = void 0;
|
|
4
4
|
const zod_1 = require("zod");
|
|
5
|
+
/**
|
|
6
|
+
* The schema for the metadata of a message. This is added by the publisher if not provided, but can also be provided by the publisher if they want to set specific values.
|
|
7
|
+
*/
|
|
5
8
|
exports.MetaSchema = zod_1.z.object({
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
+
/**
|
|
10
|
+
* The date and time at which the message was created.
|
|
11
|
+
*/
|
|
12
|
+
createdAt: zod_1.z.iso.datetime().optional(),
|
|
13
|
+
/**
|
|
14
|
+
* The unique identifier for the schema used by the message. Currently a hash of the JSON schema definition, but could be changed in the future to for example a UUID or a URL where the schema can be found.
|
|
15
|
+
*/
|
|
16
|
+
schemaId: zod_1.z.string().optional(),
|
|
17
|
+
/**
|
|
18
|
+
* The identifier of the entity that published the message. (currently an empty string, but could be used to identify the service that published the message)
|
|
19
|
+
*/
|
|
20
|
+
publishedBy: zod_1.z.string().optional(),
|
|
9
21
|
});
|
|
22
|
+
/**
|
|
23
|
+
* The id and meta fields that are added to all messages by the publisher if not provided.
|
|
24
|
+
*/
|
|
10
25
|
exports.IdMetaSchema = zod_1.z.object({
|
|
26
|
+
/**
|
|
27
|
+
* A unique identifier for the message. If not provided, one will be generated during publish.
|
|
28
|
+
*/
|
|
11
29
|
id: zod_1.z.string().optional(),
|
|
30
|
+
/**
|
|
31
|
+
* Metadata about the message, such as when it was created, which schema it uses, etc.
|
|
32
|
+
* This is optional when publishing a message, but will be added by the publisher if not provided.
|
|
33
|
+
*/
|
|
12
34
|
meta: exports.MetaSchema.optional(),
|
|
13
35
|
});
|
|
14
36
|
var MessageResult;
|
package/dist/publisher.js
CHANGED