@arbitro/client 0.2.0 → 0.5.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 +99 -21
- package/dist/chunk-C2QLJBAC.mjs +102 -0
- package/dist/chunk-C2QLJBAC.mjs.map +1 -0
- package/dist/chunk-GW36GP2C.mjs +124 -0
- package/dist/chunk-GW36GP2C.mjs.map +1 -0
- package/dist/constants-57DO6N3H.mjs +33 -0
- package/dist/constants-57DO6N3H.mjs.map +1 -0
- package/dist/index.d.mts +129 -1
- package/dist/index.d.ts +129 -1
- package/dist/index.js +680 -95
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +439 -99
- package/dist/index.mjs.map +1 -1
- package/dist/publish-BSVUMN7T.mjs +14 -0
- package/dist/publish-BSVUMN7T.mjs.map +1 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -5,6 +5,9 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
|
5
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
6
|
var __getProtoOf = Object.getPrototypeOf;
|
|
7
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __esm = (fn, res) => function __init() {
|
|
9
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
10
|
+
};
|
|
8
11
|
var __export = (target, all) => {
|
|
9
12
|
for (var name in all)
|
|
10
13
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
@@ -27,14 +30,248 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
27
30
|
));
|
|
28
31
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
32
|
|
|
33
|
+
// src/proto/constants.ts
|
|
34
|
+
var constants_exports = {};
|
|
35
|
+
__export(constants_exports, {
|
|
36
|
+
Action: () => Action,
|
|
37
|
+
CURRENT_VERSION: () => CURRENT_VERSION,
|
|
38
|
+
Cap: () => Cap,
|
|
39
|
+
EntryFlag: () => EntryFlag,
|
|
40
|
+
Flag: () => Flag,
|
|
41
|
+
HEADER_SIZE: () => HEADER_SIZE,
|
|
42
|
+
HELLO_SIZE: () => HELLO_SIZE,
|
|
43
|
+
MAGIC_V2: () => MAGIC_V2,
|
|
44
|
+
OFF_ACTION: () => OFF_ACTION,
|
|
45
|
+
OFF_ENTRY_FLAGS: () => OFF_ENTRY_FLAGS,
|
|
46
|
+
OFF_FLAGS: () => OFF_FLAGS,
|
|
47
|
+
OFF_MSG_LEN: () => OFF_MSG_LEN,
|
|
48
|
+
OFF_SEQ: () => OFF_SEQ,
|
|
49
|
+
Role: () => Role
|
|
50
|
+
});
|
|
51
|
+
var MAGIC_V2, HELLO_SIZE, CURRENT_VERSION, Role, Cap, HEADER_SIZE, OFF_ACTION, OFF_FLAGS, OFF_ENTRY_FLAGS, OFF_MSG_LEN, OFF_SEQ, Flag, EntryFlag, Action;
|
|
52
|
+
var init_constants = __esm({
|
|
53
|
+
"src/proto/constants.ts"() {
|
|
54
|
+
"use strict";
|
|
55
|
+
MAGIC_V2 = 843207233;
|
|
56
|
+
HELLO_SIZE = 8;
|
|
57
|
+
CURRENT_VERSION = 2;
|
|
58
|
+
Role = /* @__PURE__ */ ((Role2) => {
|
|
59
|
+
Role2[Role2["Client"] = 0] = "Client";
|
|
60
|
+
Role2[Role2["Server"] = 1] = "Server";
|
|
61
|
+
return Role2;
|
|
62
|
+
})(Role || {});
|
|
63
|
+
Cap = /* @__PURE__ */ ((Cap2) => {
|
|
64
|
+
Cap2[Cap2["Headers"] = 1] = "Headers";
|
|
65
|
+
Cap2[Cap2["Reply"] = 2] = "Reply";
|
|
66
|
+
Cap2[Cap2["BatchHeaders"] = 4] = "BatchHeaders";
|
|
67
|
+
Cap2[Cap2["CompressedPayload"] = 8] = "CompressedPayload";
|
|
68
|
+
return Cap2;
|
|
69
|
+
})(Cap || {});
|
|
70
|
+
HEADER_SIZE = 16;
|
|
71
|
+
OFF_ACTION = 0;
|
|
72
|
+
OFF_FLAGS = 2;
|
|
73
|
+
OFF_ENTRY_FLAGS = 3;
|
|
74
|
+
OFF_MSG_LEN = 4;
|
|
75
|
+
OFF_SEQ = 8;
|
|
76
|
+
Flag = /* @__PURE__ */ ((Flag3) => {
|
|
77
|
+
Flag3[Flag3["None"] = 0] = "None";
|
|
78
|
+
Flag3[Flag3["AckReq"] = 1] = "AckReq";
|
|
79
|
+
Flag3[Flag3["Dup"] = 2] = "Dup";
|
|
80
|
+
Flag3[Flag3["PriorityHigh"] = 4] = "PriorityHigh";
|
|
81
|
+
return Flag3;
|
|
82
|
+
})(Flag || {});
|
|
83
|
+
EntryFlag = /* @__PURE__ */ ((EntryFlag2) => {
|
|
84
|
+
EntryFlag2[EntryFlag2["None"] = 0] = "None";
|
|
85
|
+
EntryFlag2[EntryFlag2["Retain"] = 1] = "Retain";
|
|
86
|
+
EntryFlag2[EntryFlag2["Compressed"] = 2] = "Compressed";
|
|
87
|
+
EntryFlag2[EntryFlag2["NoBackpressure"] = 4] = "NoBackpressure";
|
|
88
|
+
return EntryFlag2;
|
|
89
|
+
})(EntryFlag || {});
|
|
90
|
+
Action = /* @__PURE__ */ ((Action2) => {
|
|
91
|
+
Action2[Action2["Hello"] = 1] = "Hello";
|
|
92
|
+
Action2[Action2["Auth"] = 2] = "Auth";
|
|
93
|
+
Action2[Action2["Publish"] = 257] = "Publish";
|
|
94
|
+
Action2[Action2["PublishAccumulate"] = 258] = "PublishAccumulate";
|
|
95
|
+
Action2[Action2["PublishBatch"] = 259] = "PublishBatch";
|
|
96
|
+
Action2[Action2["PublishWithReply"] = 260] = "PublishWithReply";
|
|
97
|
+
Action2[Action2["PublishWithHeaders"] = 261] = "PublishWithHeaders";
|
|
98
|
+
Action2[Action2["PublishBatchWithHeaders"] = 262] = "PublishBatchWithHeaders";
|
|
99
|
+
Action2[Action2["Deliver"] = 512] = "Deliver";
|
|
100
|
+
Action2[Action2["Ack"] = 513] = "Ack";
|
|
101
|
+
Action2[Action2["Nack"] = 514] = "Nack";
|
|
102
|
+
Action2[Action2["RepOk"] = 515] = "RepOk";
|
|
103
|
+
Action2[Action2["RepError"] = 516] = "RepError";
|
|
104
|
+
Action2[Action2["RepBatch"] = 517] = "RepBatch";
|
|
105
|
+
Action2[Action2["BatchAck"] = 518] = "BatchAck";
|
|
106
|
+
Action2[Action2["FanoutBatch"] = 519] = "FanoutBatch";
|
|
107
|
+
Action2[Action2["AckSync"] = 520] = "AckSync";
|
|
108
|
+
Action2[Action2["BatchAckSync"] = 521] = "BatchAckSync";
|
|
109
|
+
Action2[Action2["BatchNack"] = 522] = "BatchNack";
|
|
110
|
+
Action2[Action2["Subscribe"] = 769] = "Subscribe";
|
|
111
|
+
Action2[Action2["Unsubscribe"] = 770] = "Unsubscribe";
|
|
112
|
+
Action2[Action2["CreateStream"] = 1025] = "CreateStream";
|
|
113
|
+
Action2[Action2["DeleteStream"] = 1026] = "DeleteStream";
|
|
114
|
+
Action2[Action2["GetStream"] = 1027] = "GetStream";
|
|
115
|
+
Action2[Action2["ListStreams"] = 1028] = "ListStreams";
|
|
116
|
+
Action2[Action2["PurgeStream"] = 1029] = "PurgeStream";
|
|
117
|
+
Action2[Action2["DrainSubject"] = 1030] = "DrainSubject";
|
|
118
|
+
Action2[Action2["CreateConsumer"] = 1281] = "CreateConsumer";
|
|
119
|
+
Action2[Action2["DeleteConsumer"] = 1282] = "DeleteConsumer";
|
|
120
|
+
Action2[Action2["GetConsumer"] = 1283] = "GetConsumer";
|
|
121
|
+
Action2[Action2["ListConsumers"] = 1284] = "ListConsumers";
|
|
122
|
+
Action2[Action2["ConsumerStats"] = 1285] = "ConsumerStats";
|
|
123
|
+
Action2[Action2["PauseConsumer"] = 1286] = "PauseConsumer";
|
|
124
|
+
Action2[Action2["ResumeConsumer"] = 1287] = "ResumeConsumer";
|
|
125
|
+
Action2[Action2["PublishDelayed"] = 2049] = "PublishDelayed";
|
|
126
|
+
Action2[Action2["Ping"] = 1537] = "Ping";
|
|
127
|
+
Action2[Action2["Pong"] = 1538] = "Pong";
|
|
128
|
+
Action2[Action2["Connect"] = 1539] = "Connect";
|
|
129
|
+
Action2[Action2["Connected"] = 1540] = "Connected";
|
|
130
|
+
Action2[Action2["Disconnect"] = 1541] = "Disconnect";
|
|
131
|
+
Action2[Action2["CreateCron"] = 1793] = "CreateCron";
|
|
132
|
+
Action2[Action2["DeleteCron"] = 1794] = "DeleteCron";
|
|
133
|
+
Action2[Action2["ListCrons"] = 1795] = "ListCrons";
|
|
134
|
+
Action2[Action2["CronFire"] = 1796] = "CronFire";
|
|
135
|
+
Action2[Action2["CronAck"] = 1797] = "CronAck";
|
|
136
|
+
return Action2;
|
|
137
|
+
})(Action || {});
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
// src/proto/frame.ts
|
|
142
|
+
function frame(action, seq, bodyLen, flags = 0, entryFlags = 0) {
|
|
143
|
+
const buf = Buffer.allocUnsafe(HEADER_SIZE + bodyLen);
|
|
144
|
+
buf.writeUInt16LE(action, OFF_ACTION);
|
|
145
|
+
buf[OFF_FLAGS] = flags;
|
|
146
|
+
buf[OFF_ENTRY_FLAGS] = entryFlags;
|
|
147
|
+
buf.writeUInt32LE(bodyLen, OFF_MSG_LEN);
|
|
148
|
+
buf.writeBigUInt64LE(seq, OFF_SEQ);
|
|
149
|
+
return buf;
|
|
150
|
+
}
|
|
151
|
+
function packHello(caps = 2 /* Reply */) {
|
|
152
|
+
const buf = Buffer.allocUnsafe(HELLO_SIZE);
|
|
153
|
+
buf.writeUInt32LE(MAGIC_V2, 0);
|
|
154
|
+
buf[4] = CURRENT_VERSION;
|
|
155
|
+
buf[5] = 0 /* Client */;
|
|
156
|
+
buf.writeUInt16LE(caps, 6);
|
|
157
|
+
return buf;
|
|
158
|
+
}
|
|
159
|
+
function packDisconnect(seq) {
|
|
160
|
+
return frame(1541 /* Disconnect */, seq, 0);
|
|
161
|
+
}
|
|
162
|
+
var init_frame = __esm({
|
|
163
|
+
"src/proto/frame.ts"() {
|
|
164
|
+
"use strict";
|
|
165
|
+
init_constants();
|
|
166
|
+
}
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
// src/proto/publish.ts
|
|
170
|
+
var publish_exports = {};
|
|
171
|
+
__export(publish_exports, {
|
|
172
|
+
packPublish: () => packPublish,
|
|
173
|
+
packPublishBatch: () => packPublishBatch,
|
|
174
|
+
packPublishDelayed: () => packPublishDelayed,
|
|
175
|
+
packPublishWithReply: () => packPublishWithReply
|
|
176
|
+
});
|
|
177
|
+
function packPublish(seq, streamId2, subject, payload, flags = 0, entryFlags = 0, msgId = EMPTY) {
|
|
178
|
+
const buf = frame(
|
|
179
|
+
257 /* Publish */,
|
|
180
|
+
seq,
|
|
181
|
+
8 + subject.length + msgId.length + payload.length,
|
|
182
|
+
flags,
|
|
183
|
+
entryFlags
|
|
184
|
+
);
|
|
185
|
+
buf.writeUInt32LE(streamId2, HEADER_SIZE);
|
|
186
|
+
buf.writeUInt16LE(subject.length, HEADER_SIZE + 4);
|
|
187
|
+
buf.writeUInt16LE(msgId.length, HEADER_SIZE + 6);
|
|
188
|
+
let off = HEADER_SIZE + 8;
|
|
189
|
+
subject.copy(buf, off);
|
|
190
|
+
off += subject.length;
|
|
191
|
+
msgId.copy(buf, off);
|
|
192
|
+
off += msgId.length;
|
|
193
|
+
payload.copy(buf, off);
|
|
194
|
+
return buf;
|
|
195
|
+
}
|
|
196
|
+
function packPublishWithReply(seq, streamId2, subject, replyTo, payload, flags = 0, entryFlags = 0) {
|
|
197
|
+
const tail = subject.length + replyTo.length + payload.length;
|
|
198
|
+
const buf = frame(260 /* PublishWithReply */, seq, 12 + tail, flags, entryFlags);
|
|
199
|
+
buf.writeUInt32LE(streamId2, HEADER_SIZE);
|
|
200
|
+
buf.writeUInt16LE(subject.length, HEADER_SIZE + 4);
|
|
201
|
+
buf.writeUInt16LE(replyTo.length, HEADER_SIZE + 6);
|
|
202
|
+
buf.writeUInt32LE(0, HEADER_SIZE + 8);
|
|
203
|
+
let off = HEADER_SIZE + 12;
|
|
204
|
+
subject.copy(buf, off);
|
|
205
|
+
off += subject.length;
|
|
206
|
+
replyTo.copy(buf, off);
|
|
207
|
+
off += replyTo.length;
|
|
208
|
+
payload.copy(buf, off);
|
|
209
|
+
return buf;
|
|
210
|
+
}
|
|
211
|
+
function packPublishDelayed(seq, streamId2, subject, payload, delayMs, flags = 0, entryFlags = 0) {
|
|
212
|
+
const buf = frame(
|
|
213
|
+
2049 /* PublishDelayed */,
|
|
214
|
+
seq,
|
|
215
|
+
16 + subject.length + payload.length,
|
|
216
|
+
flags,
|
|
217
|
+
entryFlags
|
|
218
|
+
);
|
|
219
|
+
buf.writeUInt32LE(streamId2, HEADER_SIZE);
|
|
220
|
+
buf.writeUInt16LE(subject.length, HEADER_SIZE + 4);
|
|
221
|
+
buf.writeUInt16LE(0, HEADER_SIZE + 6);
|
|
222
|
+
buf.writeBigUInt64LE(delayMs, HEADER_SIZE + 8);
|
|
223
|
+
let off = HEADER_SIZE + 16;
|
|
224
|
+
subject.copy(buf, off);
|
|
225
|
+
off += subject.length;
|
|
226
|
+
payload.copy(buf, off);
|
|
227
|
+
return buf;
|
|
228
|
+
}
|
|
229
|
+
function packPublishBatch(seq, streamId2, entries, flags = 0, entryFlags = 0) {
|
|
230
|
+
let tail = 0;
|
|
231
|
+
for (const e of entries) {
|
|
232
|
+
const midLen = e.msgId ? e.msgId.length : 0;
|
|
233
|
+
tail += 8 + e.subject.length + midLen + e.payload.length;
|
|
234
|
+
}
|
|
235
|
+
const buf = frame(259 /* PublishBatch */, seq, 8 + tail, flags, entryFlags);
|
|
236
|
+
buf.writeUInt32LE(streamId2, HEADER_SIZE);
|
|
237
|
+
buf.writeUInt32LE(entries.length, HEADER_SIZE + 4);
|
|
238
|
+
let off = HEADER_SIZE + 8;
|
|
239
|
+
for (const e of entries) {
|
|
240
|
+
const mid = e.msgId ?? EMPTY;
|
|
241
|
+
buf.writeUInt16LE(e.subject.length, off);
|
|
242
|
+
buf.writeUInt16LE(mid.length, off + 2);
|
|
243
|
+
buf.writeUInt32LE(e.payload.length, off + 4);
|
|
244
|
+
off += 8;
|
|
245
|
+
buf.write(e.subject, off);
|
|
246
|
+
off += e.subject.length;
|
|
247
|
+
mid.copy(buf, off);
|
|
248
|
+
off += mid.length;
|
|
249
|
+
e.payload.copy(buf, off);
|
|
250
|
+
off += e.payload.length;
|
|
251
|
+
}
|
|
252
|
+
return buf;
|
|
253
|
+
}
|
|
254
|
+
var EMPTY;
|
|
255
|
+
var init_publish = __esm({
|
|
256
|
+
"src/proto/publish.ts"() {
|
|
257
|
+
"use strict";
|
|
258
|
+
init_constants();
|
|
259
|
+
init_frame();
|
|
260
|
+
EMPTY = Buffer.alloc(0);
|
|
261
|
+
}
|
|
262
|
+
});
|
|
263
|
+
|
|
30
264
|
// src/index.ts
|
|
31
265
|
var index_exports = {};
|
|
32
266
|
__export(index_exports, {
|
|
33
267
|
AckPolicy: () => AckPolicy,
|
|
34
268
|
ArbitroClient: () => ArbitroClient,
|
|
35
269
|
ArbitroError: () => ArbitroError,
|
|
270
|
+
COMPENSATION_BIT: () => COMPENSATION_BIT,
|
|
36
271
|
Codec: () => Codec,
|
|
37
272
|
Consumer: () => Consumer,
|
|
273
|
+
CronBuilder: () => CronBuilder,
|
|
274
|
+
CronHandle: () => CronHandle,
|
|
38
275
|
DeliverPolicy: () => DeliverPolicy,
|
|
39
276
|
ErrorCode: () => ErrorCode,
|
|
40
277
|
JournalType: () => JournalType,
|
|
@@ -44,6 +281,8 @@ __export(index_exports, {
|
|
|
44
281
|
StringCodec: () => StringCodec,
|
|
45
282
|
Subscription: () => Subscription,
|
|
46
283
|
Topic: () => Topic,
|
|
284
|
+
WorkflowBuilder: () => WorkflowBuilder,
|
|
285
|
+
WorkflowHandle: () => WorkflowHandle,
|
|
47
286
|
decodeJson: () => decodeJson,
|
|
48
287
|
decodeString: () => decodeString,
|
|
49
288
|
encodeJson: () => encodeJson,
|
|
@@ -234,102 +473,16 @@ function makeLazyMessage(raw, codec, fields, onAck, onNack, onNackDelay) {
|
|
|
234
473
|
return msg;
|
|
235
474
|
}
|
|
236
475
|
|
|
237
|
-
// src/
|
|
238
|
-
|
|
239
|
-
var HELLO_SIZE = 8;
|
|
240
|
-
var CURRENT_VERSION = 2;
|
|
241
|
-
var HEADER_SIZE = 16;
|
|
242
|
-
var OFF_ACTION = 0;
|
|
243
|
-
var OFF_FLAGS = 2;
|
|
244
|
-
var OFF_ENTRY_FLAGS = 3;
|
|
245
|
-
var OFF_MSG_LEN = 4;
|
|
246
|
-
var OFF_SEQ = 8;
|
|
247
|
-
|
|
248
|
-
// src/proto/frame.ts
|
|
249
|
-
function frame(action, seq, bodyLen, flags = 0, entryFlags = 0) {
|
|
250
|
-
const buf = Buffer.allocUnsafe(HEADER_SIZE + bodyLen);
|
|
251
|
-
buf.writeUInt16LE(action, OFF_ACTION);
|
|
252
|
-
buf[OFF_FLAGS] = flags;
|
|
253
|
-
buf[OFF_ENTRY_FLAGS] = entryFlags;
|
|
254
|
-
buf.writeUInt32LE(bodyLen, OFF_MSG_LEN);
|
|
255
|
-
buf.writeBigUInt64LE(seq, OFF_SEQ);
|
|
256
|
-
return buf;
|
|
257
|
-
}
|
|
258
|
-
function packHello(caps = 2 /* Reply */) {
|
|
259
|
-
const buf = Buffer.allocUnsafe(HELLO_SIZE);
|
|
260
|
-
buf.writeUInt32LE(MAGIC_V2, 0);
|
|
261
|
-
buf[4] = CURRENT_VERSION;
|
|
262
|
-
buf[5] = 0 /* Client */;
|
|
263
|
-
buf.writeUInt16LE(caps, 6);
|
|
264
|
-
return buf;
|
|
265
|
-
}
|
|
266
|
-
function packDisconnect(seq) {
|
|
267
|
-
return frame(1541 /* Disconnect */, seq, 0);
|
|
268
|
-
}
|
|
476
|
+
// src/message/message.ts
|
|
477
|
+
init_constants();
|
|
269
478
|
|
|
270
|
-
// src/proto/
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
const buf = frame(
|
|
274
|
-
257 /* Publish */,
|
|
275
|
-
seq,
|
|
276
|
-
8 + subject.length + msgId.length + payload.length,
|
|
277
|
-
flags,
|
|
278
|
-
entryFlags
|
|
279
|
-
);
|
|
280
|
-
buf.writeUInt32LE(streamId2, HEADER_SIZE);
|
|
281
|
-
buf.writeUInt16LE(subject.length, HEADER_SIZE + 4);
|
|
282
|
-
buf.writeUInt16LE(msgId.length, HEADER_SIZE + 6);
|
|
283
|
-
let off = HEADER_SIZE + 8;
|
|
284
|
-
subject.copy(buf, off);
|
|
285
|
-
off += subject.length;
|
|
286
|
-
msgId.copy(buf, off);
|
|
287
|
-
off += msgId.length;
|
|
288
|
-
payload.copy(buf, off);
|
|
289
|
-
return buf;
|
|
290
|
-
}
|
|
291
|
-
function packPublishWithReply(seq, streamId2, subject, replyTo, payload, flags = 0, entryFlags = 0) {
|
|
292
|
-
const tail = subject.length + replyTo.length + payload.length;
|
|
293
|
-
const buf = frame(260 /* PublishWithReply */, seq, 12 + tail, flags, entryFlags);
|
|
294
|
-
buf.writeUInt32LE(streamId2, HEADER_SIZE);
|
|
295
|
-
buf.writeUInt16LE(subject.length, HEADER_SIZE + 4);
|
|
296
|
-
buf.writeUInt16LE(replyTo.length, HEADER_SIZE + 6);
|
|
297
|
-
buf.writeUInt32LE(0, HEADER_SIZE + 8);
|
|
298
|
-
let off = HEADER_SIZE + 12;
|
|
299
|
-
subject.copy(buf, off);
|
|
300
|
-
off += subject.length;
|
|
301
|
-
replyTo.copy(buf, off);
|
|
302
|
-
off += replyTo.length;
|
|
303
|
-
payload.copy(buf, off);
|
|
304
|
-
return buf;
|
|
305
|
-
}
|
|
306
|
-
function packPublishBatch(seq, streamId2, entries, flags = 0, entryFlags = 0) {
|
|
307
|
-
let tail = 0;
|
|
308
|
-
for (const e of entries) {
|
|
309
|
-
const midLen = e.msgId ? e.msgId.length : 0;
|
|
310
|
-
tail += 8 + e.subject.length + midLen + e.payload.length;
|
|
311
|
-
}
|
|
312
|
-
const buf = frame(259 /* PublishBatch */, seq, 8 + tail, flags, entryFlags);
|
|
313
|
-
buf.writeUInt32LE(streamId2, HEADER_SIZE);
|
|
314
|
-
buf.writeUInt32LE(entries.length, HEADER_SIZE + 4);
|
|
315
|
-
let off = HEADER_SIZE + 8;
|
|
316
|
-
for (const e of entries) {
|
|
317
|
-
const mid = e.msgId ?? EMPTY;
|
|
318
|
-
buf.writeUInt16LE(e.subject.length, off);
|
|
319
|
-
buf.writeUInt16LE(mid.length, off + 2);
|
|
320
|
-
buf.writeUInt32LE(e.payload.length, off + 4);
|
|
321
|
-
off += 8;
|
|
322
|
-
buf.write(e.subject, off);
|
|
323
|
-
off += e.subject.length;
|
|
324
|
-
mid.copy(buf, off);
|
|
325
|
-
off += mid.length;
|
|
326
|
-
e.payload.copy(buf, off);
|
|
327
|
-
off += e.payload.length;
|
|
328
|
-
}
|
|
329
|
-
return buf;
|
|
330
|
-
}
|
|
479
|
+
// src/proto/v2.ts
|
|
480
|
+
init_frame();
|
|
481
|
+
init_publish();
|
|
331
482
|
|
|
332
483
|
// src/proto/delivery.ts
|
|
484
|
+
init_constants();
|
|
485
|
+
init_frame();
|
|
333
486
|
function packCold(action, seq, body) {
|
|
334
487
|
const utf8 = Buffer.from(JSON.stringify(body), "utf8");
|
|
335
488
|
const buf = frame(action, seq, utf8.length);
|
|
@@ -376,6 +529,8 @@ function packBatchNack(seq, consumerId, entries) {
|
|
|
376
529
|
}
|
|
377
530
|
|
|
378
531
|
// src/proto/manage.ts
|
|
532
|
+
init_constants();
|
|
533
|
+
init_frame();
|
|
379
534
|
function packCold2(action, seq, body) {
|
|
380
535
|
const utf8 = Buffer.from(JSON.stringify(body), "utf8");
|
|
381
536
|
const buf = frame(action, seq, utf8.length);
|
|
@@ -583,6 +738,7 @@ var net = __toESM(require("net"));
|
|
|
583
738
|
var tls = __toESM(require("tls"));
|
|
584
739
|
|
|
585
740
|
// src/proto/framer.ts
|
|
741
|
+
init_constants();
|
|
586
742
|
var ENVELOPE_MSG_LEN_OFF = 8;
|
|
587
743
|
var Framer = class {
|
|
588
744
|
buf = Buffer.allocUnsafe(65536);
|
|
@@ -614,6 +770,9 @@ var Framer = class {
|
|
|
614
770
|
}
|
|
615
771
|
};
|
|
616
772
|
|
|
773
|
+
// src/net/connection.ts
|
|
774
|
+
init_constants();
|
|
775
|
+
|
|
617
776
|
// src/common/logger.ts
|
|
618
777
|
var noop = (() => {
|
|
619
778
|
});
|
|
@@ -629,6 +788,39 @@ function resolveLogger(logger) {
|
|
|
629
788
|
return logger ?? NOOP;
|
|
630
789
|
}
|
|
631
790
|
|
|
791
|
+
// src/cron/cron-frame.ts
|
|
792
|
+
init_constants();
|
|
793
|
+
init_frame();
|
|
794
|
+
function packCreateCron(seq, body) {
|
|
795
|
+
const json = Buffer.from(JSON.stringify(body), "utf8");
|
|
796
|
+
const buf = frame(1793 /* CreateCron */, seq, json.length);
|
|
797
|
+
json.copy(buf, HEADER_SIZE);
|
|
798
|
+
return buf;
|
|
799
|
+
}
|
|
800
|
+
function packDeleteCron(seq, name) {
|
|
801
|
+
const buf = frame(1794 /* DeleteCron */, seq, name.length);
|
|
802
|
+
name.copy(buf, HEADER_SIZE);
|
|
803
|
+
return buf;
|
|
804
|
+
}
|
|
805
|
+
var CRON_FIRE_FIXED = 2 + 8 + 8;
|
|
806
|
+
function decodeCronFire(body) {
|
|
807
|
+
if (body.length < CRON_FIRE_FIXED) return void 0;
|
|
808
|
+
const nameLen = body.readUInt16LE(0);
|
|
809
|
+
if (body.length < CRON_FIRE_FIXED + nameLen) return void 0;
|
|
810
|
+
const fireTimeMs = body.readBigUInt64LE(2);
|
|
811
|
+
const fireCount = body.readBigUInt64LE(10);
|
|
812
|
+
const name = body.subarray(18, 18 + nameLen).toString();
|
|
813
|
+
return { name, fireTimeMs, fireCount };
|
|
814
|
+
}
|
|
815
|
+
function packCronAck(seq, name, ok) {
|
|
816
|
+
const bodyLen = 3 + name.length;
|
|
817
|
+
const buf = frame(1797 /* CronAck */, seq, bodyLen);
|
|
818
|
+
buf.writeUInt16LE(name.length, HEADER_SIZE);
|
|
819
|
+
buf[HEADER_SIZE + 2] = ok ? 0 : 1;
|
|
820
|
+
name.copy(buf, HEADER_SIZE + 3);
|
|
821
|
+
return buf;
|
|
822
|
+
}
|
|
823
|
+
|
|
632
824
|
// src/net/connection.ts
|
|
633
825
|
function parseAddr(addr) {
|
|
634
826
|
const i = addr.lastIndexOf(":");
|
|
@@ -652,6 +844,7 @@ var Connection = class _Connection {
|
|
|
652
844
|
log;
|
|
653
845
|
activeSubs = /* @__PURE__ */ new Map();
|
|
654
846
|
metrics;
|
|
847
|
+
cronState;
|
|
655
848
|
attachSocket(socket) {
|
|
656
849
|
socket.setNoDelay(true);
|
|
657
850
|
socket.on("data", (chunk) => this.framer.push(chunk, (f) => this.onFrame(f)));
|
|
@@ -706,6 +899,10 @@ var Connection = class _Connection {
|
|
|
706
899
|
setMetrics(m) {
|
|
707
900
|
this.metrics = m;
|
|
708
901
|
}
|
|
902
|
+
/** Attach cron state so the connection can dispatch CronFire frames. */
|
|
903
|
+
setCronState(s) {
|
|
904
|
+
this.cronState = s;
|
|
905
|
+
}
|
|
709
906
|
// ── Frame routing ─────────────────────────────────────────────────────────
|
|
710
907
|
// Seq-based dispatch: match reply.header.seq → pending request. O(1).
|
|
711
908
|
resolvePending(frame2) {
|
|
@@ -757,6 +954,10 @@ var Connection = class _Connection {
|
|
|
757
954
|
this.handleBatchDeliver(frame2);
|
|
758
955
|
return;
|
|
759
956
|
}
|
|
957
|
+
case 1796 /* CronFire */: {
|
|
958
|
+
this.dispatchCronFire(frame2);
|
|
959
|
+
return;
|
|
960
|
+
}
|
|
760
961
|
case 1538 /* Pong */:
|
|
761
962
|
return;
|
|
762
963
|
default: {
|
|
@@ -806,6 +1007,19 @@ var Connection = class _Connection {
|
|
|
806
1007
|
off = tailEnd;
|
|
807
1008
|
}
|
|
808
1009
|
}
|
|
1010
|
+
// ── Cron dispatch ──────────────────────────────────────────────────────────
|
|
1011
|
+
dispatchCronFire(frame2) {
|
|
1012
|
+
const body = frame2.subarray(HEADER_SIZE);
|
|
1013
|
+
const view = decodeCronFire(body);
|
|
1014
|
+
if (!view) return;
|
|
1015
|
+
const handler = this.cronState?.getHandler(view.name);
|
|
1016
|
+
const nameBuf = Buffer.from(view.name);
|
|
1017
|
+
if (!handler) {
|
|
1018
|
+
this.send(packCronAck(this.nextSeq(), nameBuf, false));
|
|
1019
|
+
return;
|
|
1020
|
+
}
|
|
1021
|
+
handler({ name: view.name, fireTime: view.fireTimeMs, fireCount: view.fireCount }).then(() => this.send(packCronAck(this.nextSeq(), nameBuf, true))).catch(() => this.send(packCronAck(this.nextSeq(), nameBuf, false)));
|
|
1022
|
+
}
|
|
809
1023
|
// ── Subscriptions ─────────────────────────────────────────────────────────
|
|
810
1024
|
async sendSubscribeV2(consumerId, filter, handler, onRenew) {
|
|
811
1025
|
return new Promise((resolve, reject) => {
|
|
@@ -848,6 +1062,14 @@ var Connection = class _Connection {
|
|
|
848
1062
|
}).catch(() => {
|
|
849
1063
|
});
|
|
850
1064
|
}
|
|
1065
|
+
this.replayCrons();
|
|
1066
|
+
}
|
|
1067
|
+
replayCrons() {
|
|
1068
|
+
if (!this.cronState) return;
|
|
1069
|
+
for (const { config } of this.cronState.allConfigs()) {
|
|
1070
|
+
const seq = this.nextSeq();
|
|
1071
|
+
this.socket.write(packCreateCron(seq, config));
|
|
1072
|
+
}
|
|
851
1073
|
}
|
|
852
1074
|
// ── Routes (internal use) ─────────────────────────────────────────────────
|
|
853
1075
|
registerRoute(consumerId, handler) {
|
|
@@ -1131,6 +1353,7 @@ var ClientMetrics = class {
|
|
|
1131
1353
|
};
|
|
1132
1354
|
|
|
1133
1355
|
// src/stream/publish.ts
|
|
1356
|
+
init_constants();
|
|
1134
1357
|
var EMPTY2 = Buffer.alloc(0);
|
|
1135
1358
|
function toMsgIdBuf(id) {
|
|
1136
1359
|
if (id == null) return EMPTY2;
|
|
@@ -1162,6 +1385,89 @@ async function streamRequest(conn, sid, subject, data, timeoutMs) {
|
|
|
1162
1385
|
return Buffer.alloc(0);
|
|
1163
1386
|
}
|
|
1164
1387
|
|
|
1388
|
+
// src/client/client.ts
|
|
1389
|
+
init_constants();
|
|
1390
|
+
|
|
1391
|
+
// src/cron/cron-builder.ts
|
|
1392
|
+
var CronBuilder = class {
|
|
1393
|
+
constructor(conn, cronState, cronName) {
|
|
1394
|
+
this.conn = conn;
|
|
1395
|
+
this.cronState = cronState;
|
|
1396
|
+
this.cronName = cronName;
|
|
1397
|
+
}
|
|
1398
|
+
expr;
|
|
1399
|
+
timezone;
|
|
1400
|
+
timeoutMs = 3e4;
|
|
1401
|
+
allowOverlap = false;
|
|
1402
|
+
every(expression) {
|
|
1403
|
+
this.expr = expression;
|
|
1404
|
+
return this;
|
|
1405
|
+
}
|
|
1406
|
+
tz(timezone) {
|
|
1407
|
+
this.timezone = timezone;
|
|
1408
|
+
return this;
|
|
1409
|
+
}
|
|
1410
|
+
timeout(ms) {
|
|
1411
|
+
this.timeoutMs = ms;
|
|
1412
|
+
return this;
|
|
1413
|
+
}
|
|
1414
|
+
overlap(allow) {
|
|
1415
|
+
this.allowOverlap = allow;
|
|
1416
|
+
return this;
|
|
1417
|
+
}
|
|
1418
|
+
async run(handler) {
|
|
1419
|
+
if (!this.expr) throw new Error("cron expression required \u2014 call .every()");
|
|
1420
|
+
const body = {
|
|
1421
|
+
name: this.cronName,
|
|
1422
|
+
every: this.expr,
|
|
1423
|
+
tz: this.timezone,
|
|
1424
|
+
timeout_ms: this.timeoutMs,
|
|
1425
|
+
overlap: this.allowOverlap
|
|
1426
|
+
};
|
|
1427
|
+
const seq = this.conn.nextSeq();
|
|
1428
|
+
await this.conn.sendExpectReply(packCreateCron(seq, body));
|
|
1429
|
+
this.cronState.register(this.cronName, body, handler);
|
|
1430
|
+
return new CronHandle(this.conn, this.cronState, this.cronName);
|
|
1431
|
+
}
|
|
1432
|
+
};
|
|
1433
|
+
var CronHandle = class {
|
|
1434
|
+
constructor(conn, cronState, cronName) {
|
|
1435
|
+
this.conn = conn;
|
|
1436
|
+
this.cronState = cronState;
|
|
1437
|
+
this.cronName = cronName;
|
|
1438
|
+
}
|
|
1439
|
+
get name() {
|
|
1440
|
+
return this.cronName;
|
|
1441
|
+
}
|
|
1442
|
+
async stop() {
|
|
1443
|
+
const nameBuf = Buffer.from(this.cronName);
|
|
1444
|
+
const seq = this.conn.nextSeq();
|
|
1445
|
+
await this.conn.sendExpectReply(packDeleteCron(seq, nameBuf));
|
|
1446
|
+
this.cronState.remove(this.cronName);
|
|
1447
|
+
}
|
|
1448
|
+
};
|
|
1449
|
+
|
|
1450
|
+
// src/cron/cron-state.ts
|
|
1451
|
+
var CronState = class {
|
|
1452
|
+
handlers = /* @__PURE__ */ new Map();
|
|
1453
|
+
register(name, config, handler) {
|
|
1454
|
+
this.handlers.set(name, { handler, config });
|
|
1455
|
+
}
|
|
1456
|
+
remove(name) {
|
|
1457
|
+
this.handlers.delete(name);
|
|
1458
|
+
}
|
|
1459
|
+
getHandler(name) {
|
|
1460
|
+
return this.handlers.get(name)?.handler;
|
|
1461
|
+
}
|
|
1462
|
+
allConfigs() {
|
|
1463
|
+
const out = [];
|
|
1464
|
+
for (const [name, entry] of this.handlers) {
|
|
1465
|
+
out.push({ name, config: entry.config });
|
|
1466
|
+
}
|
|
1467
|
+
return out;
|
|
1468
|
+
}
|
|
1469
|
+
};
|
|
1470
|
+
|
|
1165
1471
|
// src/client/client.ts
|
|
1166
1472
|
var DEFAULT_CONFIG = {
|
|
1167
1473
|
servers: ["127.0.0.1:9898"],
|
|
@@ -1176,6 +1482,7 @@ var ArbitroClient = class {
|
|
|
1176
1482
|
logger;
|
|
1177
1483
|
sidCache = /* @__PURE__ */ new Map();
|
|
1178
1484
|
_metrics = new ClientMetrics();
|
|
1485
|
+
_cronState = new CronState();
|
|
1179
1486
|
constructor(config) {
|
|
1180
1487
|
this.cfg = { ...DEFAULT_CONFIG, ...config };
|
|
1181
1488
|
this.tls = config.tls;
|
|
@@ -1192,6 +1499,7 @@ var ArbitroClient = class {
|
|
|
1192
1499
|
this.logger
|
|
1193
1500
|
);
|
|
1194
1501
|
this.conn.setMetrics(this._metrics);
|
|
1502
|
+
this.conn.setCronState(this._cronState);
|
|
1195
1503
|
return this;
|
|
1196
1504
|
}
|
|
1197
1505
|
/**
|
|
@@ -1277,6 +1585,22 @@ var ArbitroClient = class {
|
|
|
1277
1585
|
const sid = await this.resolveStreamId(streamName);
|
|
1278
1586
|
return streamRequest(this.conn, sid, subject, data, timeoutMs);
|
|
1279
1587
|
}
|
|
1588
|
+
/**
|
|
1589
|
+
* Publish a message with a delivery delay. The broker parks the message
|
|
1590
|
+
* in its delayed journal and delivers it to consumers after `delayMs`
|
|
1591
|
+
* milliseconds. Returns a Promise that resolves once the broker confirms
|
|
1592
|
+
* receipt.
|
|
1593
|
+
*/
|
|
1594
|
+
async publishDelayed(streamName, subject, data, delayMs) {
|
|
1595
|
+
const sid = await this.resolveStreamId(streamName);
|
|
1596
|
+
const { packPublishDelayed: packPublishDelayed2 } = await Promise.resolve().then(() => (init_publish(), publish_exports));
|
|
1597
|
+
const { Flag: Flag3 } = await Promise.resolve().then(() => (init_constants(), constants_exports));
|
|
1598
|
+
const subj = Buffer.from(this.prefixed(subject));
|
|
1599
|
+
await this.conn.sendExpectReply(
|
|
1600
|
+
packPublishDelayed2(this.conn.nextSeq(), sid, subj, data, BigInt(delayMs), Flag3.AckReq)
|
|
1601
|
+
);
|
|
1602
|
+
this._metrics.publishesSent++;
|
|
1603
|
+
}
|
|
1280
1604
|
async subscribe(streamName, configOrCb, callbackOrOpts, opts) {
|
|
1281
1605
|
let config;
|
|
1282
1606
|
let callback;
|
|
@@ -1385,7 +1709,7 @@ var ArbitroClient = class {
|
|
|
1385
1709
|
async createConsumerRaw(streamName, config) {
|
|
1386
1710
|
const sid = await this.resolveStreamId(streamName);
|
|
1387
1711
|
const name = Buffer.from(config.name ?? streamName);
|
|
1388
|
-
const group = Buffer.from(config.name ?? streamName);
|
|
1712
|
+
const group = Buffer.from(config.group ?? config.name ?? streamName);
|
|
1389
1713
|
const filter = Buffer.from(config.filter ?? "");
|
|
1390
1714
|
const ackPolicyByte = config.ackPolicy === "none" /* None */ ? 0 : 1;
|
|
1391
1715
|
const opts = {
|
|
@@ -1396,7 +1720,7 @@ var ArbitroClient = class {
|
|
|
1396
1720
|
maxInflight: config.maxAckPending ?? 0,
|
|
1397
1721
|
ackPolicy: ackPolicyByte,
|
|
1398
1722
|
deliverPolicy: deliverPolicyToU8(config.deliverPolicy),
|
|
1399
|
-
deliverMode: config.fanout ?
|
|
1723
|
+
deliverMode: config.fanout ? 0 : 1,
|
|
1400
1724
|
ackWaitMs: config.ackWaitMs ?? 0,
|
|
1401
1725
|
startSeq: BigInt(config.startSeq ?? 0)
|
|
1402
1726
|
};
|
|
@@ -1511,6 +1835,11 @@ var ArbitroClient = class {
|
|
|
1511
1835
|
stream(name, config) {
|
|
1512
1836
|
return new Stream(this, name, config);
|
|
1513
1837
|
}
|
|
1838
|
+
// ── Cron ──────────────────────────────────────────────────────────────────
|
|
1839
|
+
/** Start building a cron job. Call `.every()` then `.run()` to register. */
|
|
1840
|
+
cron(name) {
|
|
1841
|
+
return new CronBuilder(this.conn, this._cronState, name);
|
|
1842
|
+
}
|
|
1514
1843
|
// ── Lifecycle ─────────────────────────────────────────────────────────────
|
|
1515
1844
|
async close() {
|
|
1516
1845
|
await this.conn.close();
|
|
@@ -1590,6 +1919,257 @@ function streamId(name) {
|
|
|
1590
1919
|
return h >>> 0;
|
|
1591
1920
|
}
|
|
1592
1921
|
|
|
1922
|
+
// src/workflow/task.ts
|
|
1923
|
+
var TASK_HEADER = 7;
|
|
1924
|
+
var COMPENSATION_BIT = 32768;
|
|
1925
|
+
function encodeTask(instanceId, stepIndex, attempt, context) {
|
|
1926
|
+
const buf = Buffer.allocUnsafe(TASK_HEADER + context.length);
|
|
1927
|
+
buf.writeUInt32LE(instanceId, 0);
|
|
1928
|
+
buf.writeUInt16LE(stepIndex, 4);
|
|
1929
|
+
buf[6] = attempt;
|
|
1930
|
+
context.copy(buf, TASK_HEADER);
|
|
1931
|
+
return buf;
|
|
1932
|
+
}
|
|
1933
|
+
function decodeTask(payload) {
|
|
1934
|
+
if (payload.length < TASK_HEADER) return void 0;
|
|
1935
|
+
return {
|
|
1936
|
+
instanceId: payload.readUInt32LE(0),
|
|
1937
|
+
stepIndex: payload.readUInt16LE(4),
|
|
1938
|
+
attempt: payload[6],
|
|
1939
|
+
context: payload.subarray(TASK_HEADER)
|
|
1940
|
+
};
|
|
1941
|
+
}
|
|
1942
|
+
|
|
1943
|
+
// src/workflow/handle.ts
|
|
1944
|
+
var nextInstanceId = 1;
|
|
1945
|
+
function allocInstanceId() {
|
|
1946
|
+
return nextInstanceId++;
|
|
1947
|
+
}
|
|
1948
|
+
var WorkflowHandle = class {
|
|
1949
|
+
constructor(workflowName, taskStreamName, dlqStreamName, sub, triggerSub) {
|
|
1950
|
+
this.workflowName = workflowName;
|
|
1951
|
+
this.taskStreamName = taskStreamName;
|
|
1952
|
+
this.dlqStreamName = dlqStreamName;
|
|
1953
|
+
this.sub = sub;
|
|
1954
|
+
this.triggerSub = triggerSub;
|
|
1955
|
+
}
|
|
1956
|
+
get name() {
|
|
1957
|
+
return this.workflowName;
|
|
1958
|
+
}
|
|
1959
|
+
get taskStream() {
|
|
1960
|
+
return this.taskStreamName;
|
|
1961
|
+
}
|
|
1962
|
+
get dlqStream() {
|
|
1963
|
+
return this.dlqStreamName;
|
|
1964
|
+
}
|
|
1965
|
+
async trigger(client, context) {
|
|
1966
|
+
const instanceId = allocInstanceId();
|
|
1967
|
+
const msgId = `wf:${instanceId}:0:0`;
|
|
1968
|
+
const subject = `_wf.${this.workflowName}.step.0`;
|
|
1969
|
+
const task = encodeTask(instanceId, 0, 0, context);
|
|
1970
|
+
await client.publish(this.taskStreamName, subject, task, { msgId });
|
|
1971
|
+
return instanceId;
|
|
1972
|
+
}
|
|
1973
|
+
};
|
|
1974
|
+
|
|
1975
|
+
// src/workflow/processor.ts
|
|
1976
|
+
async function processMessage(cfg, msg) {
|
|
1977
|
+
const task = decodeTask(msg.data());
|
|
1978
|
+
if (!task) {
|
|
1979
|
+
msg.ack();
|
|
1980
|
+
return;
|
|
1981
|
+
}
|
|
1982
|
+
if (task.context.length > cfg.maxContextSize) {
|
|
1983
|
+
msg.ack();
|
|
1984
|
+
return;
|
|
1985
|
+
}
|
|
1986
|
+
const isCompensation = (task.stepIndex & COMPENSATION_BIT) !== 0;
|
|
1987
|
+
if (isCompensation) {
|
|
1988
|
+
await runCompensation(cfg, msg, task);
|
|
1989
|
+
return;
|
|
1990
|
+
}
|
|
1991
|
+
if (task.stepIndex >= cfg.steps.length) {
|
|
1992
|
+
msg.ack();
|
|
1993
|
+
return;
|
|
1994
|
+
}
|
|
1995
|
+
await runStep(cfg, msg, task);
|
|
1996
|
+
}
|
|
1997
|
+
async function runCompensation(cfg, msg, task) {
|
|
1998
|
+
const idx = task.stepIndex & ~COMPENSATION_BIT;
|
|
1999
|
+
const comp = cfg.steps[idx]?.compensation;
|
|
2000
|
+
if (comp) {
|
|
2001
|
+
try {
|
|
2002
|
+
await comp({ name: cfg.name, instanceId: task.instanceId, stepIndex: idx, attempt: task.attempt, context: task.context });
|
|
2003
|
+
} catch {
|
|
2004
|
+
}
|
|
2005
|
+
}
|
|
2006
|
+
msg.ack();
|
|
2007
|
+
}
|
|
2008
|
+
async function runStep(cfg, msg, task) {
|
|
2009
|
+
const handler = cfg.steps[task.stepIndex].handler;
|
|
2010
|
+
try {
|
|
2011
|
+
const result = await handler({
|
|
2012
|
+
name: cfg.name,
|
|
2013
|
+
instanceId: task.instanceId,
|
|
2014
|
+
stepIndex: task.stepIndex,
|
|
2015
|
+
attempt: task.attempt,
|
|
2016
|
+
context: task.context
|
|
2017
|
+
});
|
|
2018
|
+
if (result.context.length > cfg.maxContextSize) {
|
|
2019
|
+
msg.nack();
|
|
2020
|
+
return;
|
|
2021
|
+
}
|
|
2022
|
+
await advance(cfg, msg, task, result);
|
|
2023
|
+
} catch (err) {
|
|
2024
|
+
await onFailure(cfg, msg, task, err);
|
|
2025
|
+
}
|
|
2026
|
+
}
|
|
2027
|
+
async function advance(cfg, msg, task, result) {
|
|
2028
|
+
const nextStep = task.stepIndex + 1;
|
|
2029
|
+
if (nextStep < cfg.steps.length) {
|
|
2030
|
+
const msgId = `wf:${task.instanceId}:${nextStep}:0`;
|
|
2031
|
+
const subject = `_wf.${cfg.name}.step.${nextStep}`;
|
|
2032
|
+
const buf = encodeTask(task.instanceId, nextStep, 0, result.context);
|
|
2033
|
+
await cfg.client.publish(cfg.taskStreamName, subject, buf, { msgId });
|
|
2034
|
+
}
|
|
2035
|
+
msg.ack();
|
|
2036
|
+
}
|
|
2037
|
+
async function onFailure(cfg, msg, task, err) {
|
|
2038
|
+
if (task.attempt >= cfg.maxRetries) {
|
|
2039
|
+
await publishDlq(cfg, task, err);
|
|
2040
|
+
await publishCompensations(cfg, task);
|
|
2041
|
+
msg.ack();
|
|
2042
|
+
} else {
|
|
2043
|
+
msg.nack();
|
|
2044
|
+
}
|
|
2045
|
+
}
|
|
2046
|
+
async function publishDlq(cfg, task, err) {
|
|
2047
|
+
const dlqSubject = `_wf.${cfg.name}.dlq.${task.stepIndex}`;
|
|
2048
|
+
const errBytes = Buffer.from(String(err));
|
|
2049
|
+
const buf = Buffer.allocUnsafe(7 + 4 + errBytes.length + task.context.length);
|
|
2050
|
+
buf.writeUInt32LE(task.instanceId, 0);
|
|
2051
|
+
buf.writeUInt16LE(task.stepIndex, 4);
|
|
2052
|
+
buf[6] = task.attempt;
|
|
2053
|
+
buf.writeUInt32LE(errBytes.length, 7);
|
|
2054
|
+
errBytes.copy(buf, 11);
|
|
2055
|
+
task.context.copy(buf, 11 + errBytes.length);
|
|
2056
|
+
const msgId = `wf:${task.instanceId}:dlq:${task.stepIndex}`;
|
|
2057
|
+
await cfg.client.publish(cfg.dlqStreamName, dlqSubject, buf, { msgId }).catch(() => {
|
|
2058
|
+
});
|
|
2059
|
+
}
|
|
2060
|
+
async function publishCompensations(cfg, task) {
|
|
2061
|
+
for (let i = task.stepIndex - 1; i >= 0; i--) {
|
|
2062
|
+
const compStep = COMPENSATION_BIT | i;
|
|
2063
|
+
const subject = `_wf.${cfg.name}.compensate.${i}`;
|
|
2064
|
+
const buf = encodeTask(task.instanceId, compStep, 0, task.context);
|
|
2065
|
+
const msgId = `wf:${task.instanceId}:comp:${i}`;
|
|
2066
|
+
await cfg.client.publish(cfg.taskStreamName, subject, buf, { msgId }).catch(() => {
|
|
2067
|
+
});
|
|
2068
|
+
}
|
|
2069
|
+
}
|
|
2070
|
+
|
|
2071
|
+
// src/workflow/workflow.ts
|
|
2072
|
+
var nextWorkerUid = 1;
|
|
2073
|
+
var WorkflowBuilder = class {
|
|
2074
|
+
constructor(client, workflowName) {
|
|
2075
|
+
this.client = client;
|
|
2076
|
+
this.workflowName = workflowName;
|
|
2077
|
+
}
|
|
2078
|
+
triggerSubject;
|
|
2079
|
+
triggerStreamName;
|
|
2080
|
+
steps = [];
|
|
2081
|
+
ackWaitMs = 3e4;
|
|
2082
|
+
maxInflightVal = 10;
|
|
2083
|
+
maxRetriesVal = 3;
|
|
2084
|
+
maxContextSizeVal = 256 * 1024;
|
|
2085
|
+
trigger(subject) {
|
|
2086
|
+
this.triggerSubject = subject;
|
|
2087
|
+
return this;
|
|
2088
|
+
}
|
|
2089
|
+
triggerStream(streamName) {
|
|
2090
|
+
this.triggerStreamName = streamName;
|
|
2091
|
+
return this;
|
|
2092
|
+
}
|
|
2093
|
+
step(name, handler) {
|
|
2094
|
+
this.steps.push({ name, handler, compensation: void 0 });
|
|
2095
|
+
return this;
|
|
2096
|
+
}
|
|
2097
|
+
/** Compensation handler for the most recently added step. */
|
|
2098
|
+
compensate(_stepName, handler) {
|
|
2099
|
+
const last = this.steps[this.steps.length - 1];
|
|
2100
|
+
if (last) last.compensation = handler;
|
|
2101
|
+
return this;
|
|
2102
|
+
}
|
|
2103
|
+
ackWait(ms) {
|
|
2104
|
+
this.ackWaitMs = ms;
|
|
2105
|
+
return this;
|
|
2106
|
+
}
|
|
2107
|
+
inflight(n) {
|
|
2108
|
+
this.maxInflightVal = n;
|
|
2109
|
+
return this;
|
|
2110
|
+
}
|
|
2111
|
+
maxRetries(n) {
|
|
2112
|
+
this.maxRetriesVal = n;
|
|
2113
|
+
return this;
|
|
2114
|
+
}
|
|
2115
|
+
maxContextSize(bytes) {
|
|
2116
|
+
this.maxContextSizeVal = bytes;
|
|
2117
|
+
return this;
|
|
2118
|
+
}
|
|
2119
|
+
async start() {
|
|
2120
|
+
if (!this.triggerSubject) throw new Error("trigger subject required");
|
|
2121
|
+
if (this.steps.length === 0) throw new Error("at least one step required");
|
|
2122
|
+
const name = this.workflowName;
|
|
2123
|
+
const taskStream = `_wf.${name}.tasks`;
|
|
2124
|
+
const taskSubject = `_wf.${name}.>`;
|
|
2125
|
+
const dlqStream = `_wf.${name}.dlq`;
|
|
2126
|
+
const dlqSubject = `_wf.${name}.dlq.>`;
|
|
2127
|
+
await this.client.upsertStream(taskStream, { subjectFilter: taskSubject, idempotencyWindowMs: 3e5 });
|
|
2128
|
+
await this.client.upsertStream(dlqStream, { subjectFilter: dlqSubject });
|
|
2129
|
+
const cfg = {
|
|
2130
|
+
client: this.client,
|
|
2131
|
+
name,
|
|
2132
|
+
taskStreamName: taskStream,
|
|
2133
|
+
dlqStreamName: dlqStream,
|
|
2134
|
+
steps: this.steps,
|
|
2135
|
+
maxContextSize: this.maxContextSizeVal,
|
|
2136
|
+
maxRetries: this.maxRetriesVal
|
|
2137
|
+
};
|
|
2138
|
+
const sub = await this.subscribeWorker(cfg, taskStream, taskSubject);
|
|
2139
|
+
const triggerSub = await this.subscribeTrigger(taskStream, name);
|
|
2140
|
+
return new WorkflowHandle(name, taskStream, dlqStream, sub, triggerSub);
|
|
2141
|
+
}
|
|
2142
|
+
async subscribeWorker(cfg, taskStream, taskSubject) {
|
|
2143
|
+
const uid = nextWorkerUid++;
|
|
2144
|
+
return this.client.subscribe(taskStream, {
|
|
2145
|
+
name: `_wf_${cfg.name}_w${uid}`,
|
|
2146
|
+
group: `_wf_${cfg.name}_workers`,
|
|
2147
|
+
filter: taskSubject,
|
|
2148
|
+
ackPolicy: "explicit" /* Explicit */,
|
|
2149
|
+
ackWaitMs: this.ackWaitMs,
|
|
2150
|
+
maxAckPending: this.maxInflightVal
|
|
2151
|
+
}, (msg) => {
|
|
2152
|
+
void processMessage(cfg, msg);
|
|
2153
|
+
});
|
|
2154
|
+
}
|
|
2155
|
+
async subscribeTrigger(taskStream, name) {
|
|
2156
|
+
if (!this.triggerSubject || !this.triggerStreamName) return void 0;
|
|
2157
|
+
const subject = this.triggerSubject;
|
|
2158
|
+
return this.client.subscribe(this.triggerStreamName, {
|
|
2159
|
+
name: `_wf_${name}_trigger`,
|
|
2160
|
+
filter: subject,
|
|
2161
|
+
ackPolicy: "explicit" /* Explicit */,
|
|
2162
|
+
ackWaitMs: this.ackWaitMs,
|
|
2163
|
+
maxAckPending: 1
|
|
2164
|
+
}, async (msg) => {
|
|
2165
|
+
const id = allocInstanceId();
|
|
2166
|
+
const taskBuf = encodeTask(id, 0, 0, msg.data());
|
|
2167
|
+
await this.client.publish(taskStream, `_wf.${name}.step.0`, taskBuf, { msgId: `wf:${id}:0:0` });
|
|
2168
|
+
msg.ack();
|
|
2169
|
+
});
|
|
2170
|
+
}
|
|
2171
|
+
};
|
|
2172
|
+
|
|
1593
2173
|
// src/utils/zod.ts
|
|
1594
2174
|
var import_msgpackr2 = require("msgpackr");
|
|
1595
2175
|
var packr = new import_msgpackr2.Packr({ structuredClone: false, useRecords: false });
|
|
@@ -1611,8 +2191,11 @@ function zodCodec(zodSchema) {
|
|
|
1611
2191
|
AckPolicy,
|
|
1612
2192
|
ArbitroClient,
|
|
1613
2193
|
ArbitroError,
|
|
2194
|
+
COMPENSATION_BIT,
|
|
1614
2195
|
Codec,
|
|
1615
2196
|
Consumer,
|
|
2197
|
+
CronBuilder,
|
|
2198
|
+
CronHandle,
|
|
1616
2199
|
DeliverPolicy,
|
|
1617
2200
|
ErrorCode,
|
|
1618
2201
|
JournalType,
|
|
@@ -1622,6 +2205,8 @@ function zodCodec(zodSchema) {
|
|
|
1622
2205
|
StringCodec,
|
|
1623
2206
|
Subscription,
|
|
1624
2207
|
Topic,
|
|
2208
|
+
WorkflowBuilder,
|
|
2209
|
+
WorkflowHandle,
|
|
1625
2210
|
decodeJson,
|
|
1626
2211
|
decodeString,
|
|
1627
2212
|
encodeJson,
|