@mastra/google-cloud-pubsub 0.1.1 → 0.1.2-alpha.1
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/CHANGELOG.md +18 -0
- package/package.json +20 -7
- package/.turbo/turbo-build.log +0 -26
- package/dist/_tsup-dts-rollup.d.cts +0 -27
- package/dist/_tsup-dts-rollup.d.ts +0 -27
- package/dist/index.d.cts +0 -1
- package/eslint.config.js +0 -6
- package/src/index.test.ts +0 -8055
- package/src/index.ts +0 -168
- package/tsconfig.build.json +0 -9
- package/tsconfig.json +0 -5
- package/tsup.config.ts +0 -17
- package/vitest.config.ts +0 -14
package/src/index.ts
DELETED
|
@@ -1,168 +0,0 @@
|
|
|
1
|
-
import { PubSub as PubSubClient } from '@google-cloud/pubsub';
|
|
2
|
-
import type { ClientConfig, Message, Subscription } from '@google-cloud/pubsub';
|
|
3
|
-
import { PubSub } from '@mastra/core/events';
|
|
4
|
-
import type { Event } from '@mastra/core/events';
|
|
5
|
-
|
|
6
|
-
export class GoogleCloudPubSub extends PubSub {
|
|
7
|
-
private instanceId: string;
|
|
8
|
-
private pubsub: PubSubClient;
|
|
9
|
-
private ackBuffer: Record<string, Promise<any>> = {};
|
|
10
|
-
private activeSubscriptions: Record<string, Subscription> = {};
|
|
11
|
-
private activeCbs: Record<string, Set<(event: Event, ack: () => Promise<void>) => void>> = {};
|
|
12
|
-
|
|
13
|
-
constructor(config: ClientConfig) {
|
|
14
|
-
super();
|
|
15
|
-
this.pubsub = new PubSubClient(config);
|
|
16
|
-
this.instanceId = crypto.randomUUID();
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
getSubscriptionName(topic: string) {
|
|
20
|
-
return `${topic}-${this.instanceId}`;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
async ackMessage(topic: string, message: Message) {
|
|
24
|
-
try {
|
|
25
|
-
const ackResponse = Promise.race([message.ackWithResponse(), new Promise(resolve => setTimeout(resolve, 5000))]);
|
|
26
|
-
this.ackBuffer[topic + '-' + message.id] = ackResponse.catch(() => {});
|
|
27
|
-
await ackResponse;
|
|
28
|
-
delete this.ackBuffer[topic + '-' + message.id];
|
|
29
|
-
} catch (e) {
|
|
30
|
-
console.error('Error acking message', e);
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
async init(topicName: string) {
|
|
35
|
-
try {
|
|
36
|
-
await this.pubsub.createTopic(topicName);
|
|
37
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
38
|
-
} catch (error) {
|
|
39
|
-
// no-op
|
|
40
|
-
}
|
|
41
|
-
try {
|
|
42
|
-
const [sub] = await this.pubsub.topic(topicName).createSubscription(this.getSubscriptionName(topicName), {
|
|
43
|
-
enableMessageOrdering: true,
|
|
44
|
-
enableExactlyOnceDelivery: topicName === 'workflows' ? true : false,
|
|
45
|
-
});
|
|
46
|
-
this.activeSubscriptions[topicName] = sub;
|
|
47
|
-
return sub;
|
|
48
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
49
|
-
} catch (error) {
|
|
50
|
-
// no-op
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
return undefined;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
async destroy(topicName: string) {
|
|
57
|
-
const subName = this.getSubscriptionName(topicName);
|
|
58
|
-
delete this.activeSubscriptions[topicName];
|
|
59
|
-
this.pubsub.subscription(subName).removeAllListeners();
|
|
60
|
-
await this.pubsub.subscription(subName).close();
|
|
61
|
-
await this.pubsub.subscription(subName).delete();
|
|
62
|
-
await this.pubsub.topic(topicName).delete();
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
async publish(topicName: string, event: Omit<Event, 'id' | 'createdAt'>): Promise<void> {
|
|
66
|
-
if (topicName.startsWith('workflow.events.')) {
|
|
67
|
-
const parts = topicName.split('.');
|
|
68
|
-
if (parts[parts.length - 2] === 'v2') {
|
|
69
|
-
topicName = 'workflow.events.v2';
|
|
70
|
-
} else {
|
|
71
|
-
topicName = 'workflow.events.v1';
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
let topic = this.pubsub.topic(topicName);
|
|
76
|
-
|
|
77
|
-
try {
|
|
78
|
-
await topic.publishMessage({
|
|
79
|
-
data: Buffer.from(JSON.stringify(event)),
|
|
80
|
-
orderingKey: 'workflows',
|
|
81
|
-
});
|
|
82
|
-
} catch (e: any) {
|
|
83
|
-
if (e.code === 5) {
|
|
84
|
-
await this.pubsub.createTopic(topicName);
|
|
85
|
-
await this.publish(topicName, event);
|
|
86
|
-
} else {
|
|
87
|
-
throw e;
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
async subscribe(topic: string, cb: (event: Event, ack?: () => Promise<void>) => void): Promise<void> {
|
|
93
|
-
if (topic.startsWith('workflow.events.')) {
|
|
94
|
-
const parts = topic.split('.');
|
|
95
|
-
if (parts[parts.length - 2] === 'v2') {
|
|
96
|
-
topic = 'workflow.events.v2';
|
|
97
|
-
} else {
|
|
98
|
-
topic = 'workflow.events.v1';
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
// Update tracked callbacks
|
|
103
|
-
const subscription = this.activeSubscriptions[topic] ?? (await this.init(topic));
|
|
104
|
-
if (!subscription) {
|
|
105
|
-
throw new Error(`Failed to subscribe to topic: ${topic}`);
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
this.activeSubscriptions[topic] = subscription;
|
|
109
|
-
|
|
110
|
-
const activeCbs = this.activeCbs[topic] ?? new Set();
|
|
111
|
-
activeCbs.add(cb);
|
|
112
|
-
this.activeCbs[topic] = activeCbs;
|
|
113
|
-
|
|
114
|
-
if (subscription.isOpen) {
|
|
115
|
-
return;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
subscription.on('message', async message => {
|
|
119
|
-
const event = JSON.parse(message.data.toString()) as Event;
|
|
120
|
-
event.id = message.id;
|
|
121
|
-
event.createdAt = message.publishTime;
|
|
122
|
-
|
|
123
|
-
try {
|
|
124
|
-
const activeCbs = this.activeCbs[topic] ?? [];
|
|
125
|
-
for (const cb of activeCbs) {
|
|
126
|
-
cb(event, async () => {
|
|
127
|
-
try {
|
|
128
|
-
await this.ackMessage(topic, message);
|
|
129
|
-
} catch (e) {
|
|
130
|
-
console.error('Error acking message', e);
|
|
131
|
-
}
|
|
132
|
-
});
|
|
133
|
-
}
|
|
134
|
-
} catch (error) {
|
|
135
|
-
console.error('Error processing event', error);
|
|
136
|
-
}
|
|
137
|
-
});
|
|
138
|
-
|
|
139
|
-
subscription.on('error', async error => {
|
|
140
|
-
// if (error.code === 5) {
|
|
141
|
-
// await this.init(topic);
|
|
142
|
-
// } else {
|
|
143
|
-
// // TODO: determine if other errors require re-subscription
|
|
144
|
-
// // console.error('subscription error, retrying in 5 seconds', error);
|
|
145
|
-
// // await new Promise(resolve => setTimeout(resolve, 5000));
|
|
146
|
-
// // await this.subscribe(topic, cb);
|
|
147
|
-
// console.error('subscription error', error);
|
|
148
|
-
// }
|
|
149
|
-
console.error('subscription error', error);
|
|
150
|
-
});
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
async unsubscribe(topic: string, cb: (event: Event, ack?: () => Promise<void>) => void): Promise<void> {
|
|
154
|
-
const subscription = this.activeSubscriptions[topic] ?? this.pubsub.subscription(this.getSubscriptionName(topic));
|
|
155
|
-
const activeCbs = this.activeCbs[topic] ?? new Set();
|
|
156
|
-
activeCbs.delete(cb);
|
|
157
|
-
this.activeCbs[topic] = activeCbs;
|
|
158
|
-
|
|
159
|
-
if (activeCbs.size === 0) {
|
|
160
|
-
subscription.removeListener('message', cb);
|
|
161
|
-
await subscription.close();
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
async flush(): Promise<void> {
|
|
166
|
-
await Promise.all(Object.values(this.ackBuffer));
|
|
167
|
-
}
|
|
168
|
-
}
|
package/tsconfig.build.json
DELETED
package/tsconfig.json
DELETED
package/tsup.config.ts
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { generateTypes } from '@internal/types-builder';
|
|
2
|
-
import { defineConfig } from 'tsup';
|
|
3
|
-
|
|
4
|
-
export default defineConfig({
|
|
5
|
-
entry: ['src/index.ts'],
|
|
6
|
-
format: ['esm', 'cjs'],
|
|
7
|
-
clean: true,
|
|
8
|
-
dts: false,
|
|
9
|
-
splitting: true,
|
|
10
|
-
treeshake: {
|
|
11
|
-
preset: 'smallest',
|
|
12
|
-
},
|
|
13
|
-
sourcemap: true,
|
|
14
|
-
onSuccess: async () => {
|
|
15
|
-
await generateTypes(process.cwd());
|
|
16
|
-
},
|
|
17
|
-
});
|
package/vitest.config.ts
DELETED