@spine-event-engine/delivery-server 2.0.0-snapshot.10
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/LICENSE +201 -0
- package/README.md +106 -0
- package/REFERENCE.md +75 -0
- package/dist/admin/admin-service.d.ts +47 -0
- package/dist/admin/admin-service.d.ts.map +1 -0
- package/dist/admin/admin-service.js +188 -0
- package/dist/admin/admin-service.js.map +1 -0
- package/dist/bin/spine-delivery-server.d.ts +3 -0
- package/dist/bin/spine-delivery-server.d.ts.map +1 -0
- package/dist/bin/spine-delivery-server.js +54 -0
- package/dist/bin/spine-delivery-server.js.map +1 -0
- package/dist/core/in-memory-delivery-core.d.ts +56 -0
- package/dist/core/in-memory-delivery-core.d.ts.map +1 -0
- package/dist/core/in-memory-delivery-core.js +44 -0
- package/dist/core/in-memory-delivery-core.js.map +1 -0
- package/dist/core/in-memory-delivery-state.d.ts +86 -0
- package/dist/core/in-memory-delivery-state.d.ts.map +1 -0
- package/dist/core/in-memory-delivery-state.js +214 -0
- package/dist/core/in-memory-delivery-state.js.map +1 -0
- package/dist/core/inbox-service.d.ts +20 -0
- package/dist/core/inbox-service.d.ts.map +1 -0
- package/dist/core/inbox-service.js +212 -0
- package/dist/core/inbox-service.js.map +1 -0
- package/dist/core/limits.d.ts +64 -0
- package/dist/core/limits.d.ts.map +1 -0
- package/dist/core/limits.js +73 -0
- package/dist/core/limits.js.map +1 -0
- package/dist/core/mutation-admission.d.ts +18 -0
- package/dist/core/mutation-admission.d.ts.map +1 -0
- package/dist/core/mutation-admission.js +78 -0
- package/dist/core/mutation-admission.js.map +1 -0
- package/dist/core/shard-service.d.ts +22 -0
- package/dist/core/shard-service.d.ts.map +1 -0
- package/dist/core/shard-service.js +189 -0
- package/dist/core/shard-service.js.map +1 -0
- package/dist/core/wire-values.d.ts +22 -0
- package/dist/core/wire-values.d.ts.map +1 -0
- package/dist/core/wire-values.js +66 -0
- package/dist/core/wire-values.js.map +1 -0
- package/dist/health/health-service.d.ts +9 -0
- package/dist/health/health-service.d.ts.map +1 -0
- package/dist/health/health-service.js +47 -0
- package/dist/health/health-service.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -0
- package/dist/server/assembly.d.ts +41 -0
- package/dist/server/assembly.d.ts.map +1 -0
- package/dist/server/assembly.js +49 -0
- package/dist/server/assembly.js.map +1 -0
- package/dist/server/config.d.ts +57 -0
- package/dist/server/config.d.ts.map +1 -0
- package/dist/server/config.js +52 -0
- package/dist/server/config.js.map +1 -0
- package/dist/server/delivery-server-log.d.ts +11 -0
- package/dist/server/delivery-server-log.d.ts.map +1 -0
- package/dist/server/delivery-server-log.js +44 -0
- package/dist/server/delivery-server-log.js.map +1 -0
- package/dist/server/delivery-server.d.ts +103 -0
- package/dist/server/delivery-server.d.ts.map +1 -0
- package/dist/server/delivery-server.js +201 -0
- package/dist/server/delivery-server.js.map +1 -0
- package/dist/server/shutdown.d.ts +36 -0
- package/dist/server/shutdown.d.ts.map +1 -0
- package/dist/server/shutdown.js +25 -0
- package/dist/server/shutdown.js.map +1 -0
- package/dist/testing/index.d.ts +5 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +18 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +41 -0
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2026, CodeMatters. All rights reserved.
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
|
5
|
+
* in compliance with the License. You may obtain a copy of the License at
|
|
6
|
+
*
|
|
7
|
+
* https://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
*
|
|
9
|
+
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
|
10
|
+
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
|
11
|
+
* or implied. See the License for the specific language governing permissions and limitations under
|
|
12
|
+
* the License.
|
|
13
|
+
*/
|
|
14
|
+
import { create, toBinary, } from "@bufbuild/protobuf";
|
|
15
|
+
import { Code, ConnectError } from "@connectrpc/connect";
|
|
16
|
+
import { CommandSchema, EventSchema } from "@spine-event-engine/proto";
|
|
17
|
+
import { InboxService, OptionalInboxMessageSchema, PageOfMessagesSchema, } from "@spine-event-engine/proto/delivery-server";
|
|
18
|
+
import { InboxLabel, InboxMessageSchema, InboxMessageStatus, } from "@spine-event-engine/proto/delivery";
|
|
19
|
+
import { InMemoryDeliveryState } from "./in-memory-delivery-state.js";
|
|
20
|
+
import { MAX_DELIVERY_BATCH_MESSAGES, MAX_DELIVERY_RPC_BYTES, MAX_INBOX_PAYLOAD_BYTES, MAX_INBOX_RECORD_BYTES, } from "./limits.js";
|
|
21
|
+
import { MutationAdmission } from "./mutation-admission.js";
|
|
22
|
+
import { DeliveryMessages, DeliveryShards } from "./wire-values.js";
|
|
23
|
+
/**
|
|
24
|
+
* Provides Inbox RPC handler implementations.
|
|
25
|
+
*/
|
|
26
|
+
export const InboxHandlers = Object.freeze({
|
|
27
|
+
create: (state, admission, onMessageTransition) => ({
|
|
28
|
+
writeOne: async (request, context) => {
|
|
29
|
+
const message = InboxMessages.required(request.message);
|
|
30
|
+
await admission.run(context.signal, () => {
|
|
31
|
+
for (const inserted of state.putAll([message]))
|
|
32
|
+
onMessageTransition?.(InboxShards.required(inserted.id?.index), 1);
|
|
33
|
+
});
|
|
34
|
+
return {};
|
|
35
|
+
},
|
|
36
|
+
writeMany: async (request, context) => {
|
|
37
|
+
const shard = InboxShards.required(request.shard);
|
|
38
|
+
InboxMessages.requiredBatchLength(request.message.length);
|
|
39
|
+
const messages = request.message.map(InboxMessages.required);
|
|
40
|
+
InboxShards.ensure(messages.map((value) => value.message), shard);
|
|
41
|
+
await admission.run(context.signal, () => {
|
|
42
|
+
for (const inserted of state.putAll(messages))
|
|
43
|
+
onMessageTransition?.(InboxShards.required(inserted.id?.index), 1);
|
|
44
|
+
});
|
|
45
|
+
return {};
|
|
46
|
+
},
|
|
47
|
+
removeOne: async (request, context) => {
|
|
48
|
+
const message = InboxMessages.required(request.message);
|
|
49
|
+
await admission.run(context.signal, () => {
|
|
50
|
+
if (state.delete(message.message))
|
|
51
|
+
onMessageTransition?.(InboxShards.required(message.message.id?.index), -1);
|
|
52
|
+
});
|
|
53
|
+
return {};
|
|
54
|
+
},
|
|
55
|
+
removeMany: async (request, context) => {
|
|
56
|
+
const shard = InboxShards.required(request.shard);
|
|
57
|
+
InboxMessages.requiredBatchLength(request.message.length);
|
|
58
|
+
const messages = request.message.map(InboxMessages.required);
|
|
59
|
+
InboxShards.ensure(messages.map((value) => value.message), shard);
|
|
60
|
+
await admission.run(context.signal, () => {
|
|
61
|
+
for (const message of messages)
|
|
62
|
+
if (state.delete(message.message))
|
|
63
|
+
onMessageTransition?.(InboxShards.required(message.message.id?.index), -1);
|
|
64
|
+
});
|
|
65
|
+
return {};
|
|
66
|
+
},
|
|
67
|
+
findOne: (request) => {
|
|
68
|
+
if (request.index === undefined || request.uuid.trim().length === 0)
|
|
69
|
+
throw InboxResponses.invalid("Delivery message identity is missing.");
|
|
70
|
+
InboxShards.required(request.index);
|
|
71
|
+
const message = state.messages.get(`${DeliveryShards.key(request.index)}:${request.uuid}`);
|
|
72
|
+
return InboxResponses.bounded(OptionalInboxMessageSchema, message === undefined ? {} : { message: DeliveryMessages.copy(message) });
|
|
73
|
+
},
|
|
74
|
+
findManyInShard: (request) => {
|
|
75
|
+
const shard = InboxShards.required(request.shard);
|
|
76
|
+
if (!Number.isInteger(request.pageSize) || request.pageSize < 1 || request.pageSize > 1_000)
|
|
77
|
+
throw InboxResponses.invalid("Delivery page size must be between 1 and 1000.");
|
|
78
|
+
if (request.sinceWhen !== undefined && !InboxTime.valid(request.sinceWhen))
|
|
79
|
+
throw InboxResponses.invalid("Delivery page timestamp is invalid.");
|
|
80
|
+
const message = [...state.messages.values()]
|
|
81
|
+
.filter((value) => value.id?.index !== undefined &&
|
|
82
|
+
DeliveryShards.key(value.id.index) === DeliveryShards.key(shard))
|
|
83
|
+
.filter((value) => request.sinceWhen === undefined || InboxTime.compare(value, request.sinceWhen) > 0)
|
|
84
|
+
.sort(InboxMessages.compare)
|
|
85
|
+
.slice(0, request.pageSize)
|
|
86
|
+
.map(DeliveryMessages.copy);
|
|
87
|
+
return InboxResponses.bounded(PageOfMessagesSchema, { message }, "Delivery page exceeds the 4 MiB response limit; request a smaller page.");
|
|
88
|
+
},
|
|
89
|
+
newestMessageToDeliver: (shard) => {
|
|
90
|
+
const key = DeliveryShards.key(InboxShards.required(shard));
|
|
91
|
+
const newest = [...state.messages.values()]
|
|
92
|
+
.filter((value) => value.id?.index !== undefined &&
|
|
93
|
+
DeliveryShards.key(value.id.index) === key &&
|
|
94
|
+
value.status === InboxMessageStatus.TO_DELIVER)
|
|
95
|
+
.sort(InboxMessages.compare)
|
|
96
|
+
.at(-1);
|
|
97
|
+
return InboxResponses.bounded(OptionalInboxMessageSchema, newest === undefined ? {} : { message: DeliveryMessages.copy(newest) });
|
|
98
|
+
},
|
|
99
|
+
}),
|
|
100
|
+
});
|
|
101
|
+
/**
|
|
102
|
+
* Validates Inbox messages and preserves their delivery ordering.
|
|
103
|
+
*/
|
|
104
|
+
const InboxMessages = Object.freeze({
|
|
105
|
+
required: (message) => {
|
|
106
|
+
if (message?.id?.index === undefined || message.inboxId?.entityId?.id === undefined)
|
|
107
|
+
throw InboxResponses.invalid("Delivery message identity is incomplete.");
|
|
108
|
+
if (message.signalId === undefined || message.whenReceived === undefined)
|
|
109
|
+
throw InboxResponses.invalid("Delivery message fields are incomplete.");
|
|
110
|
+
if (message.id.uuid.trim().length === 0 ||
|
|
111
|
+
message.signalId.value.trim().length === 0 ||
|
|
112
|
+
message.inboxId.typeUrl.trim().length === 0 ||
|
|
113
|
+
message.inboxId.entityId.id.typeUrl.trim().length === 0 ||
|
|
114
|
+
!InboxShards.valid(message.id.index) ||
|
|
115
|
+
!InboxTime.valid(message.whenReceived) ||
|
|
116
|
+
(message.keepUntil !== undefined && !InboxTime.valid(message.keepUntil)) ||
|
|
117
|
+
!Number.isSafeInteger(message.version) ||
|
|
118
|
+
message.version < 0) {
|
|
119
|
+
throw InboxResponses.invalid("Delivery message is incomplete.");
|
|
120
|
+
}
|
|
121
|
+
if (!InboxMessages.validPayload(message))
|
|
122
|
+
throw InboxResponses.invalid("Delivery message payload is invalid.");
|
|
123
|
+
if (!InboxMessages.validLabel(message.label) || !InboxMessages.validStatus(message.status))
|
|
124
|
+
throw InboxResponses.invalid("Delivery message enum is invalid.");
|
|
125
|
+
const bytes = toBinary(InboxMessageSchema, message).byteLength;
|
|
126
|
+
if (bytes > MAX_INBOX_RECORD_BYTES)
|
|
127
|
+
throw InboxResponses.invalid("Delivery message record is too large.");
|
|
128
|
+
return { message: DeliveryMessages.copy(message), bytes };
|
|
129
|
+
},
|
|
130
|
+
requiredBatchLength: (length) => {
|
|
131
|
+
if (length < 1 || length > MAX_DELIVERY_BATCH_MESSAGES)
|
|
132
|
+
throw InboxResponses.invalid("Delivery message batch is invalid.");
|
|
133
|
+
},
|
|
134
|
+
compare: (left, right) => {
|
|
135
|
+
const received = InboxTime.compare(left, right.whenReceived);
|
|
136
|
+
if (received !== 0)
|
|
137
|
+
return received;
|
|
138
|
+
const version = left.version - right.version;
|
|
139
|
+
if (version !== 0)
|
|
140
|
+
return version;
|
|
141
|
+
return (left.id?.uuid ?? "").localeCompare(right.id?.uuid ?? "");
|
|
142
|
+
},
|
|
143
|
+
validPayload: (message) => {
|
|
144
|
+
const payload = message.payload;
|
|
145
|
+
if (payload.case !== "command" && payload.case !== "event")
|
|
146
|
+
return false;
|
|
147
|
+
const schema = payload.case === "command" ? CommandSchema : EventSchema;
|
|
148
|
+
return (toBinary(schema, payload.value, { writeUnknownFields: false }).byteLength <=
|
|
149
|
+
MAX_INBOX_PAYLOAD_BYTES);
|
|
150
|
+
},
|
|
151
|
+
validLabel: (label) => label === InboxLabel.HANDLE_COMMAND ||
|
|
152
|
+
label === InboxLabel.UPDATE_SUBSCRIBER ||
|
|
153
|
+
label === InboxLabel.REACT_UPON_EVENT ||
|
|
154
|
+
label === InboxLabel.CATCH_UP,
|
|
155
|
+
validStatus: (status) => status === InboxMessageStatus.TO_DELIVER ||
|
|
156
|
+
status === InboxMessageStatus.SCHEDULED ||
|
|
157
|
+
status === InboxMessageStatus.DELIVERED ||
|
|
158
|
+
status === InboxMessageStatus.TO_CATCH_UP,
|
|
159
|
+
});
|
|
160
|
+
/**
|
|
161
|
+
* Validates Inbox shard identities and batch consistency.
|
|
162
|
+
*/
|
|
163
|
+
const InboxShards = Object.freeze({
|
|
164
|
+
required: (shard) => {
|
|
165
|
+
if (shard === undefined || !InboxShards.valid(shard))
|
|
166
|
+
throw InboxResponses.invalid("Delivery shard is invalid.");
|
|
167
|
+
return shard;
|
|
168
|
+
},
|
|
169
|
+
valid: (shard) => Number.isInteger(shard.index) &&
|
|
170
|
+
shard.index >= 0 &&
|
|
171
|
+
Number.isInteger(shard.ofTotal) &&
|
|
172
|
+
shard.ofTotal >= 1 &&
|
|
173
|
+
shard.index < shard.ofTotal,
|
|
174
|
+
ensure: (messages, shard) => {
|
|
175
|
+
for (const message of messages) {
|
|
176
|
+
if (message.id?.index === undefined ||
|
|
177
|
+
DeliveryShards.key(message.id.index) !== DeliveryShards.key(shard))
|
|
178
|
+
throw InboxResponses.invalid("Delivery batch spans shards.");
|
|
179
|
+
}
|
|
180
|
+
},
|
|
181
|
+
});
|
|
182
|
+
/**
|
|
183
|
+
* Validates and compares Inbox timestamps.
|
|
184
|
+
*/
|
|
185
|
+
const InboxTime = Object.freeze({
|
|
186
|
+
valid: (value) => value.seconds >= -62135596800n &&
|
|
187
|
+
value.seconds <= 253402300799n &&
|
|
188
|
+
Number.isInteger(value.nanos) &&
|
|
189
|
+
value.nanos >= 0 &&
|
|
190
|
+
value.nanos < 1_000_000_000,
|
|
191
|
+
compare: (left, right) => {
|
|
192
|
+
if (right === undefined || left.whenReceived === undefined)
|
|
193
|
+
throw new TypeError("Delivery message receive time is missing.");
|
|
194
|
+
if (left.whenReceived.seconds !== right.seconds)
|
|
195
|
+
return left.whenReceived.seconds < right.seconds ? -1 : 1;
|
|
196
|
+
return left.whenReceived.nanos - right.nanos;
|
|
197
|
+
},
|
|
198
|
+
});
|
|
199
|
+
/**
|
|
200
|
+
* Bounds Inbox responses and creates RPC errors.
|
|
201
|
+
*/
|
|
202
|
+
const InboxResponses = Object.freeze({
|
|
203
|
+
bounded: (schema, initializer, errorMessage = "Delivery response exceeds the 4 MiB limit.") => {
|
|
204
|
+
const response = create(schema, initializer);
|
|
205
|
+
if (toBinary(schema, response).byteLength > MAX_DELIVERY_RPC_BYTES)
|
|
206
|
+
throw InboxResponses.exhausted(errorMessage);
|
|
207
|
+
return response;
|
|
208
|
+
},
|
|
209
|
+
invalid: (message) => new ConnectError(message, Code.InvalidArgument),
|
|
210
|
+
exhausted: (message) => new ConnectError(message, Code.ResourceExhausted),
|
|
211
|
+
});
|
|
212
|
+
//# sourceMappingURL=inbox-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inbox-service.js","sourceRoot":"","sources":["../../src/core/inbox-service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EACL,MAAM,EACN,QAAQ,GAIT,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAAE,IAAI,EAAE,YAAY,EAAoB,MAAM,qBAAqB,CAAC;AAC3E,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACvE,OAAO,EACL,YAAY,EACZ,0BAA0B,EAC1B,oBAAoB,GACrB,MAAM,2CAA2C,CAAC;AACnD,OAAO,EACL,UAAU,EACV,kBAAkB,EAClB,kBAAkB,GAGnB,MAAM,oCAAoC,CAAC;AAE5C,OAAO,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AACtE,OAAO,EACL,2BAA2B,EAC3B,sBAAsB,EACtB,uBAAuB,EACvB,sBAAsB,GACvB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAEpE;;GAEG;AACH,MAAM,CAAC,MAAM,aAAa,GAgBrB,MAAM,CAAC,MAAM,CAAC;IACjB,MAAM,EAAE,CACN,KAA4B,EAC5B,SAA4B,EAC5B,mBAAgE,EAC9B,EAAE,CAAC,CAAC;QACtC,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE;YACnC,MAAM,OAAO,GAAG,aAAa,CAAC,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;YACxD,MAAM,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,EAAE;gBACvC,KAAK,MAAM,QAAQ,IAAI,KAAK,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC;oBAC5C,mBAAmB,EAAE,CAAC,WAAW,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;YACvE,CAAC,CAAC,CAAC;YACH,OAAO,EAAE,CAAC;QACZ,CAAC;QACD,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE;YACpC,MAAM,KAAK,GAAG,WAAW,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;YAClD,aAAa,CAAC,mBAAmB,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;YAC1D,MAAM,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;YAC7D,WAAW,CAAC,MAAM,CAChB,QAAQ,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,EACtC,KAAK,CACN,CAAC;YACF,MAAM,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,EAAE;gBACvC,KAAK,MAAM,QAAQ,IAAI,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC;oBAC3C,mBAAmB,EAAE,CAAC,WAAW,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;YACvE,CAAC,CAAC,CAAC;YACH,OAAO,EAAE,CAAC;QACZ,CAAC;QACD,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE;YACpC,MAAM,OAAO,GAAG,aAAa,CAAC,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;YACxD,MAAM,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,EAAE;gBACvC,IAAI,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC;oBAC/B,mBAAmB,EAAE,CAAC,WAAW,CAAC,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;YAC/E,CAAC,CAAC,CAAC;YACH,OAAO,EAAE,CAAC;QACZ,CAAC;QACD,UAAU,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE;YACrC,MAAM,KAAK,GAAG,WAAW,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;YAClD,aAAa,CAAC,mBAAmB,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;YAC1D,MAAM,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;YAC7D,WAAW,CAAC,MAAM,CAChB,QAAQ,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,EACtC,KAAK,CACN,CAAC;YACF,MAAM,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,EAAE;gBACvC,KAAK,MAAM,OAAO,IAAI,QAAQ;oBAC5B,IAAI,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC;wBAC/B,mBAAmB,EAAE,CAAC,WAAW,CAAC,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;YACjF,CAAC,CAAC,CAAC;YACH,OAAO,EAAE,CAAC;QACZ,CAAC;QACD,OAAO,EAAE,CAAC,OAAO,EAAE,EAAE;YACnB,IAAI,OAAO,CAAC,KAAK,KAAK,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC;gBACjE,MAAM,cAAc,CAAC,OAAO,CAAC,uCAAuC,CAAC,CAAC;YACxE,WAAW,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;YACpC,MAAM,OAAO,GAAG,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,cAAc,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;YAC3F,OAAO,cAAc,CAAC,OAAO,CAC3B,0BAA0B,EAC1B,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,gBAAgB,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CACzE,CAAC;QACJ,CAAC;QACD,eAAe,EAAE,CAAC,OAAO,EAAE,EAAE;YAC3B,MAAM,KAAK,GAAG,WAAW,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;YAClD,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,OAAO,CAAC,QAAQ,GAAG,CAAC,IAAI,OAAO,CAAC,QAAQ,GAAG,KAAK;gBACzF,MAAM,cAAc,CAAC,OAAO,CAAC,gDAAgD,CAAC,CAAC;YACjF,IAAI,OAAO,CAAC,SAAS,KAAK,SAAS,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC;gBACxE,MAAM,cAAc,CAAC,OAAO,CAAC,qCAAqC,CAAC,CAAC;YACtE,MAAM,OAAO,GAAG,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;iBACzC,MAAM,CACL,CAAC,KAAK,EAAE,EAAE,CACR,KAAK,CAAC,EAAE,EAAE,KAAK,KAAK,SAAS;gBAC7B,cAAc,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,KAAK,cAAc,CAAC,GAAG,CAAC,KAAK,CAAC,CACnE;iBACA,MAAM,CACL,CAAC,KAAK,EAAE,EAAE,CACR,OAAO,CAAC,SAAS,KAAK,SAAS,IAAI,SAAS,CAAC,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,CACrF;iBACA,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC;iBAC3B,KAAK,CAAC,CAAC,EAAE,OAAO,CAAC,QAAQ,CAAC;iBAC1B,GAAG,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC;YAC9B,OAAO,cAAc,CAAC,OAAO,CAC3B,oBAAoB,EACpB,EAAE,OAAO,EAAE,EACX,yEAAyE,CAC1E,CAAC;QACJ,CAAC;QACD,sBAAsB,EAAE,CAAC,KAAK,EAAE,EAAE;YAChC,MAAM,GAAG,GAAG,cAAc,CAAC,GAAG,CAAC,WAAW,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC;YAC5D,MAAM,MAAM,GAAG,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;iBACxC,MAAM,CACL,CAAC,KAAK,EAAE,EAAE,CACR,KAAK,CAAC,EAAE,EAAE,KAAK,KAAK,SAAS;gBAC7B,cAAc,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,KAAK,GAAG;gBAC1C,KAAK,CAAC,MAAM,KAAK,kBAAkB,CAAC,UAAU,CACjD;iBACA,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC;iBAC3B,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;YACV,OAAO,cAAc,CAAC,OAAO,CAC3B,0BAA0B,EAC1B,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,gBAAgB,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CACvE,CAAC;QACJ,CAAC;KACF,CAAC;CACH,CAAC,CAAC;AAmBH;;GAEG;AACH,MAAM,aAAa,GAmDd,MAAM,CAAC,MAAM,CAAC;IACjB,QAAQ,EAAE,CAAC,OAAiC,EAAe,EAAE;QAC3D,IAAI,OAAO,EAAE,EAAE,EAAE,KAAK,KAAK,SAAS,IAAI,OAAO,CAAC,OAAO,EAAE,QAAQ,EAAE,EAAE,KAAK,SAAS;YACjF,MAAM,cAAc,CAAC,OAAO,CAAC,0CAA0C,CAAC,CAAC;QAC3E,IAAI,OAAO,CAAC,QAAQ,KAAK,SAAS,IAAI,OAAO,CAAC,YAAY,KAAK,SAAS;YACtE,MAAM,cAAc,CAAC,OAAO,CAAC,yCAAyC,CAAC,CAAC;QAC1E,IACE,OAAO,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC;YACnC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC;YAC1C,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC;YAC3C,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC;YACvD,CAAC,WAAW,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,KAAK,CAAC;YACpC,CAAC,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC,YAAY,CAAC;YACtC,CAAC,OAAO,CAAC,SAAS,KAAK,SAAS,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;YACxE,CAAC,MAAM,CAAC,aAAa,CAAC,OAAO,CAAC,OAAO,CAAC;YACtC,OAAO,CAAC,OAAO,GAAG,CAAC,EACnB,CAAC;YACD,MAAM,cAAc,CAAC,OAAO,CAAC,iCAAiC,CAAC,CAAC;QAClE,CAAC;QACD,IAAI,CAAC,aAAa,CAAC,YAAY,CAAC,OAAO,CAAC;YACtC,MAAM,cAAc,CAAC,OAAO,CAAC,sCAAsC,CAAC,CAAC;QACvE,IAAI,CAAC,aAAa,CAAC,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,WAAW,CAAC,OAAO,CAAC,MAAM,CAAC;YACxF,MAAM,cAAc,CAAC,OAAO,CAAC,mCAAmC,CAAC,CAAC;QACpE,MAAM,KAAK,GAAG,QAAQ,CAAC,kBAAkB,EAAE,OAAO,CAAC,CAAC,UAAU,CAAC;QAC/D,IAAI,KAAK,GAAG,sBAAsB;YAChC,MAAM,cAAc,CAAC,OAAO,CAAC,uCAAuC,CAAC,CAAC;QACxE,OAAO,EAAE,OAAO,EAAE,gBAAgB,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,CAAC;IAC5D,CAAC;IACD,mBAAmB,EAAE,CAAC,MAAc,EAAQ,EAAE;QAC5C,IAAI,MAAM,GAAG,CAAC,IAAI,MAAM,GAAG,2BAA2B;YACpD,MAAM,cAAc,CAAC,OAAO,CAAC,oCAAoC,CAAC,CAAC;IACvE,CAAC;IACD,OAAO,EAAE,CAAC,IAAkB,EAAE,KAAmB,EAAU,EAAE;QAC3D,MAAM,QAAQ,GAAG,SAAS,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,YAAY,CAAC,CAAC;QAC7D,IAAI,QAAQ,KAAK,CAAC;YAAE,OAAO,QAAQ,CAAC;QACpC,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC;QAC7C,IAAI,OAAO,KAAK,CAAC;YAAE,OAAO,OAAO,CAAC;QAClC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,IAAI,EAAE,CAAC,CAAC,aAAa,CAAC,KAAK,CAAC,EAAE,EAAE,IAAI,IAAI,EAAE,CAAC,CAAC;IACnE,CAAC;IACD,YAAY,EAAE,CAAC,OAAqB,EAAW,EAAE;QAC/C,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;QAChC,IAAI,OAAO,CAAC,IAAI,KAAK,SAAS,IAAI,OAAO,CAAC,IAAI,KAAK,OAAO;YAAE,OAAO,KAAK,CAAC;QACzE,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,WAAW,CAAC;QACxE,OAAO,CACL,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,EAAE,EAAE,kBAAkB,EAAE,KAAK,EAAE,CAAC,CAAC,UAAU;YACzE,uBAAuB,CACxB,CAAC;IACJ,CAAC;IACD,UAAU,EAAE,CAAC,KAAiB,EAAW,EAAE,CACzC,KAAK,KAAK,UAAU,CAAC,cAAc;QACnC,KAAK,KAAK,UAAU,CAAC,iBAAiB;QACtC,KAAK,KAAK,UAAU,CAAC,gBAAgB;QACrC,KAAK,KAAK,UAAU,CAAC,QAAQ;IAC/B,WAAW,EAAE,CAAC,MAA0B,EAAW,EAAE,CACnD,MAAM,KAAK,kBAAkB,CAAC,UAAU;QACxC,MAAM,KAAK,kBAAkB,CAAC,SAAS;QACvC,MAAM,KAAK,kBAAkB,CAAC,SAAS;QACvC,MAAM,KAAK,kBAAkB,CAAC,WAAW;CAC5C,CAAC,CAAC;AAEH;;GAEG;AACH,MAAM,WAAW,GA2BZ,MAAM,CAAC,MAAM,CAAC;IACjB,QAAQ,EAAE,CAAC,KAA6B,EAAc,EAAE;QACtD,IAAI,KAAK,KAAK,SAAS,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,KAAK,CAAC;YAClD,MAAM,cAAc,CAAC,OAAO,CAAC,4BAA4B,CAAC,CAAC;QAC7D,OAAO,KAAK,CAAC;IACf,CAAC;IACD,KAAK,EAAE,CAAC,KAAiB,EAAW,EAAE,CACpC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,KAAK,CAAC;QAC7B,KAAK,CAAC,KAAK,IAAI,CAAC;QAChB,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC;QAC/B,KAAK,CAAC,OAAO,IAAI,CAAC;QAClB,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC,OAAO;IAC7B,MAAM,EAAE,CAAC,QAAiC,EAAE,KAAiB,EAAQ,EAAE;QACrE,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;YAC/B,IACE,OAAO,CAAC,EAAE,EAAE,KAAK,KAAK,SAAS;gBAC/B,cAAc,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,KAAK,CAAC,KAAK,cAAc,CAAC,GAAG,CAAC,KAAK,CAAC;gBAElE,MAAM,cAAc,CAAC,OAAO,CAAC,8BAA8B,CAAC,CAAC;QACjE,CAAC;IACH,CAAC;CACF,CAAC,CAAC;AAEH;;GAEG;AACH,MAAM,SAAS,GAsBV,MAAM,CAAC,MAAM,CAAC;IACjB,KAAK,EAAE,CAAC,KAA2D,EAAW,EAAE,CAC9E,KAAK,CAAC,OAAO,IAAI,CAAC,YAAe;QACjC,KAAK,CAAC,OAAO,IAAI,aAAgB;QACjC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,KAAK,CAAC;QAC7B,KAAK,CAAC,KAAK,IAAI,CAAC;QAChB,KAAK,CAAC,KAAK,GAAG,aAAa;IAC7B,OAAO,EAAE,CACP,IAAkB,EAClB,KAAuE,EAC/D,EAAE;QACV,IAAI,KAAK,KAAK,SAAS,IAAI,IAAI,CAAC,YAAY,KAAK,SAAS;YACxD,MAAM,IAAI,SAAS,CAAC,2CAA2C,CAAC,CAAC;QACnE,IAAI,IAAI,CAAC,YAAY,CAAC,OAAO,KAAK,KAAK,CAAC,OAAO;YAC7C,OAAO,IAAI,CAAC,YAAY,CAAC,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC5D,OAAO,IAAI,CAAC,YAAY,CAAC,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC;IAC/C,CAAC;CACF,CAAC,CAAC;AAEH;;GAEG;AACH,MAAM,cAAc,GAgCf,MAAM,CAAC,MAAM,CAAC;IACjB,OAAO,EAAE,CACP,MAAc,EACd,WAAqC,EACrC,YAAY,GAAG,4CAA4C,EACrC,EAAE;QACxB,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;QAC7C,IAAI,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,UAAU,GAAG,sBAAsB;YAChE,MAAM,cAAc,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC;QAC/C,OAAO,QAAQ,CAAC;IAClB,CAAC;IACD,OAAO,EAAE,CAAC,OAAe,EAAgB,EAAE,CAAC,IAAI,YAAY,CAAC,OAAO,EAAE,IAAI,CAAC,eAAe,CAAC;IAC3F,SAAS,EAAE,CAAC,OAAe,EAAgB,EAAE,CAAC,IAAI,YAAY,CAAC,OAAO,EAAE,IAAI,CAAC,iBAAiB,CAAC;CAChG,CAAC,CAAC"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Delivery-server resource limits. They deliberately remain well below the
|
|
3
|
+
* 4 MiB delivery RPC ceiling, so one bounded shard response can be encoded.
|
|
4
|
+
*/
|
|
5
|
+
export interface DeliveryStateLimits {
|
|
6
|
+
/**
|
|
7
|
+
* Limits retained messages.
|
|
8
|
+
*/
|
|
9
|
+
readonly maxRetainedMessages: number;
|
|
10
|
+
/**
|
|
11
|
+
* Limits retained serialized bytes.
|
|
12
|
+
*/
|
|
13
|
+
readonly maxRetainedBytes: number;
|
|
14
|
+
/**
|
|
15
|
+
* Limits tracked shards.
|
|
16
|
+
*/
|
|
17
|
+
readonly maxTrackedShards: number;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Limits encoded delivery RPC bytes.
|
|
21
|
+
*/
|
|
22
|
+
export declare const MAX_DELIVERY_RPC_BYTES = 4194304;
|
|
23
|
+
/**
|
|
24
|
+
* Limits messages accepted in one batch.
|
|
25
|
+
*/
|
|
26
|
+
export declare const MAX_DELIVERY_BATCH_MESSAGES = 100;
|
|
27
|
+
/**
|
|
28
|
+
* Limits encoded Inbox payload bytes.
|
|
29
|
+
*/
|
|
30
|
+
export declare const MAX_INBOX_PAYLOAD_BYTES = 1048576;
|
|
31
|
+
/**
|
|
32
|
+
* Leaves room for the optional/page response wrapper below the RPC ceiling.
|
|
33
|
+
*/
|
|
34
|
+
export declare const MAX_INBOX_RECORD_BYTES: number;
|
|
35
|
+
/**
|
|
36
|
+
* Limits shards in a delivery response.
|
|
37
|
+
*/
|
|
38
|
+
export declare const MAX_DELIVERY_RESPONSE_SHARDS = 1000;
|
|
39
|
+
/**
|
|
40
|
+
* Keeps one bounded 1,000-session expiration response below the 4 MiB RPC ceiling.
|
|
41
|
+
*/
|
|
42
|
+
export declare const MAX_DELIVERY_WORKER_BYTES = 128;
|
|
43
|
+
/**
|
|
44
|
+
* Limits generic delivery integer values.
|
|
45
|
+
*/
|
|
46
|
+
export declare const MAX_DELIVERY_LIMIT = 2147483647;
|
|
47
|
+
/**
|
|
48
|
+
* Provides default retained-state bounds.
|
|
49
|
+
*/
|
|
50
|
+
export declare const DEFAULT_DELIVERY_STATE_LIMITS: DeliveryStateLimits;
|
|
51
|
+
/**
|
|
52
|
+
* Provides delivery limit validation.
|
|
53
|
+
*/
|
|
54
|
+
export declare const DeliveryLimits: Readonly<{
|
|
55
|
+
/**
|
|
56
|
+
* Resolves and validates retained-state limits.
|
|
57
|
+
*
|
|
58
|
+
* @param options Overrides default retained-state bounds.
|
|
59
|
+
* @returns Provides frozen validated limits.
|
|
60
|
+
*/
|
|
61
|
+
resolve(options?: Partial<DeliveryStateLimits>): DeliveryStateLimits;
|
|
62
|
+
require(value: number, maximum: number, name: string): void;
|
|
63
|
+
}>;
|
|
64
|
+
//# sourceMappingURL=limits.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"limits.d.ts","sourceRoot":"","sources":["../../src/core/limits.ts"],"names":[],"mappings":"AAcA;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IAGlC;;OAEG;IACH,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAAC;IAErC;;OAEG;IACH,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAElC;;OAEG;IACH,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;CACnC;AAED;;GAEG;AACH,eAAO,MAAM,sBAAsB,UAAY,CAAC;AAEhD;;GAEG;AACH,eAAO,MAAM,2BAA2B,MAAM,CAAC;AAE/C;;GAEG;AACH,eAAO,MAAM,uBAAuB,UAAY,CAAC;AAEjD;;GAEG;AACH,eAAO,MAAM,sBAAsB,EAAE,MAAoC,CAAC;AAE1E;;GAEG;AACH,eAAO,MAAM,4BAA4B,OAAQ,CAAC;AAElD;;GAEG;AACH,eAAO,MAAM,yBAAyB,MAAM,CAAC;AAE7C;;GAEG;AACH,eAAO,MAAM,kBAAkB,aAAgB,CAAC;AAEhD;;GAEG;AACH,eAAO,MAAM,6BAA6B,EAAE,mBAI1C,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,cAAc,EAAE,QAAQ,CAAC;IAGpC;;;;;OAKG;IACH,OAAO,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC,mBAAmB,CAAC,GAAG,mBAAmB,CAAC;IACrE,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7D,CAyBC,CAAC"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2026, CodeMatters. All rights reserved.
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
|
5
|
+
* in compliance with the License. You may obtain a copy of the License at
|
|
6
|
+
*
|
|
7
|
+
* https://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
*
|
|
9
|
+
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
|
10
|
+
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
|
11
|
+
* or implied. See the License for the specific language governing permissions and limitations under
|
|
12
|
+
* the License.
|
|
13
|
+
*/
|
|
14
|
+
/**
|
|
15
|
+
* Limits encoded delivery RPC bytes.
|
|
16
|
+
*/
|
|
17
|
+
export const MAX_DELIVERY_RPC_BYTES = 4_194_304;
|
|
18
|
+
/**
|
|
19
|
+
* Limits messages accepted in one batch.
|
|
20
|
+
*/
|
|
21
|
+
export const MAX_DELIVERY_BATCH_MESSAGES = 100;
|
|
22
|
+
/**
|
|
23
|
+
* Limits encoded Inbox payload bytes.
|
|
24
|
+
*/
|
|
25
|
+
export const MAX_INBOX_PAYLOAD_BYTES = 1_048_576;
|
|
26
|
+
/**
|
|
27
|
+
* Leaves room for the optional/page response wrapper below the RPC ceiling.
|
|
28
|
+
*/
|
|
29
|
+
export const MAX_INBOX_RECORD_BYTES = MAX_DELIVERY_RPC_BYTES - 64;
|
|
30
|
+
/**
|
|
31
|
+
* Limits shards in a delivery response.
|
|
32
|
+
*/
|
|
33
|
+
export const MAX_DELIVERY_RESPONSE_SHARDS = 1_000;
|
|
34
|
+
/**
|
|
35
|
+
* Keeps one bounded 1,000-session expiration response below the 4 MiB RPC ceiling.
|
|
36
|
+
*/
|
|
37
|
+
export const MAX_DELIVERY_WORKER_BYTES = 128;
|
|
38
|
+
/**
|
|
39
|
+
* Limits generic delivery integer values.
|
|
40
|
+
*/
|
|
41
|
+
export const MAX_DELIVERY_LIMIT = 2_147_483_647;
|
|
42
|
+
/**
|
|
43
|
+
* Provides default retained-state bounds.
|
|
44
|
+
*/
|
|
45
|
+
export const DEFAULT_DELIVERY_STATE_LIMITS = Object.freeze({
|
|
46
|
+
maxRetainedMessages: 10_000,
|
|
47
|
+
maxRetainedBytes: 32 * 1_024 * 1_024,
|
|
48
|
+
maxTrackedShards: MAX_DELIVERY_RESPONSE_SHARDS,
|
|
49
|
+
});
|
|
50
|
+
/**
|
|
51
|
+
* Provides delivery limit validation.
|
|
52
|
+
*/
|
|
53
|
+
export const DeliveryLimits = Object.freeze({
|
|
54
|
+
resolve(options = {}) {
|
|
55
|
+
const limits = {
|
|
56
|
+
maxRetainedMessages: options.maxRetainedMessages ?? DEFAULT_DELIVERY_STATE_LIMITS.maxRetainedMessages,
|
|
57
|
+
maxRetainedBytes: options.maxRetainedBytes ?? DEFAULT_DELIVERY_STATE_LIMITS.maxRetainedBytes,
|
|
58
|
+
maxTrackedShards: options.maxTrackedShards ?? DEFAULT_DELIVERY_STATE_LIMITS.maxTrackedShards,
|
|
59
|
+
};
|
|
60
|
+
DeliveryLimits.require(limits.maxRetainedMessages, MAX_DELIVERY_LIMIT, "maxRetainedMessages");
|
|
61
|
+
DeliveryLimits.require(limits.maxRetainedBytes, MAX_DELIVERY_LIMIT, "maxRetainedBytes");
|
|
62
|
+
DeliveryLimits.require(limits.maxTrackedShards, MAX_DELIVERY_RESPONSE_SHARDS, "maxTrackedShards");
|
|
63
|
+
return Object.freeze(limits);
|
|
64
|
+
},
|
|
65
|
+
/**
|
|
66
|
+
* Requires a bounded positive integer limit.
|
|
67
|
+
*/
|
|
68
|
+
require(value, maximum, name) {
|
|
69
|
+
if (!Number.isSafeInteger(value) || value < 1 || value > maximum)
|
|
70
|
+
throw new RangeError(`Delivery server ${name} is invalid.`);
|
|
71
|
+
},
|
|
72
|
+
});
|
|
73
|
+
//# sourceMappingURL=limits.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"limits.js","sourceRoot":"","sources":["../../src/core/limits.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAyBH;;GAEG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,SAAS,CAAC;AAEhD;;GAEG;AACH,MAAM,CAAC,MAAM,2BAA2B,GAAG,GAAG,CAAC;AAE/C;;GAEG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,SAAS,CAAC;AAEjD;;GAEG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAW,sBAAsB,GAAG,EAAE,CAAC;AAE1E;;GAEG;AACH,MAAM,CAAC,MAAM,4BAA4B,GAAG,KAAK,CAAC;AAElD;;GAEG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,GAAG,CAAC;AAE7C;;GAEG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,aAAa,CAAC;AAEhD;;GAEG;AACH,MAAM,CAAC,MAAM,6BAA6B,GAAwB,MAAM,CAAC,MAAM,CAAC;IAC9E,mBAAmB,EAAE,MAAM;IAC3B,gBAAgB,EAAE,EAAE,GAAG,KAAK,GAAG,KAAK;IACpC,gBAAgB,EAAE,4BAA4B;CAC/C,CAAC,CAAC;AAEH;;GAEG;AACH,MAAM,CAAC,MAAM,cAAc,GAWtB,MAAM,CAAC,MAAM,CAAC;IACjB,OAAO,CAAC,UAAwC,EAAE;QAChD,MAAM,MAAM,GAAG;YACb,mBAAmB,EACjB,OAAO,CAAC,mBAAmB,IAAI,6BAA6B,CAAC,mBAAmB;YAClF,gBAAgB,EAAE,OAAO,CAAC,gBAAgB,IAAI,6BAA6B,CAAC,gBAAgB;YAC5F,gBAAgB,EAAE,OAAO,CAAC,gBAAgB,IAAI,6BAA6B,CAAC,gBAAgB;SAC7F,CAAC;QACF,cAAc,CAAC,OAAO,CAAC,MAAM,CAAC,mBAAmB,EAAE,kBAAkB,EAAE,qBAAqB,CAAC,CAAC;QAC9F,cAAc,CAAC,OAAO,CAAC,MAAM,CAAC,gBAAgB,EAAE,kBAAkB,EAAE,kBAAkB,CAAC,CAAC;QACxF,cAAc,CAAC,OAAO,CACpB,MAAM,CAAC,gBAAgB,EACvB,4BAA4B,EAC5B,kBAAkB,CACnB,CAAC;QACF,OAAO,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAC/B,CAAC;IAED;;OAEG;IACH,OAAO,CAAC,KAAa,EAAE,OAAe,EAAE,IAAY;QAClD,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,IAAI,KAAK,GAAG,OAAO;YAC9D,MAAM,IAAI,UAAU,CAAC,mBAAmB,IAAI,cAAc,CAAC,CAAC;IAChE,CAAC;CACF,CAAC,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A finite FIFO boundary for all state-changing delivery operations.
|
|
3
|
+
*/
|
|
4
|
+
export declare class MutationAdmission {
|
|
5
|
+
#private;
|
|
6
|
+
/**
|
|
7
|
+
* Closes admission and rejects pending mutations.
|
|
8
|
+
*/
|
|
9
|
+
close(): void;
|
|
10
|
+
/**
|
|
11
|
+
* Queues one synchronous state mutation.
|
|
12
|
+
* @param signal Cancels admission before commit.
|
|
13
|
+
* @param commit Performs the linearized mutation.
|
|
14
|
+
* @returns Resolves with the committed value.
|
|
15
|
+
*/
|
|
16
|
+
run<T>(signal: AbortSignal | undefined, commit: () => T): Promise<T>;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=mutation-admission.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mutation-admission.d.ts","sourceRoot":"","sources":["../../src/core/mutation-admission.ts"],"names":[],"mappings":"AAgBA;;GAEG;AACH,qBAAa,iBAAiB;;IAK5B;;OAEG;IACH,KAAK,IAAI,IAAI;IAOb;;;;;OAKG;IACH,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,WAAW,GAAG,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;CAwCrE"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2026, CodeMatters. All rights reserved.
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
|
5
|
+
* in compliance with the License. You may obtain a copy of the License at
|
|
6
|
+
*
|
|
7
|
+
* https://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
*
|
|
9
|
+
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
|
10
|
+
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
|
11
|
+
* or implied. See the License for the specific language governing permissions and limitations under
|
|
12
|
+
* the License.
|
|
13
|
+
*/
|
|
14
|
+
import { Code, ConnectError } from "@connectrpc/connect";
|
|
15
|
+
/**
|
|
16
|
+
* A finite FIFO boundary for all state-changing delivery operations.
|
|
17
|
+
*/
|
|
18
|
+
export class MutationAdmission {
|
|
19
|
+
#pending = [];
|
|
20
|
+
#scheduled = false;
|
|
21
|
+
#closed = false;
|
|
22
|
+
/**
|
|
23
|
+
* Closes admission and rejects pending mutations.
|
|
24
|
+
*/
|
|
25
|
+
close() {
|
|
26
|
+
this.#closed = true;
|
|
27
|
+
const error = new ConnectError("Delivery server is closed.", Code.Unavailable);
|
|
28
|
+
for (const pending of this.#pending)
|
|
29
|
+
pending.reject(error);
|
|
30
|
+
this.#pending = [];
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Queues one synchronous state mutation.
|
|
34
|
+
* @param signal Cancels admission before commit.
|
|
35
|
+
* @param commit Performs the linearized mutation.
|
|
36
|
+
* @returns Resolves with the committed value.
|
|
37
|
+
*/
|
|
38
|
+
run(signal, commit) {
|
|
39
|
+
if (this.#closed)
|
|
40
|
+
return Promise.reject(new ConnectError("Delivery server is closed.", Code.Unavailable));
|
|
41
|
+
if (signal?.aborted)
|
|
42
|
+
return Promise.reject(this.#abortError(signal));
|
|
43
|
+
if (this.#pending.length >= 100)
|
|
44
|
+
return Promise.reject(new ConnectError("Delivery mutation queue is full.", Code.ResourceExhausted));
|
|
45
|
+
return new Promise((resolve, reject) => {
|
|
46
|
+
const admission = () => {
|
|
47
|
+
if (signal?.aborted) {
|
|
48
|
+
reject(this.#abortError(signal));
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
try {
|
|
52
|
+
resolve(commit());
|
|
53
|
+
}
|
|
54
|
+
catch (error) {
|
|
55
|
+
reject(error instanceof Error ? error : new Error("Delivery mutation failed."));
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
this.#pending.push({ admit: admission, reject });
|
|
59
|
+
if (!this.#scheduled) {
|
|
60
|
+
this.#scheduled = true;
|
|
61
|
+
queueMicrotask(() => {
|
|
62
|
+
this.#flush();
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
#flush() {
|
|
68
|
+
this.#scheduled = false;
|
|
69
|
+
const pending = this.#pending;
|
|
70
|
+
this.#pending = [];
|
|
71
|
+
for (const admission of pending)
|
|
72
|
+
admission.admit();
|
|
73
|
+
}
|
|
74
|
+
#abortError(signal) {
|
|
75
|
+
return signal.reason instanceof Error ? signal.reason : new Error("Delivery mutation aborted.");
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=mutation-admission.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mutation-admission.js","sourceRoot":"","sources":["../../src/core/mutation-admission.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAEzD;;GAEG;AACH,MAAM,OAAO,iBAAiB;IAC5B,QAAQ,GAA8E,EAAE,CAAC;IACzF,UAAU,GAAG,KAAK,CAAC;IACnB,OAAO,GAAG,KAAK,CAAC;IAEhB;;OAEG;IACH,KAAK;QACH,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QACpB,MAAM,KAAK,GAAG,IAAI,YAAY,CAAC,4BAA4B,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;QAC/E,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,QAAQ;YAAE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC3D,IAAI,CAAC,QAAQ,GAAG,EAAE,CAAC;IACrB,CAAC;IAED;;;;;OAKG;IACH,GAAG,CAAI,MAA+B,EAAE,MAAe;QACrD,IAAI,IAAI,CAAC,OAAO;YACd,OAAO,OAAO,CAAC,MAAM,CAAC,IAAI,YAAY,CAAC,4BAA4B,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC;QAC1F,IAAI,MAAM,EAAE,OAAO;YAAE,OAAO,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC;QACrE,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,IAAI,GAAG;YAC7B,OAAO,OAAO,CAAC,MAAM,CACnB,IAAI,YAAY,CAAC,kCAAkC,EAAE,IAAI,CAAC,iBAAiB,CAAC,CAC7E,CAAC;QACJ,OAAO,IAAI,OAAO,CAAI,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACxC,MAAM,SAAS,GAAG,GAAG,EAAE;gBACrB,IAAI,MAAM,EAAE,OAAO,EAAE,CAAC;oBACpB,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC;oBACjC,OAAO;gBACT,CAAC;gBACD,IAAI,CAAC;oBACH,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;gBACpB,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,MAAM,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC,CAAC;gBAClF,CAAC;YACH,CAAC,CAAC;YACF,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC,CAAC;YACjD,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;gBACrB,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;gBACvB,cAAc,CAAC,GAAG,EAAE;oBAClB,IAAI,CAAC,MAAM,EAAE,CAAC;gBAChB,CAAC,CAAC,CAAC;YACL,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;IAED,MAAM;QACJ,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC;QACxB,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC;QAC9B,IAAI,CAAC,QAAQ,GAAG,EAAE,CAAC;QACnB,KAAK,MAAM,SAAS,IAAI,OAAO;YAAE,SAAS,CAAC,KAAK,EAAE,CAAC;IACrD,CAAC;IAED,WAAW,CAAC,MAAmB;QAC7B,OAAO,MAAM,CAAC,MAAM,YAAY,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;IAClG,CAAC;CACF"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { type ServiceImpl } from "@connectrpc/connect";
|
|
2
|
+
import { ShardService } from "@spine-event-engine/proto/delivery-server";
|
|
3
|
+
import type { ShardIndex } from "@spine-event-engine/proto/delivery";
|
|
4
|
+
import { InMemoryDeliveryState } from "./in-memory-delivery-state.js";
|
|
5
|
+
import { MutationAdmission } from "./mutation-admission.js";
|
|
6
|
+
/**
|
|
7
|
+
* Provides Shard RPC handler implementations.
|
|
8
|
+
*/
|
|
9
|
+
export declare const ShardHandlers: Readonly<{
|
|
10
|
+
/**
|
|
11
|
+
* Creates Shard RPC handlers.
|
|
12
|
+
*
|
|
13
|
+
* @param state Stores the Shard sessions served by the handlers.
|
|
14
|
+
* @param admission Controls mutation admission and cancellation.
|
|
15
|
+
* @param now Supplies the current millisecond time.
|
|
16
|
+
* @param processingTimeoutMs Holds the automatic processing timeout.
|
|
17
|
+
* @param onTransition Observes picked and released shard transitions.
|
|
18
|
+
* @returns The Shard service implementation.
|
|
19
|
+
*/
|
|
20
|
+
create: (state: InMemoryDeliveryState, admission: MutationAdmission, now: () => number, processingTimeoutMs: number, onTransition?: (shard: ShardIndex) => void) => ServiceImpl<typeof ShardService>;
|
|
21
|
+
}>;
|
|
22
|
+
//# sourceMappingURL=shard-service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shard-service.d.ts","sourceRoot":"","sources":["../../src/core/shard-service.ts"],"names":[],"mappings":"AAeA,OAAO,EAAsB,KAAK,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAC3E,OAAO,EAML,YAAY,EACb,MAAM,2CAA2C,CAAC;AACnD,OAAO,KAAK,EAAE,UAAU,EAAY,MAAM,oCAAoC,CAAC;AAE/E,OAAO,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AAEtE,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAG5D;;GAEG;AACH,eAAO,MAAM,aAAa,EAAE,QAAQ,CAAC;IAGnC;;;;;;;;;OASG;IACH,MAAM,EAAE,CACN,KAAK,EAAE,qBAAqB,EAC5B,SAAS,EAAE,iBAAiB,EAC5B,GAAG,EAAE,MAAM,MAAM,EACjB,mBAAmB,EAAE,MAAM,EAC3B,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,KACvC,WAAW,CAAC,OAAO,YAAY,CAAC,CAAC;CACvC,CA6GC,CAAC"}
|