@hatchet-dev/typescript-sdk 1.34.0-alpha.2 → 1.34.0
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 +1 -0
- package/package.json +1 -1
- package/protoc/v1/streams.d.ts +79 -0
- package/protoc/v1/streams.js +511 -0
- package/protoc-es/v1/streams_pb.d.ts +133 -0
- package/protoc-es/v1/streams_pb.js +41 -0
- package/v1/client/client.d.ts +8 -1
- package/v1/client/client.js +11 -0
- package/v1/client/features/index.d.ts +1 -0
- package/v1/client/features/index.js +1 -0
- package/v1/client/features/streams.d.ts +47 -0
- package/v1/client/features/streams.js +210 -0
- package/v1/examples/durable-streams/publish-latency.d.ts +15 -0
- package/v1/examples/durable-streams/publish-latency.js +50 -0
- package/v1/examples/durable_callback_ordering/workflow.js +5 -1
- package/version.d.ts +1 -1
- package/version.js +1 -1
package/README.md
CHANGED
|
@@ -49,6 +49,7 @@ TypeScript SDK reference (overview: https://docs.hatchet.run/reference/typescrip
|
|
|
49
49
|
- Rate Limits: https://docs.hatchet.run/reference/typescript/feature-clients/ratelimits.md (guide: https://docs.hatchet.run/v1/rate-limits.md)
|
|
50
50
|
- Runs: https://docs.hatchet.run/reference/typescript/feature-clients/runs.md (guide: https://docs.hatchet.run/v1/running-your-task.md)
|
|
51
51
|
- Scheduled Runs: https://docs.hatchet.run/reference/typescript/feature-clients/schedules.md (guide: https://docs.hatchet.run/v1/scheduled-runs.md)
|
|
52
|
+
- Streams: https://docs.hatchet.run/reference/typescript/feature-clients/streams.md
|
|
52
53
|
- Tenant: https://docs.hatchet.run/reference/typescript/feature-clients/tenant.md
|
|
53
54
|
- Webhooks: https://docs.hatchet.run/reference/typescript/feature-clients/webhooks.md (guide: https://docs.hatchet.run/v1/webhooks.md)
|
|
54
55
|
- Workers: https://docs.hatchet.run/reference/typescript/feature-clients/workers.md (guide: https://docs.hatchet.run/v1/workers.md)
|
package/package.json
CHANGED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { BinaryReader, BinaryWriter } from '@bufbuild/protobuf/wire';
|
|
2
|
+
import type { CallContext, CallOptions } from 'nice-grpc-common';
|
|
3
|
+
export declare const protobufPackage = "v1";
|
|
4
|
+
export interface PublishStreamMessageRequest {
|
|
5
|
+
namespace: string;
|
|
6
|
+
topic: string;
|
|
7
|
+
payload: Uint8Array;
|
|
8
|
+
producerId: string;
|
|
9
|
+
producerSeq: number;
|
|
10
|
+
}
|
|
11
|
+
export interface PublishStreamMessageResponse {
|
|
12
|
+
}
|
|
13
|
+
export interface SubscribeStreamRequest {
|
|
14
|
+
namespace: string;
|
|
15
|
+
topic: string;
|
|
16
|
+
cursor?: string | undefined;
|
|
17
|
+
}
|
|
18
|
+
export interface StreamMessage {
|
|
19
|
+
entries: StreamEntry[];
|
|
20
|
+
hangup: boolean;
|
|
21
|
+
cursor: string;
|
|
22
|
+
}
|
|
23
|
+
export interface StreamEntry {
|
|
24
|
+
payload: Uint8Array;
|
|
25
|
+
cursor: string;
|
|
26
|
+
createdAt: Date | undefined;
|
|
27
|
+
}
|
|
28
|
+
export declare const PublishStreamMessageRequest: MessageFns<PublishStreamMessageRequest>;
|
|
29
|
+
export declare const PublishStreamMessageResponse: MessageFns<PublishStreamMessageResponse>;
|
|
30
|
+
export declare const SubscribeStreamRequest: MessageFns<SubscribeStreamRequest>;
|
|
31
|
+
export declare const StreamMessage: MessageFns<StreamMessage>;
|
|
32
|
+
export declare const StreamEntry: MessageFns<StreamEntry>;
|
|
33
|
+
export type V1StreamsDefinition = typeof V1StreamsDefinition;
|
|
34
|
+
export declare const V1StreamsDefinition: {
|
|
35
|
+
readonly name: "V1Streams";
|
|
36
|
+
readonly fullName: "v1.V1Streams";
|
|
37
|
+
readonly methods: {
|
|
38
|
+
readonly publish: {
|
|
39
|
+
readonly name: "Publish";
|
|
40
|
+
readonly requestType: typeof PublishStreamMessageRequest;
|
|
41
|
+
readonly requestStream: false;
|
|
42
|
+
readonly responseType: typeof PublishStreamMessageResponse;
|
|
43
|
+
readonly responseStream: false;
|
|
44
|
+
readonly options: {};
|
|
45
|
+
};
|
|
46
|
+
readonly subscribe: {
|
|
47
|
+
readonly name: "Subscribe";
|
|
48
|
+
readonly requestType: typeof SubscribeStreamRequest;
|
|
49
|
+
readonly requestStream: false;
|
|
50
|
+
readonly responseType: typeof StreamMessage;
|
|
51
|
+
readonly responseStream: true;
|
|
52
|
+
readonly options: {};
|
|
53
|
+
};
|
|
54
|
+
};
|
|
55
|
+
};
|
|
56
|
+
export interface V1StreamsServiceImplementation<CallContextExt = {}> {
|
|
57
|
+
publish(request: PublishStreamMessageRequest, context: CallContext & CallContextExt): Promise<DeepPartial<PublishStreamMessageResponse>>;
|
|
58
|
+
subscribe(request: SubscribeStreamRequest, context: CallContext & CallContextExt): ServerStreamingMethodResult<DeepPartial<StreamMessage>>;
|
|
59
|
+
}
|
|
60
|
+
export interface V1StreamsClient<CallOptionsExt = {}> {
|
|
61
|
+
publish(request: DeepPartial<PublishStreamMessageRequest>, options?: CallOptions & CallOptionsExt): Promise<PublishStreamMessageResponse>;
|
|
62
|
+
subscribe(request: DeepPartial<SubscribeStreamRequest>, options?: CallOptions & CallOptionsExt): AsyncIterable<StreamMessage>;
|
|
63
|
+
}
|
|
64
|
+
type Builtin = Date | Function | Uint8Array | string | number | boolean | undefined;
|
|
65
|
+
export type DeepPartial<T> = T extends Builtin ? T : T extends globalThis.Array<infer U> ? globalThis.Array<DeepPartial<U>> : T extends ReadonlyArray<infer U> ? ReadonlyArray<DeepPartial<U>> : T extends {} ? {
|
|
66
|
+
[K in keyof T]?: DeepPartial<T[K]>;
|
|
67
|
+
} : Partial<T>;
|
|
68
|
+
export type ServerStreamingMethodResult<Response> = {
|
|
69
|
+
[Symbol.asyncIterator](): AsyncIterator<Response, void>;
|
|
70
|
+
};
|
|
71
|
+
export interface MessageFns<T> {
|
|
72
|
+
encode(message: T, writer?: BinaryWriter): BinaryWriter;
|
|
73
|
+
decode(input: BinaryReader | Uint8Array, length?: number): T;
|
|
74
|
+
fromJSON(object: any): T;
|
|
75
|
+
toJSON(message: T): unknown;
|
|
76
|
+
create(base?: DeepPartial<T>): T;
|
|
77
|
+
fromPartial(object: DeepPartial<T>): T;
|
|
78
|
+
}
|
|
79
|
+
export {};
|
|
@@ -0,0 +1,511 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Code generated by protoc-gen-ts_proto. DO NOT EDIT.
|
|
3
|
+
// versions:
|
|
4
|
+
// protoc-gen-ts_proto v2.12.0
|
|
5
|
+
// protoc v3.19.1
|
|
6
|
+
// source: v1/streams.proto
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.V1StreamsDefinition = exports.StreamEntry = exports.StreamMessage = exports.SubscribeStreamRequest = exports.PublishStreamMessageResponse = exports.PublishStreamMessageRequest = exports.protobufPackage = void 0;
|
|
9
|
+
/* eslint-disable */
|
|
10
|
+
const wire_1 = require("@bufbuild/protobuf/wire");
|
|
11
|
+
const timestamp_1 = require("../google/protobuf/timestamp");
|
|
12
|
+
exports.protobufPackage = 'v1';
|
|
13
|
+
function createBasePublishStreamMessageRequest() {
|
|
14
|
+
return { namespace: '', topic: '', payload: new Uint8Array(0), producerId: '', producerSeq: 0 };
|
|
15
|
+
}
|
|
16
|
+
exports.PublishStreamMessageRequest = {
|
|
17
|
+
encode(message, writer = new wire_1.BinaryWriter()) {
|
|
18
|
+
if (message.namespace !== '') {
|
|
19
|
+
writer.uint32(10).string(message.namespace);
|
|
20
|
+
}
|
|
21
|
+
if (message.topic !== '') {
|
|
22
|
+
writer.uint32(18).string(message.topic);
|
|
23
|
+
}
|
|
24
|
+
if (message.payload.length !== 0) {
|
|
25
|
+
writer.uint32(26).bytes(message.payload);
|
|
26
|
+
}
|
|
27
|
+
if (message.producerId !== '') {
|
|
28
|
+
writer.uint32(34).string(message.producerId);
|
|
29
|
+
}
|
|
30
|
+
if (message.producerSeq !== 0) {
|
|
31
|
+
writer.uint32(40).int64(message.producerSeq);
|
|
32
|
+
}
|
|
33
|
+
return writer;
|
|
34
|
+
},
|
|
35
|
+
decode(input, length) {
|
|
36
|
+
const reader = input instanceof wire_1.BinaryReader ? input : new wire_1.BinaryReader(input);
|
|
37
|
+
const end = length === undefined ? reader.len : reader.pos + length;
|
|
38
|
+
const message = createBasePublishStreamMessageRequest();
|
|
39
|
+
while (reader.pos < end) {
|
|
40
|
+
const tag = reader.uint32();
|
|
41
|
+
switch (tag >>> 3) {
|
|
42
|
+
case 1: {
|
|
43
|
+
if (tag !== 10) {
|
|
44
|
+
break;
|
|
45
|
+
}
|
|
46
|
+
message.namespace = reader.string();
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
case 2: {
|
|
50
|
+
if (tag !== 18) {
|
|
51
|
+
break;
|
|
52
|
+
}
|
|
53
|
+
message.topic = reader.string();
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
case 3: {
|
|
57
|
+
if (tag !== 26) {
|
|
58
|
+
break;
|
|
59
|
+
}
|
|
60
|
+
message.payload = reader.bytes();
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
case 4: {
|
|
64
|
+
if (tag !== 34) {
|
|
65
|
+
break;
|
|
66
|
+
}
|
|
67
|
+
message.producerId = reader.string();
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
case 5: {
|
|
71
|
+
if (tag !== 40) {
|
|
72
|
+
break;
|
|
73
|
+
}
|
|
74
|
+
message.producerSeq = longToNumber(reader.int64());
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
if ((tag & 7) === 4 || tag === 0) {
|
|
79
|
+
break;
|
|
80
|
+
}
|
|
81
|
+
reader.skip(tag & 7);
|
|
82
|
+
}
|
|
83
|
+
return message;
|
|
84
|
+
},
|
|
85
|
+
fromJSON(object) {
|
|
86
|
+
return {
|
|
87
|
+
namespace: isSet(object.namespace) ? globalThis.String(object.namespace) : '',
|
|
88
|
+
topic: isSet(object.topic) ? globalThis.String(object.topic) : '',
|
|
89
|
+
payload: isSet(object.payload) ? bytesFromBase64(object.payload) : new Uint8Array(0),
|
|
90
|
+
producerId: isSet(object.producerId)
|
|
91
|
+
? globalThis.String(object.producerId)
|
|
92
|
+
: isSet(object.producer_id)
|
|
93
|
+
? globalThis.String(object.producer_id)
|
|
94
|
+
: '',
|
|
95
|
+
producerSeq: isSet(object.producerSeq)
|
|
96
|
+
? globalThis.Number(object.producerSeq)
|
|
97
|
+
: isSet(object.producer_seq)
|
|
98
|
+
? globalThis.Number(object.producer_seq)
|
|
99
|
+
: 0,
|
|
100
|
+
};
|
|
101
|
+
},
|
|
102
|
+
toJSON(message) {
|
|
103
|
+
const obj = {};
|
|
104
|
+
if (message.namespace !== '') {
|
|
105
|
+
obj.namespace = message.namespace;
|
|
106
|
+
}
|
|
107
|
+
if (message.topic !== '') {
|
|
108
|
+
obj.topic = message.topic;
|
|
109
|
+
}
|
|
110
|
+
if (message.payload.length !== 0) {
|
|
111
|
+
obj.payload = base64FromBytes(message.payload);
|
|
112
|
+
}
|
|
113
|
+
if (message.producerId !== '') {
|
|
114
|
+
obj.producerId = message.producerId;
|
|
115
|
+
}
|
|
116
|
+
if (message.producerSeq !== 0) {
|
|
117
|
+
obj.producerSeq = Math.round(message.producerSeq);
|
|
118
|
+
}
|
|
119
|
+
return obj;
|
|
120
|
+
},
|
|
121
|
+
create(base) {
|
|
122
|
+
return exports.PublishStreamMessageRequest.fromPartial(base !== null && base !== void 0 ? base : {});
|
|
123
|
+
},
|
|
124
|
+
fromPartial(object) {
|
|
125
|
+
var _a, _b, _c, _d, _e;
|
|
126
|
+
const message = createBasePublishStreamMessageRequest();
|
|
127
|
+
message.namespace = (_a = object.namespace) !== null && _a !== void 0 ? _a : '';
|
|
128
|
+
message.topic = (_b = object.topic) !== null && _b !== void 0 ? _b : '';
|
|
129
|
+
message.payload = (_c = object.payload) !== null && _c !== void 0 ? _c : new Uint8Array(0);
|
|
130
|
+
message.producerId = (_d = object.producerId) !== null && _d !== void 0 ? _d : '';
|
|
131
|
+
message.producerSeq = (_e = object.producerSeq) !== null && _e !== void 0 ? _e : 0;
|
|
132
|
+
return message;
|
|
133
|
+
},
|
|
134
|
+
};
|
|
135
|
+
function createBasePublishStreamMessageResponse() {
|
|
136
|
+
return {};
|
|
137
|
+
}
|
|
138
|
+
exports.PublishStreamMessageResponse = {
|
|
139
|
+
encode(_, writer = new wire_1.BinaryWriter()) {
|
|
140
|
+
return writer;
|
|
141
|
+
},
|
|
142
|
+
decode(input, length) {
|
|
143
|
+
const reader = input instanceof wire_1.BinaryReader ? input : new wire_1.BinaryReader(input);
|
|
144
|
+
const end = length === undefined ? reader.len : reader.pos + length;
|
|
145
|
+
const message = createBasePublishStreamMessageResponse();
|
|
146
|
+
while (reader.pos < end) {
|
|
147
|
+
const tag = reader.uint32();
|
|
148
|
+
switch (tag >>> 3) {
|
|
149
|
+
}
|
|
150
|
+
if ((tag & 7) === 4 || tag === 0) {
|
|
151
|
+
break;
|
|
152
|
+
}
|
|
153
|
+
reader.skip(tag & 7);
|
|
154
|
+
}
|
|
155
|
+
return message;
|
|
156
|
+
},
|
|
157
|
+
fromJSON(_) {
|
|
158
|
+
return {};
|
|
159
|
+
},
|
|
160
|
+
toJSON(_) {
|
|
161
|
+
const obj = {};
|
|
162
|
+
return obj;
|
|
163
|
+
},
|
|
164
|
+
create(base) {
|
|
165
|
+
return exports.PublishStreamMessageResponse.fromPartial(base !== null && base !== void 0 ? base : {});
|
|
166
|
+
},
|
|
167
|
+
fromPartial(_) {
|
|
168
|
+
const message = createBasePublishStreamMessageResponse();
|
|
169
|
+
return message;
|
|
170
|
+
},
|
|
171
|
+
};
|
|
172
|
+
function createBaseSubscribeStreamRequest() {
|
|
173
|
+
return { namespace: '', topic: '', cursor: undefined };
|
|
174
|
+
}
|
|
175
|
+
exports.SubscribeStreamRequest = {
|
|
176
|
+
encode(message, writer = new wire_1.BinaryWriter()) {
|
|
177
|
+
if (message.namespace !== '') {
|
|
178
|
+
writer.uint32(10).string(message.namespace);
|
|
179
|
+
}
|
|
180
|
+
if (message.topic !== '') {
|
|
181
|
+
writer.uint32(18).string(message.topic);
|
|
182
|
+
}
|
|
183
|
+
if (message.cursor !== undefined) {
|
|
184
|
+
writer.uint32(26).string(message.cursor);
|
|
185
|
+
}
|
|
186
|
+
return writer;
|
|
187
|
+
},
|
|
188
|
+
decode(input, length) {
|
|
189
|
+
const reader = input instanceof wire_1.BinaryReader ? input : new wire_1.BinaryReader(input);
|
|
190
|
+
const end = length === undefined ? reader.len : reader.pos + length;
|
|
191
|
+
const message = createBaseSubscribeStreamRequest();
|
|
192
|
+
while (reader.pos < end) {
|
|
193
|
+
const tag = reader.uint32();
|
|
194
|
+
switch (tag >>> 3) {
|
|
195
|
+
case 1: {
|
|
196
|
+
if (tag !== 10) {
|
|
197
|
+
break;
|
|
198
|
+
}
|
|
199
|
+
message.namespace = reader.string();
|
|
200
|
+
continue;
|
|
201
|
+
}
|
|
202
|
+
case 2: {
|
|
203
|
+
if (tag !== 18) {
|
|
204
|
+
break;
|
|
205
|
+
}
|
|
206
|
+
message.topic = reader.string();
|
|
207
|
+
continue;
|
|
208
|
+
}
|
|
209
|
+
case 3: {
|
|
210
|
+
if (tag !== 26) {
|
|
211
|
+
break;
|
|
212
|
+
}
|
|
213
|
+
message.cursor = reader.string();
|
|
214
|
+
continue;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
if ((tag & 7) === 4 || tag === 0) {
|
|
218
|
+
break;
|
|
219
|
+
}
|
|
220
|
+
reader.skip(tag & 7);
|
|
221
|
+
}
|
|
222
|
+
return message;
|
|
223
|
+
},
|
|
224
|
+
fromJSON(object) {
|
|
225
|
+
return {
|
|
226
|
+
namespace: isSet(object.namespace) ? globalThis.String(object.namespace) : '',
|
|
227
|
+
topic: isSet(object.topic) ? globalThis.String(object.topic) : '',
|
|
228
|
+
cursor: isSet(object.cursor) ? globalThis.String(object.cursor) : undefined,
|
|
229
|
+
};
|
|
230
|
+
},
|
|
231
|
+
toJSON(message) {
|
|
232
|
+
const obj = {};
|
|
233
|
+
if (message.namespace !== '') {
|
|
234
|
+
obj.namespace = message.namespace;
|
|
235
|
+
}
|
|
236
|
+
if (message.topic !== '') {
|
|
237
|
+
obj.topic = message.topic;
|
|
238
|
+
}
|
|
239
|
+
if (message.cursor !== undefined) {
|
|
240
|
+
obj.cursor = message.cursor;
|
|
241
|
+
}
|
|
242
|
+
return obj;
|
|
243
|
+
},
|
|
244
|
+
create(base) {
|
|
245
|
+
return exports.SubscribeStreamRequest.fromPartial(base !== null && base !== void 0 ? base : {});
|
|
246
|
+
},
|
|
247
|
+
fromPartial(object) {
|
|
248
|
+
var _a, _b, _c;
|
|
249
|
+
const message = createBaseSubscribeStreamRequest();
|
|
250
|
+
message.namespace = (_a = object.namespace) !== null && _a !== void 0 ? _a : '';
|
|
251
|
+
message.topic = (_b = object.topic) !== null && _b !== void 0 ? _b : '';
|
|
252
|
+
message.cursor = (_c = object.cursor) !== null && _c !== void 0 ? _c : undefined;
|
|
253
|
+
return message;
|
|
254
|
+
},
|
|
255
|
+
};
|
|
256
|
+
function createBaseStreamMessage() {
|
|
257
|
+
return { entries: [], hangup: false, cursor: '' };
|
|
258
|
+
}
|
|
259
|
+
exports.StreamMessage = {
|
|
260
|
+
encode(message, writer = new wire_1.BinaryWriter()) {
|
|
261
|
+
for (const v of message.entries) {
|
|
262
|
+
exports.StreamEntry.encode(v, writer.uint32(10).fork()).join();
|
|
263
|
+
}
|
|
264
|
+
if (message.hangup !== false) {
|
|
265
|
+
writer.uint32(16).bool(message.hangup);
|
|
266
|
+
}
|
|
267
|
+
if (message.cursor !== '') {
|
|
268
|
+
writer.uint32(26).string(message.cursor);
|
|
269
|
+
}
|
|
270
|
+
return writer;
|
|
271
|
+
},
|
|
272
|
+
decode(input, length) {
|
|
273
|
+
const reader = input instanceof wire_1.BinaryReader ? input : new wire_1.BinaryReader(input);
|
|
274
|
+
const end = length === undefined ? reader.len : reader.pos + length;
|
|
275
|
+
const message = createBaseStreamMessage();
|
|
276
|
+
while (reader.pos < end) {
|
|
277
|
+
const tag = reader.uint32();
|
|
278
|
+
switch (tag >>> 3) {
|
|
279
|
+
case 1: {
|
|
280
|
+
if (tag !== 10) {
|
|
281
|
+
break;
|
|
282
|
+
}
|
|
283
|
+
message.entries.push(exports.StreamEntry.decode(reader, reader.uint32()));
|
|
284
|
+
continue;
|
|
285
|
+
}
|
|
286
|
+
case 2: {
|
|
287
|
+
if (tag !== 16) {
|
|
288
|
+
break;
|
|
289
|
+
}
|
|
290
|
+
message.hangup = reader.bool();
|
|
291
|
+
continue;
|
|
292
|
+
}
|
|
293
|
+
case 3: {
|
|
294
|
+
if (tag !== 26) {
|
|
295
|
+
break;
|
|
296
|
+
}
|
|
297
|
+
message.cursor = reader.string();
|
|
298
|
+
continue;
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
if ((tag & 7) === 4 || tag === 0) {
|
|
302
|
+
break;
|
|
303
|
+
}
|
|
304
|
+
reader.skip(tag & 7);
|
|
305
|
+
}
|
|
306
|
+
return message;
|
|
307
|
+
},
|
|
308
|
+
fromJSON(object) {
|
|
309
|
+
return {
|
|
310
|
+
entries: globalThis.Array.isArray(object === null || object === void 0 ? void 0 : object.entries)
|
|
311
|
+
? object.entries.map((e) => exports.StreamEntry.fromJSON(e))
|
|
312
|
+
: [],
|
|
313
|
+
hangup: isSet(object.hangup) ? globalThis.Boolean(object.hangup) : false,
|
|
314
|
+
cursor: isSet(object.cursor) ? globalThis.String(object.cursor) : '',
|
|
315
|
+
};
|
|
316
|
+
},
|
|
317
|
+
toJSON(message) {
|
|
318
|
+
var _a;
|
|
319
|
+
const obj = {};
|
|
320
|
+
if ((_a = message.entries) === null || _a === void 0 ? void 0 : _a.length) {
|
|
321
|
+
obj.entries = message.entries.map((e) => exports.StreamEntry.toJSON(e));
|
|
322
|
+
}
|
|
323
|
+
if (message.hangup !== false) {
|
|
324
|
+
obj.hangup = message.hangup;
|
|
325
|
+
}
|
|
326
|
+
if (message.cursor !== '') {
|
|
327
|
+
obj.cursor = message.cursor;
|
|
328
|
+
}
|
|
329
|
+
return obj;
|
|
330
|
+
},
|
|
331
|
+
create(base) {
|
|
332
|
+
return exports.StreamMessage.fromPartial(base !== null && base !== void 0 ? base : {});
|
|
333
|
+
},
|
|
334
|
+
fromPartial(object) {
|
|
335
|
+
var _a, _b, _c;
|
|
336
|
+
const message = createBaseStreamMessage();
|
|
337
|
+
message.entries = ((_a = object.entries) === null || _a === void 0 ? void 0 : _a.map((e) => exports.StreamEntry.fromPartial(e))) || [];
|
|
338
|
+
message.hangup = (_b = object.hangup) !== null && _b !== void 0 ? _b : false;
|
|
339
|
+
message.cursor = (_c = object.cursor) !== null && _c !== void 0 ? _c : '';
|
|
340
|
+
return message;
|
|
341
|
+
},
|
|
342
|
+
};
|
|
343
|
+
function createBaseStreamEntry() {
|
|
344
|
+
return { payload: new Uint8Array(0), cursor: '', createdAt: undefined };
|
|
345
|
+
}
|
|
346
|
+
exports.StreamEntry = {
|
|
347
|
+
encode(message, writer = new wire_1.BinaryWriter()) {
|
|
348
|
+
if (message.payload.length !== 0) {
|
|
349
|
+
writer.uint32(10).bytes(message.payload);
|
|
350
|
+
}
|
|
351
|
+
if (message.cursor !== '') {
|
|
352
|
+
writer.uint32(18).string(message.cursor);
|
|
353
|
+
}
|
|
354
|
+
if (message.createdAt !== undefined) {
|
|
355
|
+
timestamp_1.Timestamp.encode(toTimestamp(message.createdAt), writer.uint32(26).fork()).join();
|
|
356
|
+
}
|
|
357
|
+
return writer;
|
|
358
|
+
},
|
|
359
|
+
decode(input, length) {
|
|
360
|
+
const reader = input instanceof wire_1.BinaryReader ? input : new wire_1.BinaryReader(input);
|
|
361
|
+
const end = length === undefined ? reader.len : reader.pos + length;
|
|
362
|
+
const message = createBaseStreamEntry();
|
|
363
|
+
while (reader.pos < end) {
|
|
364
|
+
const tag = reader.uint32();
|
|
365
|
+
switch (tag >>> 3) {
|
|
366
|
+
case 1: {
|
|
367
|
+
if (tag !== 10) {
|
|
368
|
+
break;
|
|
369
|
+
}
|
|
370
|
+
message.payload = reader.bytes();
|
|
371
|
+
continue;
|
|
372
|
+
}
|
|
373
|
+
case 2: {
|
|
374
|
+
if (tag !== 18) {
|
|
375
|
+
break;
|
|
376
|
+
}
|
|
377
|
+
message.cursor = reader.string();
|
|
378
|
+
continue;
|
|
379
|
+
}
|
|
380
|
+
case 3: {
|
|
381
|
+
if (tag !== 26) {
|
|
382
|
+
break;
|
|
383
|
+
}
|
|
384
|
+
message.createdAt = fromTimestamp(timestamp_1.Timestamp.decode(reader, reader.uint32()));
|
|
385
|
+
continue;
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
if ((tag & 7) === 4 || tag === 0) {
|
|
389
|
+
break;
|
|
390
|
+
}
|
|
391
|
+
reader.skip(tag & 7);
|
|
392
|
+
}
|
|
393
|
+
return message;
|
|
394
|
+
},
|
|
395
|
+
fromJSON(object) {
|
|
396
|
+
return {
|
|
397
|
+
payload: isSet(object.payload) ? bytesFromBase64(object.payload) : new Uint8Array(0),
|
|
398
|
+
cursor: isSet(object.cursor) ? globalThis.String(object.cursor) : '',
|
|
399
|
+
createdAt: isSet(object.createdAt)
|
|
400
|
+
? fromJsonTimestamp(object.createdAt)
|
|
401
|
+
: isSet(object.created_at)
|
|
402
|
+
? fromJsonTimestamp(object.created_at)
|
|
403
|
+
: undefined,
|
|
404
|
+
};
|
|
405
|
+
},
|
|
406
|
+
toJSON(message) {
|
|
407
|
+
const obj = {};
|
|
408
|
+
if (message.payload.length !== 0) {
|
|
409
|
+
obj.payload = base64FromBytes(message.payload);
|
|
410
|
+
}
|
|
411
|
+
if (message.cursor !== '') {
|
|
412
|
+
obj.cursor = message.cursor;
|
|
413
|
+
}
|
|
414
|
+
if (message.createdAt !== undefined) {
|
|
415
|
+
obj.createdAt = message.createdAt.toISOString();
|
|
416
|
+
}
|
|
417
|
+
return obj;
|
|
418
|
+
},
|
|
419
|
+
create(base) {
|
|
420
|
+
return exports.StreamEntry.fromPartial(base !== null && base !== void 0 ? base : {});
|
|
421
|
+
},
|
|
422
|
+
fromPartial(object) {
|
|
423
|
+
var _a, _b, _c;
|
|
424
|
+
const message = createBaseStreamEntry();
|
|
425
|
+
message.payload = (_a = object.payload) !== null && _a !== void 0 ? _a : new Uint8Array(0);
|
|
426
|
+
message.cursor = (_b = object.cursor) !== null && _b !== void 0 ? _b : '';
|
|
427
|
+
message.createdAt = (_c = object.createdAt) !== null && _c !== void 0 ? _c : undefined;
|
|
428
|
+
return message;
|
|
429
|
+
},
|
|
430
|
+
};
|
|
431
|
+
exports.V1StreamsDefinition = {
|
|
432
|
+
name: 'V1Streams',
|
|
433
|
+
fullName: 'v1.V1Streams',
|
|
434
|
+
methods: {
|
|
435
|
+
publish: {
|
|
436
|
+
name: 'Publish',
|
|
437
|
+
requestType: exports.PublishStreamMessageRequest,
|
|
438
|
+
requestStream: false,
|
|
439
|
+
responseType: exports.PublishStreamMessageResponse,
|
|
440
|
+
responseStream: false,
|
|
441
|
+
options: {},
|
|
442
|
+
},
|
|
443
|
+
subscribe: {
|
|
444
|
+
name: 'Subscribe',
|
|
445
|
+
requestType: exports.SubscribeStreamRequest,
|
|
446
|
+
requestStream: false,
|
|
447
|
+
responseType: exports.StreamMessage,
|
|
448
|
+
responseStream: true,
|
|
449
|
+
options: {},
|
|
450
|
+
},
|
|
451
|
+
},
|
|
452
|
+
};
|
|
453
|
+
function bytesFromBase64(b64) {
|
|
454
|
+
if (globalThis.Buffer) {
|
|
455
|
+
return Uint8Array.from(globalThis.Buffer.from(b64, 'base64'));
|
|
456
|
+
}
|
|
457
|
+
else {
|
|
458
|
+
const bin = globalThis.atob(b64);
|
|
459
|
+
const arr = new Uint8Array(bin.length);
|
|
460
|
+
for (let i = 0; i < bin.length; ++i) {
|
|
461
|
+
arr[i] = bin.charCodeAt(i);
|
|
462
|
+
}
|
|
463
|
+
return arr;
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
function base64FromBytes(arr) {
|
|
467
|
+
if (globalThis.Buffer) {
|
|
468
|
+
return globalThis.Buffer.from(arr).toString('base64');
|
|
469
|
+
}
|
|
470
|
+
else {
|
|
471
|
+
const bin = [];
|
|
472
|
+
arr.forEach((byte) => {
|
|
473
|
+
bin.push(globalThis.String.fromCharCode(byte));
|
|
474
|
+
});
|
|
475
|
+
return globalThis.btoa(bin.join(''));
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
function toTimestamp(date) {
|
|
479
|
+
const seconds = Math.trunc(date.getTime() / 1000);
|
|
480
|
+
const nanos = (date.getTime() % 1000) * 1000000;
|
|
481
|
+
return { seconds, nanos };
|
|
482
|
+
}
|
|
483
|
+
function fromTimestamp(t) {
|
|
484
|
+
let millis = (t.seconds || 0) * 1000;
|
|
485
|
+
millis += (t.nanos || 0) / 1000000;
|
|
486
|
+
return new globalThis.Date(millis);
|
|
487
|
+
}
|
|
488
|
+
function fromJsonTimestamp(o) {
|
|
489
|
+
if (o instanceof globalThis.Date) {
|
|
490
|
+
return o;
|
|
491
|
+
}
|
|
492
|
+
else if (typeof o === 'string') {
|
|
493
|
+
return new globalThis.Date(o);
|
|
494
|
+
}
|
|
495
|
+
else {
|
|
496
|
+
return fromTimestamp(timestamp_1.Timestamp.fromJSON(o));
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
function longToNumber(int64) {
|
|
500
|
+
const num = globalThis.Number(int64.toString());
|
|
501
|
+
if (num > globalThis.Number.MAX_SAFE_INTEGER) {
|
|
502
|
+
throw new globalThis.Error('Value is larger than Number.MAX_SAFE_INTEGER');
|
|
503
|
+
}
|
|
504
|
+
if (num < globalThis.Number.MIN_SAFE_INTEGER) {
|
|
505
|
+
throw new globalThis.Error('Value is smaller than Number.MIN_SAFE_INTEGER');
|
|
506
|
+
}
|
|
507
|
+
return num;
|
|
508
|
+
}
|
|
509
|
+
function isSet(value) {
|
|
510
|
+
return value !== null && value !== undefined;
|
|
511
|
+
}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import type { GenFile, GenMessage, GenService } from "@bufbuild/protobuf/codegenv2";
|
|
2
|
+
import type { Timestamp } from "@bufbuild/protobuf/wkt";
|
|
3
|
+
import type { Message } from "@bufbuild/protobuf";
|
|
4
|
+
/**
|
|
5
|
+
* Describes the file v1/streams.proto.
|
|
6
|
+
*/
|
|
7
|
+
export declare const file_v1_streams: GenFile;
|
|
8
|
+
/**
|
|
9
|
+
* @generated from message v1.PublishStreamMessageRequest
|
|
10
|
+
*/
|
|
11
|
+
export type PublishStreamMessageRequest = Message<"v1.PublishStreamMessageRequest"> & {
|
|
12
|
+
/**
|
|
13
|
+
* @generated from field: string namespace = 1;
|
|
14
|
+
*/
|
|
15
|
+
namespace: string;
|
|
16
|
+
/**
|
|
17
|
+
* @generated from field: string topic = 2;
|
|
18
|
+
*/
|
|
19
|
+
topic: string;
|
|
20
|
+
/**
|
|
21
|
+
* @generated from field: bytes payload = 3;
|
|
22
|
+
*/
|
|
23
|
+
payload: Uint8Array;
|
|
24
|
+
/**
|
|
25
|
+
* @generated from field: string producer_id = 4;
|
|
26
|
+
*/
|
|
27
|
+
producerId: string;
|
|
28
|
+
/**
|
|
29
|
+
* @generated from field: int64 producer_seq = 5;
|
|
30
|
+
*/
|
|
31
|
+
producerSeq: bigint;
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* Describes the message v1.PublishStreamMessageRequest.
|
|
35
|
+
* Use `create(PublishStreamMessageRequestSchema)` to create a new message.
|
|
36
|
+
*/
|
|
37
|
+
export declare const PublishStreamMessageRequestSchema: GenMessage<PublishStreamMessageRequest>;
|
|
38
|
+
/**
|
|
39
|
+
* @generated from message v1.PublishStreamMessageResponse
|
|
40
|
+
*/
|
|
41
|
+
export type PublishStreamMessageResponse = Message<"v1.PublishStreamMessageResponse"> & {};
|
|
42
|
+
/**
|
|
43
|
+
* Describes the message v1.PublishStreamMessageResponse.
|
|
44
|
+
* Use `create(PublishStreamMessageResponseSchema)` to create a new message.
|
|
45
|
+
*/
|
|
46
|
+
export declare const PublishStreamMessageResponseSchema: GenMessage<PublishStreamMessageResponse>;
|
|
47
|
+
/**
|
|
48
|
+
* @generated from message v1.SubscribeStreamRequest
|
|
49
|
+
*/
|
|
50
|
+
export type SubscribeStreamRequest = Message<"v1.SubscribeStreamRequest"> & {
|
|
51
|
+
/**
|
|
52
|
+
* @generated from field: string namespace = 1;
|
|
53
|
+
*/
|
|
54
|
+
namespace: string;
|
|
55
|
+
/**
|
|
56
|
+
* @generated from field: string topic = 2;
|
|
57
|
+
*/
|
|
58
|
+
topic: string;
|
|
59
|
+
/**
|
|
60
|
+
* @generated from field: optional string cursor = 3;
|
|
61
|
+
*/
|
|
62
|
+
cursor?: string | undefined;
|
|
63
|
+
};
|
|
64
|
+
/**
|
|
65
|
+
* Describes the message v1.SubscribeStreamRequest.
|
|
66
|
+
* Use `create(SubscribeStreamRequestSchema)` to create a new message.
|
|
67
|
+
*/
|
|
68
|
+
export declare const SubscribeStreamRequestSchema: GenMessage<SubscribeStreamRequest>;
|
|
69
|
+
/**
|
|
70
|
+
* @generated from message v1.StreamMessage
|
|
71
|
+
*/
|
|
72
|
+
export type StreamMessage = Message<"v1.StreamMessage"> & {
|
|
73
|
+
/**
|
|
74
|
+
* @generated from field: repeated v1.StreamEntry entries = 1;
|
|
75
|
+
*/
|
|
76
|
+
entries: StreamEntry[];
|
|
77
|
+
/**
|
|
78
|
+
* @generated from field: bool hangup = 2;
|
|
79
|
+
*/
|
|
80
|
+
hangup: boolean;
|
|
81
|
+
/**
|
|
82
|
+
* @generated from field: string cursor = 3;
|
|
83
|
+
*/
|
|
84
|
+
cursor: string;
|
|
85
|
+
};
|
|
86
|
+
/**
|
|
87
|
+
* Describes the message v1.StreamMessage.
|
|
88
|
+
* Use `create(StreamMessageSchema)` to create a new message.
|
|
89
|
+
*/
|
|
90
|
+
export declare const StreamMessageSchema: GenMessage<StreamMessage>;
|
|
91
|
+
/**
|
|
92
|
+
* @generated from message v1.StreamEntry
|
|
93
|
+
*/
|
|
94
|
+
export type StreamEntry = Message<"v1.StreamEntry"> & {
|
|
95
|
+
/**
|
|
96
|
+
* @generated from field: bytes payload = 1;
|
|
97
|
+
*/
|
|
98
|
+
payload: Uint8Array;
|
|
99
|
+
/**
|
|
100
|
+
* @generated from field: string cursor = 2;
|
|
101
|
+
*/
|
|
102
|
+
cursor: string;
|
|
103
|
+
/**
|
|
104
|
+
* @generated from field: google.protobuf.Timestamp created_at = 3;
|
|
105
|
+
*/
|
|
106
|
+
createdAt?: Timestamp | undefined;
|
|
107
|
+
};
|
|
108
|
+
/**
|
|
109
|
+
* Describes the message v1.StreamEntry.
|
|
110
|
+
* Use `create(StreamEntrySchema)` to create a new message.
|
|
111
|
+
*/
|
|
112
|
+
export declare const StreamEntrySchema: GenMessage<StreamEntry>;
|
|
113
|
+
/**
|
|
114
|
+
* @generated from service v1.V1Streams
|
|
115
|
+
*/
|
|
116
|
+
export declare const V1Streams: GenService<{
|
|
117
|
+
/**
|
|
118
|
+
* @generated from rpc v1.V1Streams.Publish
|
|
119
|
+
*/
|
|
120
|
+
publish: {
|
|
121
|
+
methodKind: "unary";
|
|
122
|
+
input: typeof PublishStreamMessageRequestSchema;
|
|
123
|
+
output: typeof PublishStreamMessageResponseSchema;
|
|
124
|
+
};
|
|
125
|
+
/**
|
|
126
|
+
* @generated from rpc v1.V1Streams.Subscribe
|
|
127
|
+
*/
|
|
128
|
+
subscribe: {
|
|
129
|
+
methodKind: "server_streaming";
|
|
130
|
+
input: typeof SubscribeStreamRequestSchema;
|
|
131
|
+
output: typeof StreamMessageSchema;
|
|
132
|
+
};
|
|
133
|
+
}>;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// @generated by protoc-gen-es v2.15.0 with parameter "target=ts"
|
|
3
|
+
// @generated from file v1/streams.proto (package v1, syntax proto3)
|
|
4
|
+
/* eslint-disable */
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.V1Streams = exports.StreamEntrySchema = exports.StreamMessageSchema = exports.SubscribeStreamRequestSchema = exports.PublishStreamMessageResponseSchema = exports.PublishStreamMessageRequestSchema = exports.file_v1_streams = void 0;
|
|
7
|
+
const codegenv2_1 = require("@bufbuild/protobuf/codegenv2");
|
|
8
|
+
const wkt_1 = require("@bufbuild/protobuf/wkt");
|
|
9
|
+
/**
|
|
10
|
+
* Describes the file v1/streams.proto.
|
|
11
|
+
*/
|
|
12
|
+
exports.file_v1_streams = (0, codegenv2_1.fileDesc)("ChB2MS9zdHJlYW1zLnByb3RvEgJ2MSJ7ChtQdWJsaXNoU3RyZWFtTWVzc2FnZVJlcXVlc3QSEQoJbmFtZXNwYWNlGAEgASgJEg0KBXRvcGljGAIgASgJEg8KB3BheWxvYWQYAyABKAwSEwoLcHJvZHVjZXJfaWQYBCABKAkSFAoMcHJvZHVjZXJfc2VxGAUgASgDIh4KHFB1Ymxpc2hTdHJlYW1NZXNzYWdlUmVzcG9uc2UiWgoWU3Vic2NyaWJlU3RyZWFtUmVxdWVzdBIRCgluYW1lc3BhY2UYASABKAkSDQoFdG9waWMYAiABKAkSEwoGY3Vyc29yGAMgASgJSACIAQFCCQoHX2N1cnNvciJRCg1TdHJlYW1NZXNzYWdlEiAKB2VudHJpZXMYASADKAsyDy52MS5TdHJlYW1FbnRyeRIOCgZoYW5ndXAYAiABKAgSDgoGY3Vyc29yGAMgASgJIl4KC1N0cmVhbUVudHJ5Eg8KB3BheWxvYWQYASABKAwSDgoGY3Vyc29yGAIgASgJEi4KCmNyZWF0ZWRfYXQYAyABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wMpsBCglWMVN0cmVhbXMSTgoHUHVibGlzaBIfLnYxLlB1Ymxpc2hTdHJlYW1NZXNzYWdlUmVxdWVzdBogLnYxLlB1Ymxpc2hTdHJlYW1NZXNzYWdlUmVzcG9uc2UiABI+CglTdWJzY3JpYmUSGi52MS5TdWJzY3JpYmVTdHJlYW1SZXF1ZXN0GhEudjEuU3RyZWFtTWVzc2FnZSIAMAFCQlpAZ2l0aHViLmNvbS9oYXRjaGV0LWRldi9oYXRjaGV0L2ludGVybmFsL3NlcnZpY2VzL3NoYXJlZC9wcm90by92MWIGcHJvdG8z", [wkt_1.file_google_protobuf_timestamp]);
|
|
13
|
+
/**
|
|
14
|
+
* Describes the message v1.PublishStreamMessageRequest.
|
|
15
|
+
* Use `create(PublishStreamMessageRequestSchema)` to create a new message.
|
|
16
|
+
*/
|
|
17
|
+
exports.PublishStreamMessageRequestSchema = (0, codegenv2_1.messageDesc)(exports.file_v1_streams, 0);
|
|
18
|
+
/**
|
|
19
|
+
* Describes the message v1.PublishStreamMessageResponse.
|
|
20
|
+
* Use `create(PublishStreamMessageResponseSchema)` to create a new message.
|
|
21
|
+
*/
|
|
22
|
+
exports.PublishStreamMessageResponseSchema = (0, codegenv2_1.messageDesc)(exports.file_v1_streams, 1);
|
|
23
|
+
/**
|
|
24
|
+
* Describes the message v1.SubscribeStreamRequest.
|
|
25
|
+
* Use `create(SubscribeStreamRequestSchema)` to create a new message.
|
|
26
|
+
*/
|
|
27
|
+
exports.SubscribeStreamRequestSchema = (0, codegenv2_1.messageDesc)(exports.file_v1_streams, 2);
|
|
28
|
+
/**
|
|
29
|
+
* Describes the message v1.StreamMessage.
|
|
30
|
+
* Use `create(StreamMessageSchema)` to create a new message.
|
|
31
|
+
*/
|
|
32
|
+
exports.StreamMessageSchema = (0, codegenv2_1.messageDesc)(exports.file_v1_streams, 3);
|
|
33
|
+
/**
|
|
34
|
+
* Describes the message v1.StreamEntry.
|
|
35
|
+
* Use `create(StreamEntrySchema)` to create a new message.
|
|
36
|
+
*/
|
|
37
|
+
exports.StreamEntrySchema = (0, codegenv2_1.messageDesc)(exports.file_v1_streams, 4);
|
|
38
|
+
/**
|
|
39
|
+
* @generated from service v1.V1Streams
|
|
40
|
+
*/
|
|
41
|
+
exports.V1Streams = (0, codegenv2_1.serviceDesc)(exports.file_v1_streams, 0);
|
package/v1/client/client.d.ts
CHANGED
|
@@ -19,7 +19,7 @@ import { BatchTaskFn } from '../task';
|
|
|
19
19
|
import type { LegacyWorkflow } from '../../legacy/legacy-transformer';
|
|
20
20
|
import { IHatchetClient } from './client.interface';
|
|
21
21
|
import { CreateWorkerOpts, Worker } from './worker/worker';
|
|
22
|
-
import { CELClient, CronClient, FiltersClient, LogsClient, MetricsClient, RatelimitsClient, RunsClient, ScheduleClient, TenantClient, WebhooksClient, WorkersClient, WorkflowsClient } from './features';
|
|
22
|
+
import { CELClient, CronClient, FiltersClient, LogsClient, MetricsClient, RatelimitsClient, RunsClient, ScheduleClient, StreamsClient, TenantClient, WebhooksClient, WorkersClient, WorkflowsClient } from './features';
|
|
23
23
|
import { InputType, OutputType, UnknownInputType, StrictWorkflowOutputType, Resolved } from '../types';
|
|
24
24
|
import { AdminClient } from './admin';
|
|
25
25
|
import { DurableContext } from './worker/context';
|
|
@@ -294,6 +294,13 @@ export declare class HatchetClient<GlobalInput extends Record<string, any> = {},
|
|
|
294
294
|
* @returns A runs client instance
|
|
295
295
|
*/
|
|
296
296
|
get runs(): RunsClient;
|
|
297
|
+
private _streams;
|
|
298
|
+
/**
|
|
299
|
+
* Get the streams client for publishing to and reading from durable,
|
|
300
|
+
* topic-based streams
|
|
301
|
+
* @returns A streams client instance
|
|
302
|
+
*/
|
|
303
|
+
get streams(): StreamsClient;
|
|
297
304
|
private _workflows;
|
|
298
305
|
/**
|
|
299
306
|
* Get the workflows client for creating and managing workflows
|
package/v1/client/client.js
CHANGED
|
@@ -405,6 +405,17 @@ class HatchetClient {
|
|
|
405
405
|
}
|
|
406
406
|
return this._runs;
|
|
407
407
|
}
|
|
408
|
+
/**
|
|
409
|
+
* Get the streams client for publishing to and reading from durable,
|
|
410
|
+
* topic-based streams
|
|
411
|
+
* @returns A streams client instance
|
|
412
|
+
*/
|
|
413
|
+
get streams() {
|
|
414
|
+
if (!this._streams) {
|
|
415
|
+
this._streams = new features_1.StreamsClient(this);
|
|
416
|
+
}
|
|
417
|
+
return this._streams;
|
|
418
|
+
}
|
|
408
419
|
/**
|
|
409
420
|
* Get the workflows client for creating and managing workflows
|
|
410
421
|
* @returns A workflows client instance
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { HatchetClient } from '../client';
|
|
2
|
+
export type StreamEvent = {
|
|
3
|
+
/** the message payload */
|
|
4
|
+
payload: Uint8Array;
|
|
5
|
+
/** resumes events() right after this event */
|
|
6
|
+
cursor: string;
|
|
7
|
+
/** when the message was stored */
|
|
8
|
+
createdAt?: Date;
|
|
9
|
+
};
|
|
10
|
+
export type StreamCallOptions = {
|
|
11
|
+
namespace?: string;
|
|
12
|
+
cursor?: string;
|
|
13
|
+
/** ends an events() iteration cleanly, without throwing */
|
|
14
|
+
signal?: AbortSignal;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* StreamsClient publishes to and reads from durable topics. Unlike
|
|
18
|
+
* `runs.subscribeToStream`, topics are stored, independent of any run, and
|
|
19
|
+
* readers can resume from a cursor.
|
|
20
|
+
*/
|
|
21
|
+
export declare class StreamsClient {
|
|
22
|
+
private _config;
|
|
23
|
+
private _grpc;
|
|
24
|
+
private producers;
|
|
25
|
+
private publishChains;
|
|
26
|
+
constructor(client: HatchetClient);
|
|
27
|
+
private get grpc();
|
|
28
|
+
private publishOrdered;
|
|
29
|
+
/**
|
|
30
|
+
* Resolves once the message is stored. A client's messages to a topic are
|
|
31
|
+
* delivered in the order publish() was called.
|
|
32
|
+
* @param topic - the topic to publish to
|
|
33
|
+
* @param message - the message payload
|
|
34
|
+
* @param options - optional namespace override
|
|
35
|
+
*/
|
|
36
|
+
publish(topic: string, message: Uint8Array | string, options?: StreamCallOptions): Promise<void>;
|
|
37
|
+
/**
|
|
38
|
+
* Yields topic's messages after options.cursor, or from the oldest retained.
|
|
39
|
+
* If the connection drops, it resubscribes from the last message yielded, so
|
|
40
|
+
* nothing is skipped or repeated. Ends when the server hangs up an idle
|
|
41
|
+
* subscription, options.signal aborts, or the caller stops iterating; throws
|
|
42
|
+
* on errors a retry can't fix, such as an expired cursor.
|
|
43
|
+
* @param topic - the topic to read from
|
|
44
|
+
* @param options - optional namespace override, resume cursor, and abort signal
|
|
45
|
+
*/
|
|
46
|
+
events(topic: string, options?: StreamCallOptions): AsyncIterable<StreamEvent>;
|
|
47
|
+
}
|
|
@@ -0,0 +1,210 @@
|
|
|
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
|
+
var __asyncValues = (this && this.__asyncValues) || function (o) {
|
|
12
|
+
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
|
|
13
|
+
var m = o[Symbol.asyncIterator], i;
|
|
14
|
+
return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
|
|
15
|
+
function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
|
|
16
|
+
function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
|
|
17
|
+
};
|
|
18
|
+
var __await = (this && this.__await) || function (v) { return this instanceof __await ? (this.v = v, this) : new __await(v); }
|
|
19
|
+
var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _arguments, generator) {
|
|
20
|
+
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
|
|
21
|
+
var g = generator.apply(thisArg, _arguments || []), i, q = [];
|
|
22
|
+
return i = Object.create((typeof AsyncIterator === "function" ? AsyncIterator : Object).prototype), verb("next"), verb("throw"), verb("return", awaitReturn), i[Symbol.asyncIterator] = function () { return this; }, i;
|
|
23
|
+
function awaitReturn(f) { return function (v) { return Promise.resolve(v).then(f, reject); }; }
|
|
24
|
+
function verb(n, f) { if (g[n]) { i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; if (f) i[n] = f(i[n]); } }
|
|
25
|
+
function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }
|
|
26
|
+
function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }
|
|
27
|
+
function fulfill(value) { resume("next", value); }
|
|
28
|
+
function reject(value) { resume("throw", value); }
|
|
29
|
+
function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }
|
|
30
|
+
};
|
|
31
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
32
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
33
|
+
};
|
|
34
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
35
|
+
exports.StreamsClient = void 0;
|
|
36
|
+
const crypto_1 = require("crypto");
|
|
37
|
+
const nice_grpc_1 = require("nice-grpc");
|
|
38
|
+
const grpc_helpers_1 = require("../../../util/grpc-helpers");
|
|
39
|
+
const grpc_error_1 = require("../../../util/grpc-error");
|
|
40
|
+
const sleep_1 = __importDefault(require("../../../util/sleep"));
|
|
41
|
+
const streams_1 = require("../../../protoc/v1/streams");
|
|
42
|
+
// the server stored nothing, so the seq is unused
|
|
43
|
+
function publishRejectedBeforeStoring(err) {
|
|
44
|
+
const code = (0, grpc_error_1.getGrpcErrorCode)(err);
|
|
45
|
+
return (code === nice_grpc_1.Status.INVALID_ARGUMENT ||
|
|
46
|
+
code === nice_grpc_1.Status.RESOURCE_EXHAUSTED ||
|
|
47
|
+
code === nice_grpc_1.Status.UNAUTHENTICATED ||
|
|
48
|
+
code === nice_grpc_1.Status.PERMISSION_DENIED);
|
|
49
|
+
}
|
|
50
|
+
// retrying a subscribe that failed with these can't succeed
|
|
51
|
+
const permanentSubscribeErrors = new Set([
|
|
52
|
+
nice_grpc_1.Status.INVALID_ARGUMENT,
|
|
53
|
+
nice_grpc_1.Status.PERMISSION_DENIED,
|
|
54
|
+
nice_grpc_1.Status.UNAUTHENTICATED,
|
|
55
|
+
nice_grpc_1.Status.OUT_OF_RANGE,
|
|
56
|
+
nice_grpc_1.Status.FAILED_PRECONDITION,
|
|
57
|
+
nice_grpc_1.Status.NOT_FOUND,
|
|
58
|
+
]);
|
|
59
|
+
const resubscribeMinDelayMs = 250;
|
|
60
|
+
const resubscribeMaxDelayMs = 10000;
|
|
61
|
+
function shouldResubscribe(err, attempt) {
|
|
62
|
+
const code = (0, grpc_error_1.getGrpcErrorCode)(err);
|
|
63
|
+
if (code === undefined || permanentSubscribeErrors.has(code)) {
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
// proxies answer 404 while an engine restarts, but on a first attempt it means no streams support
|
|
67
|
+
if (code === nice_grpc_1.Status.UNIMPLEMENTED) {
|
|
68
|
+
return attempt > 0;
|
|
69
|
+
}
|
|
70
|
+
return true;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* StreamsClient publishes to and reads from durable topics. Unlike
|
|
74
|
+
* `runs.subscribeToStream`, topics are stored, independent of any run, and
|
|
75
|
+
* readers can resume from a cursor.
|
|
76
|
+
*/
|
|
77
|
+
class StreamsClient {
|
|
78
|
+
constructor(client) {
|
|
79
|
+
// per (namespace, topic); seq only advances after a publish succeeds
|
|
80
|
+
this.producers = new Map();
|
|
81
|
+
// serializes publishes per (namespace, topic) so two never share a seq; the
|
|
82
|
+
// stored promise always resolves, so one failure doesn't block later calls
|
|
83
|
+
this.publishChains = new Map();
|
|
84
|
+
this._config = client.config;
|
|
85
|
+
}
|
|
86
|
+
get grpc() {
|
|
87
|
+
if (!this._grpc) {
|
|
88
|
+
const { client } = (0, grpc_helpers_1.createGrpcClient)(this._config, streams_1.V1StreamsDefinition);
|
|
89
|
+
this._grpc = client;
|
|
90
|
+
}
|
|
91
|
+
return this._grpc;
|
|
92
|
+
}
|
|
93
|
+
publishOrdered(key_1, namespace_1, topic_1, payload_1) {
|
|
94
|
+
return __awaiter(this, arguments, void 0, function* (key, namespace, topic, payload, retryGap = true) {
|
|
95
|
+
let producer = this.producers.get(key);
|
|
96
|
+
if (!producer) {
|
|
97
|
+
producer = { producerId: (0, crypto_1.randomUUID)(), seq: 0 };
|
|
98
|
+
this.producers.set(key, producer);
|
|
99
|
+
}
|
|
100
|
+
try {
|
|
101
|
+
yield this.grpc.publish({
|
|
102
|
+
namespace,
|
|
103
|
+
topic,
|
|
104
|
+
payload,
|
|
105
|
+
producerId: producer.producerId,
|
|
106
|
+
producerSeq: producer.seq,
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
catch (err) {
|
|
110
|
+
// it may still land, and a different payload under its seq would be dropped as a duplicate
|
|
111
|
+
if (!publishRejectedBeforeStoring(err)) {
|
|
112
|
+
this.producers.set(key, { producerId: (0, crypto_1.randomUUID)(), seq: 0 });
|
|
113
|
+
}
|
|
114
|
+
// a gap stored nothing (e.g. the watermark passed cursor retention), so resend as the new producer
|
|
115
|
+
if (retryGap && (0, grpc_error_1.getGrpcErrorCode)(err) === nice_grpc_1.Status.FAILED_PRECONDITION) {
|
|
116
|
+
return this.publishOrdered(key, namespace, topic, payload, false);
|
|
117
|
+
}
|
|
118
|
+
throw err;
|
|
119
|
+
}
|
|
120
|
+
producer.seq += 1;
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Resolves once the message is stored. A client's messages to a topic are
|
|
125
|
+
* delivered in the order publish() was called.
|
|
126
|
+
* @param topic - the topic to publish to
|
|
127
|
+
* @param message - the message payload
|
|
128
|
+
* @param options - optional namespace override
|
|
129
|
+
*/
|
|
130
|
+
publish(topic, message, options) {
|
|
131
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
132
|
+
var _a, _b;
|
|
133
|
+
const payload = typeof message === 'string' ? new TextEncoder().encode(message) : message;
|
|
134
|
+
const namespace = (_a = options === null || options === void 0 ? void 0 : options.namespace) !== null && _a !== void 0 ? _a : '';
|
|
135
|
+
const key = `${namespace}\u0000${topic}`;
|
|
136
|
+
const previous = (_b = this.publishChains.get(key)) !== null && _b !== void 0 ? _b : Promise.resolve();
|
|
137
|
+
const publishPromise = previous.then(() => this.publishOrdered(key, namespace, topic, payload));
|
|
138
|
+
this.publishChains.set(key, publishPromise.catch(() => { }));
|
|
139
|
+
return publishPromise;
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Yields topic's messages after options.cursor, or from the oldest retained.
|
|
144
|
+
* If the connection drops, it resubscribes from the last message yielded, so
|
|
145
|
+
* nothing is skipped or repeated. Ends when the server hangs up an idle
|
|
146
|
+
* subscription, options.signal aborts, or the caller stops iterating; throws
|
|
147
|
+
* on errors a retry can't fix, such as an expired cursor.
|
|
148
|
+
* @param topic - the topic to read from
|
|
149
|
+
* @param options - optional namespace override, resume cursor, and abort signal
|
|
150
|
+
*/
|
|
151
|
+
events(topic, options) {
|
|
152
|
+
return __asyncGenerator(this, arguments, function* events_1() {
|
|
153
|
+
var _a, e_1, _b, _c;
|
|
154
|
+
var _d;
|
|
155
|
+
const namespace = (_d = options === null || options === void 0 ? void 0 : options.namespace) !== null && _d !== void 0 ? _d : '';
|
|
156
|
+
const signal = options === null || options === void 0 ? void 0 : options.signal;
|
|
157
|
+
let { cursor } = options !== null && options !== void 0 ? options : {};
|
|
158
|
+
let failures = 0;
|
|
159
|
+
for (let attempt = 0;; attempt += 1) {
|
|
160
|
+
try {
|
|
161
|
+
const stream = this.grpc.subscribe({ namespace, topic, cursor }, { signal });
|
|
162
|
+
try {
|
|
163
|
+
for (var _e = true, stream_1 = (e_1 = void 0, __asyncValues(stream)), stream_1_1; stream_1_1 = yield __await(stream_1.next()), _a = stream_1_1.done, !_a; _e = true) {
|
|
164
|
+
_c = stream_1_1.value;
|
|
165
|
+
_e = false;
|
|
166
|
+
const msg = _c;
|
|
167
|
+
if (msg.hangup) {
|
|
168
|
+
return yield __await(void 0);
|
|
169
|
+
}
|
|
170
|
+
failures = 0;
|
|
171
|
+
for (const entry of msg.entries) {
|
|
172
|
+
({ cursor } = entry);
|
|
173
|
+
yield yield __await({
|
|
174
|
+
payload: entry.payload,
|
|
175
|
+
cursor: entry.cursor,
|
|
176
|
+
createdAt: entry.createdAt,
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
182
|
+
finally {
|
|
183
|
+
try {
|
|
184
|
+
if (!_e && !_a && (_b = stream_1.return)) yield __await(_b.call(stream_1));
|
|
185
|
+
}
|
|
186
|
+
finally { if (e_1) throw e_1.error; }
|
|
187
|
+
}
|
|
188
|
+
// ending without a hangup means the engine went away, e.g. it is shutting down
|
|
189
|
+
}
|
|
190
|
+
catch (err) {
|
|
191
|
+
if (signal === null || signal === void 0 ? void 0 : signal.aborted) {
|
|
192
|
+
return yield __await(void 0);
|
|
193
|
+
}
|
|
194
|
+
if (!shouldResubscribe(err, attempt)) {
|
|
195
|
+
throw err;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
const delayMs = Math.min(resubscribeMinDelayMs * 2 ** failures, resubscribeMaxDelayMs);
|
|
199
|
+
failures += 1;
|
|
200
|
+
try {
|
|
201
|
+
yield __await((0, sleep_1.default)(delayMs * (0.5 + Math.random() / 2), signal));
|
|
202
|
+
}
|
|
203
|
+
catch (_f) {
|
|
204
|
+
return yield __await(void 0);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
exports.StreamsClient = StreamsClient;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { HatchetClient } from '../..';
|
|
2
|
+
export type PublishLatencyStats = {
|
|
3
|
+
count: number;
|
|
4
|
+
avgMs: number;
|
|
5
|
+
p50Ms: number;
|
|
6
|
+
p99Ms: number;
|
|
7
|
+
maxMs: number;
|
|
8
|
+
throughputPerSec: number;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Times `count` sequential publishes, after `warmupCount` unmeasured ones
|
|
12
|
+
* absorb connection setup and topic creation.
|
|
13
|
+
*/
|
|
14
|
+
export declare function measurePublishLatency(hatchet: HatchetClient, topic: string, payload: Uint8Array | string, count: number, warmupCount?: number): Promise<PublishLatencyStats>;
|
|
15
|
+
export declare function formatPublishLatency(stats: PublishLatencyStats): string;
|
|
@@ -0,0 +1,50 @@
|
|
|
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.measurePublishLatency = measurePublishLatency;
|
|
13
|
+
exports.formatPublishLatency = formatPublishLatency;
|
|
14
|
+
const perf_hooks_1 = require("perf_hooks");
|
|
15
|
+
function percentile(sorted, p) {
|
|
16
|
+
return sorted[Math.min(sorted.length - 1, Math.floor(sorted.length * p))];
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Times `count` sequential publishes, after `warmupCount` unmeasured ones
|
|
20
|
+
* absorb connection setup and topic creation.
|
|
21
|
+
*/
|
|
22
|
+
function measurePublishLatency(hatchet_1, topic_1, payload_1, count_1) {
|
|
23
|
+
return __awaiter(this, arguments, void 0, function* (hatchet, topic, payload, count, warmupCount = 5) {
|
|
24
|
+
for (let i = 0; i < warmupCount; i += 1) {
|
|
25
|
+
yield hatchet.streams.publish(topic, payload);
|
|
26
|
+
}
|
|
27
|
+
const durationsMs = [];
|
|
28
|
+
const start = perf_hooks_1.performance.now();
|
|
29
|
+
for (let i = 0; i < count; i += 1) {
|
|
30
|
+
const before = perf_hooks_1.performance.now();
|
|
31
|
+
yield hatchet.streams.publish(topic, payload);
|
|
32
|
+
durationsMs.push(perf_hooks_1.performance.now() - before);
|
|
33
|
+
}
|
|
34
|
+
const totalMs = perf_hooks_1.performance.now() - start;
|
|
35
|
+
const sorted = [...durationsMs].sort((a, b) => a - b);
|
|
36
|
+
return {
|
|
37
|
+
count,
|
|
38
|
+
avgMs: durationsMs.reduce((sum, d) => sum + d, 0) / count,
|
|
39
|
+
p50Ms: percentile(sorted, 0.5),
|
|
40
|
+
p99Ms: percentile(sorted, 0.99),
|
|
41
|
+
maxMs: sorted[sorted.length - 1],
|
|
42
|
+
throughputPerSec: (count / totalMs) * 1000,
|
|
43
|
+
};
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
function formatPublishLatency(stats) {
|
|
47
|
+
const fmt = (ms) => ms.toFixed(2);
|
|
48
|
+
return (`avg=${fmt(stats.avgMs)}ms p50=${fmt(stats.p50Ms)}ms p99=${fmt(stats.p99Ms)}ms ` +
|
|
49
|
+
`max=${fmt(stats.maxMs)}ms throughput=${fmt(stats.throughputPerSec)}/s`);
|
|
50
|
+
}
|
|
@@ -69,11 +69,15 @@ exports.callbackOrderingMid = hatchet_client_1.hatchet.durableTask({
|
|
|
69
69
|
};
|
|
70
70
|
}),
|
|
71
71
|
});
|
|
72
|
+
// The root is never evicted. The ordering property under test lives in the
|
|
73
|
+
// mids, and the worker evicts one waiting run per server round trip, oldest
|
|
74
|
+
// wait first: evictable roots register before every mid and would consume the
|
|
75
|
+
// sweep for as long as it takes to ack all of them before any mid is reached.
|
|
72
76
|
exports.callbackOrderingRoot = hatchet_client_1.hatchet.durableTask({
|
|
73
77
|
name: `${WORKFLOW_PREFIX}-root`,
|
|
74
78
|
executionTimeout: '10m',
|
|
75
79
|
retries: 0,
|
|
76
|
-
evictionPolicy:
|
|
80
|
+
evictionPolicy: { ttl: undefined, allowCapacityEviction: false, priority: 0 },
|
|
77
81
|
fn: (input, ctx) => __awaiter(void 0, void 0, void 0, function* () {
|
|
78
82
|
var _a;
|
|
79
83
|
const durables = (_a = input.durables) !== null && _a !== void 0 ? _a : exports.ROOT_DEFAULTS.durables;
|
package/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const HATCHET_VERSION = "1.34.0
|
|
1
|
+
export declare const HATCHET_VERSION = "1.34.0";
|
package/version.js
CHANGED