@palmetto/pubsub 1.0.0 → 1.0.2
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/dist/bullmq/publisher.d.ts +1 -0
- package/dist/bullmq/publisher.js +5 -0
- package/dist/bullmq/pubsub.d.ts +1 -0
- package/dist/bullmq/pubsub.js +5 -0
- package/dist/interfaces.d.ts +1 -0
- package/dist/publisher.d.ts +3 -0
- package/dist/publisher.js +34 -14
- package/dist/rabbitmq/connection.d.ts +1 -0
- package/dist/rabbitmq/connection.js +3 -0
- package/dist/rabbitmq/publisher.d.ts +2 -2
- package/dist/rabbitmq/publisher.js +7 -2
- package/dist/rabbitmq/pubsub.d.ts +1 -0
- package/dist/rabbitmq/pubsub.js +5 -0
- package/package.json +4 -5
- package/src/rabbitmq/README.md +11 -3
|
@@ -9,5 +9,6 @@ export declare class BullMqPublisher implements PublisherProvider {
|
|
|
9
9
|
readonly transport: string;
|
|
10
10
|
private getQueue;
|
|
11
11
|
publish(config: BullMqQueueConfiguration, message: string): Promise<void>;
|
|
12
|
+
init(config: BullMqQueueConfiguration): Promise<void>;
|
|
12
13
|
close(): Promise<void>;
|
|
13
14
|
}
|
package/dist/bullmq/publisher.js
CHANGED
|
@@ -50,6 +50,11 @@ class BullMqPublisher {
|
|
|
50
50
|
});
|
|
51
51
|
});
|
|
52
52
|
}
|
|
53
|
+
init(config) {
|
|
54
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
55
|
+
yield this.getQueue(config);
|
|
56
|
+
});
|
|
57
|
+
}
|
|
53
58
|
close() {
|
|
54
59
|
return __awaiter(this, void 0, void 0, function* () {
|
|
55
60
|
for (const queue of this.queues.values()) {
|
package/dist/bullmq/pubsub.d.ts
CHANGED
|
@@ -9,4 +9,5 @@ export declare class BullMqPubSubProvider implements PubSubProvider {
|
|
|
9
9
|
publish(config: BullMqQueueConfiguration, message: string): Promise<void>;
|
|
10
10
|
startSubscribe(config: BullMqQueueConfiguration, onMessage: (s: string, context: MessageContext) => Promise<MessageResult> | MessageResult): Promise<StopSubscribe>;
|
|
11
11
|
close(): Promise<void>;
|
|
12
|
+
init(config: BullMqQueueConfiguration): Promise<void>;
|
|
12
13
|
}
|
package/dist/bullmq/pubsub.js
CHANGED
|
@@ -31,5 +31,10 @@ class BullMqPubSubProvider {
|
|
|
31
31
|
yield this.publisher.close();
|
|
32
32
|
});
|
|
33
33
|
}
|
|
34
|
+
init(config) {
|
|
35
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
36
|
+
yield this.publisher.init(config);
|
|
37
|
+
});
|
|
38
|
+
}
|
|
34
39
|
}
|
|
35
40
|
exports.BullMqPubSubProvider = BullMqPubSubProvider;
|
package/dist/interfaces.d.ts
CHANGED
|
@@ -22,6 +22,7 @@ export type BaseMessage = z4.infer<typeof IdMetaSchema>;
|
|
|
22
22
|
*/
|
|
23
23
|
export interface PublisherProvider {
|
|
24
24
|
transport: string;
|
|
25
|
+
init(config: PubSubConfiguration): Promise<void> | void;
|
|
25
26
|
publish(config: PubSubConfiguration, message: string): Promise<void> | void;
|
|
26
27
|
close(): Promise<void> | void;
|
|
27
28
|
}
|
package/dist/publisher.d.ts
CHANGED
|
@@ -6,6 +6,9 @@ export declare class Publisher {
|
|
|
6
6
|
constructor(logger: Logger, providers?: PublisherProvider[]);
|
|
7
7
|
addProvider(provider: PublisherProvider): void;
|
|
8
8
|
removeProvider(providerOrTransport: PublisherProvider | string): boolean;
|
|
9
|
+
init(config: PubSubConfiguration): Promise<void>;
|
|
9
10
|
publish(config: PubSubConfiguration, message: BaseMessage): Promise<void>;
|
|
10
11
|
close(): Promise<void>;
|
|
12
|
+
private getProvider;
|
|
13
|
+
private assertSchema;
|
|
11
14
|
}
|
package/dist/publisher.js
CHANGED
|
@@ -40,39 +40,36 @@ class Publisher {
|
|
|
40
40
|
(_b = (_a = this.logger).debug) === null || _b === void 0 ? void 0 : _b.call(_a, `Publisher removing provider for ${transport}`);
|
|
41
41
|
return this.publisherProviders.delete(transport);
|
|
42
42
|
}
|
|
43
|
+
init(config) {
|
|
44
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
45
|
+
yield this.getProvider(config).init(config);
|
|
46
|
+
yield this.assertSchema(config);
|
|
47
|
+
});
|
|
48
|
+
}
|
|
43
49
|
publish(config, message) {
|
|
44
50
|
return __awaiter(this, void 0, void 0, function* () {
|
|
45
51
|
var _a, _b;
|
|
46
|
-
const
|
|
47
|
-
const provider = this.publisherProviders.get(transport);
|
|
48
|
-
if (!provider) {
|
|
49
|
-
throw new errors_1.MissingPubSubProviderError(`No provider configured for ${transport}`);
|
|
50
|
-
}
|
|
52
|
+
const provider = this.getProvider(config);
|
|
51
53
|
if (!message.id) {
|
|
52
54
|
message.id = (0, uuid_1.v4)();
|
|
53
55
|
}
|
|
54
|
-
|
|
55
|
-
if (!hash) {
|
|
56
|
-
const jsonSchema = JSON.stringify(v4_1.z.toJSONSchema(schema), null, 3);
|
|
57
|
-
hash = yield (0, crypto_hash_1.sha256)(jsonSchema);
|
|
58
|
-
this.hashes.set(schema, hash);
|
|
59
|
-
}
|
|
56
|
+
const { schema, schemaId } = yield this.assertSchema(config);
|
|
60
57
|
if (!message.meta) {
|
|
61
58
|
message.meta = {
|
|
62
59
|
createdAt: new Date().toISOString(),
|
|
63
60
|
publishedBy: "",
|
|
64
|
-
schemaId:
|
|
61
|
+
schemaId: schemaId,
|
|
65
62
|
};
|
|
66
63
|
}
|
|
67
64
|
else {
|
|
68
|
-
message.meta.schemaId =
|
|
65
|
+
message.meta.schemaId = schemaId;
|
|
69
66
|
}
|
|
70
67
|
const json = JSON.stringify(message);
|
|
71
68
|
const check = schema.safeParse(JSON.parse(json));
|
|
72
69
|
if (!check.success) {
|
|
73
70
|
throw new errors_1.SchemaValidationError(`Schema did not accept the published message: ${check.error.message}`);
|
|
74
71
|
}
|
|
75
|
-
(_b = (_a = this.logger).debug) === null || _b === void 0 ? void 0 : _b.call(_a, `Publisher publishing message for ${transport}`);
|
|
72
|
+
(_b = (_a = this.logger).debug) === null || _b === void 0 ? void 0 : _b.call(_a, `Publisher publishing message for ${provider.transport}`);
|
|
76
73
|
yield provider.publish(config, json);
|
|
77
74
|
});
|
|
78
75
|
}
|
|
@@ -83,5 +80,28 @@ class Publisher {
|
|
|
83
80
|
}
|
|
84
81
|
});
|
|
85
82
|
}
|
|
83
|
+
getProvider(config) {
|
|
84
|
+
const { transport } = config;
|
|
85
|
+
const provider = this.publisherProviders.get(transport);
|
|
86
|
+
if (!provider) {
|
|
87
|
+
throw new errors_1.MissingPubSubProviderError(`No provider configured for ${transport}`);
|
|
88
|
+
}
|
|
89
|
+
return provider;
|
|
90
|
+
}
|
|
91
|
+
assertSchema(config) {
|
|
92
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
93
|
+
const { schema } = config;
|
|
94
|
+
let hash = this.hashes.get(schema);
|
|
95
|
+
if (!hash) {
|
|
96
|
+
const jsonSchema = JSON.stringify(v4_1.z.toJSONSchema(schema), null, 3);
|
|
97
|
+
hash = yield (0, crypto_hash_1.sha256)(jsonSchema);
|
|
98
|
+
this.hashes.set(schema, hash);
|
|
99
|
+
}
|
|
100
|
+
return {
|
|
101
|
+
schema,
|
|
102
|
+
schemaId: hash,
|
|
103
|
+
};
|
|
104
|
+
});
|
|
105
|
+
}
|
|
86
106
|
}
|
|
87
107
|
exports.Publisher = Publisher;
|
|
@@ -18,6 +18,7 @@ export declare class RabbitMqConnection {
|
|
|
18
18
|
static create(config: RabbitMqConnectionConfig, logger: Logger): Promise<RabbitMqConnection>;
|
|
19
19
|
private constructor();
|
|
20
20
|
close(): Promise<void>;
|
|
21
|
+
isConnected(): boolean;
|
|
21
22
|
/**
|
|
22
23
|
* Creates the exchanges necessary for the given config
|
|
23
24
|
* @param channel
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import type { ChannelWrapper } from "amqp-connection-manager";
|
|
2
1
|
import { Logger, PublisherProvider } from "../interfaces";
|
|
3
2
|
import { RabbitMqConnection } from "./connection";
|
|
4
3
|
import { RabbitQueueExchangeConfiguration } from "./config";
|
|
@@ -10,13 +9,14 @@ export declare class RabbitMqPublisher implements PublisherProvider {
|
|
|
10
9
|
private connected;
|
|
11
10
|
constructor(connection: RabbitMqConnection, logger: Logger);
|
|
12
11
|
readonly transport: string;
|
|
12
|
+
init(config: RabbitQueueExchangeConfiguration): Promise<void>;
|
|
13
13
|
/**
|
|
14
14
|
* Initializes the rabbit connection and asserts the exchange for the configuration.
|
|
15
15
|
*
|
|
16
16
|
* @param config
|
|
17
17
|
* @returns a Promise containing the ChannelWrapper to publish messages with
|
|
18
18
|
*/
|
|
19
|
-
|
|
19
|
+
private getChannel;
|
|
20
20
|
/**
|
|
21
21
|
* Publishes a message to Rabbit based on the configuration
|
|
22
22
|
*
|
|
@@ -22,13 +22,18 @@ class RabbitMqPublisher {
|
|
|
22
22
|
this.connected = false;
|
|
23
23
|
this.transport = connection_1.RABBITMQ_TRANSPORT;
|
|
24
24
|
}
|
|
25
|
+
init(config) {
|
|
26
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
27
|
+
yield this.getChannel(config);
|
|
28
|
+
});
|
|
29
|
+
}
|
|
25
30
|
/**
|
|
26
31
|
* Initializes the rabbit connection and asserts the exchange for the configuration.
|
|
27
32
|
*
|
|
28
33
|
* @param config
|
|
29
34
|
* @returns a Promise containing the ChannelWrapper to publish messages with
|
|
30
35
|
*/
|
|
31
|
-
|
|
36
|
+
getChannel(config) {
|
|
32
37
|
return __awaiter(this, void 0, void 0, function* () {
|
|
33
38
|
var _a, _b, _c, _d;
|
|
34
39
|
const delayMs = this.connection.config.startupRetryDelayMs || 500;
|
|
@@ -76,7 +81,7 @@ class RabbitMqPublisher {
|
|
|
76
81
|
publish(config, message) {
|
|
77
82
|
return __awaiter(this, void 0, void 0, function* () {
|
|
78
83
|
var _a, _b, _c, _d;
|
|
79
|
-
const channel = yield this.
|
|
84
|
+
const channel = yield this.getChannel(config);
|
|
80
85
|
(_b = (_a = this.logger).debug) === null || _b === void 0 ? void 0 : _b.call(_a, `Publishing message to ${(0, config_1.getExchangeName)(config)} - ${message} [starting]`);
|
|
81
86
|
const exchangeName = (0, config_1.getExchangeName)(config);
|
|
82
87
|
const ok = yield channel.publish(exchangeName, (0, config_1.getRoutingKey)(config), Buffer.from(message, "utf8"), {
|
|
@@ -12,4 +12,5 @@ export declare class RabbitMqPubSubProvider implements PubSubProvider {
|
|
|
12
12
|
publish(config: RabbitQueueExchangeConfiguration, message: string): Promise<void>;
|
|
13
13
|
startSubscribe(config: RabbitQueueExchangeConfiguration, onMessage: (s: string, context: MessageContext) => Promise<MessageResult> | MessageResult): StopSubscribe;
|
|
14
14
|
close(): Promise<void>;
|
|
15
|
+
init(config: RabbitQueueExchangeConfiguration): Promise<void>;
|
|
15
16
|
}
|
package/dist/rabbitmq/pubsub.js
CHANGED
|
@@ -33,5 +33,10 @@ class RabbitMqPubSubProvider {
|
|
|
33
33
|
yield Promise.all([this.subscriber.close(), this.publisher.close()]);
|
|
34
34
|
});
|
|
35
35
|
}
|
|
36
|
+
init(config) {
|
|
37
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
38
|
+
yield this.publisher.init(config);
|
|
39
|
+
});
|
|
40
|
+
}
|
|
36
41
|
}
|
|
37
42
|
exports.RabbitMqPubSubProvider = RabbitMqPubSubProvider;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@palmetto/pubsub",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"main": "./dist/main.js",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"lint": "yarn run -T eslint --fix ./src",
|
|
@@ -15,10 +15,9 @@
|
|
|
15
15
|
"hook:format": "prettier --write --loglevel warn",
|
|
16
16
|
"hook:tc": "yarn tc",
|
|
17
17
|
"prepublishOnly": "yarn build",
|
|
18
|
-
"test": "
|
|
19
|
-
"test
|
|
20
|
-
"
|
|
21
|
-
"rabbitmq-up": "docker compose -f rabbitmq-compose.yml up -d"
|
|
18
|
+
"test-runner": "../../scripts/test-runner.sh",
|
|
19
|
+
"test": "yarn run test-runner vitest run",
|
|
20
|
+
"test:watch": "yarn run test-runner vitest watch"
|
|
22
21
|
},
|
|
23
22
|
"devDependencies": {
|
|
24
23
|
"@types/amqplib": "^0",
|
package/src/rabbitmq/README.md
CHANGED
|
@@ -52,7 +52,15 @@ yarn add @palmetto/pubsub amqp-connection-manager amqplib zod
|
|
|
52
52
|
};
|
|
53
53
|
```
|
|
54
54
|
|
|
55
|
-
6.
|
|
55
|
+
6. Initialize the publisher
|
|
56
|
+
|
|
57
|
+
For performance reasons, it's a good idea to initialize the publisher on your API startup. This can reduce the latency for the first message published.
|
|
58
|
+
|
|
59
|
+
```ts
|
|
60
|
+
await publisher.init(config);
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
7. Publish a message
|
|
56
64
|
|
|
57
65
|
```ts
|
|
58
66
|
const message: MyModel = {... };
|
|
@@ -60,7 +68,7 @@ yarn add @palmetto/pubsub amqp-connection-manager amqplib zod
|
|
|
60
68
|
await publisher.publish(config, message);
|
|
61
69
|
```
|
|
62
70
|
|
|
63
|
-
|
|
71
|
+
8. Subscribe to a queue
|
|
64
72
|
|
|
65
73
|
```ts
|
|
66
74
|
subscriber.addSubscriber(queue, (message: MyModel, context: RabbitMqMessageContext) => {
|
|
@@ -69,7 +77,7 @@ yarn add @palmetto/pubsub amqp-connection-manager amqplib zod
|
|
|
69
77
|
});
|
|
70
78
|
```
|
|
71
79
|
|
|
72
|
-
|
|
80
|
+
9. Subscribe to the dead-letter queue if you want to re-process completely failed messages. Set the `queueType` to `"dead-letter"`
|
|
73
81
|
|
|
74
82
|
```ts
|
|
75
83
|
const dlQueue = {
|