@yielded/agent-storage-memory 0.1.0-beta.169 → 0.1.0-beta.170
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/MemoryMessageDeliveryStore.d.mts +1 -1
- package/dist/MemoryMessageDeliveryStore.mjs +28 -2
- package/dist/MemoryMessageDeliveryStore.mjs.map +1 -1
- package/dist/MemorySubmissionLedger.d.mts +1 -1
- package/dist/MemorySubscriptionStore.mjs +94 -18
- package/dist/MemorySubscriptionStore.mjs.map +1 -1
- package/dist/MemoryThreadStore.d.mts +1 -1
- package/dist/MemoryThreadStore.mjs +2 -9
- package/dist/MemoryThreadStore.mjs.map +1 -1
- package/dist/{MemoryThreadStoreKernel-DYNDjlhO.d.mts → MemoryThreadStoreKernel-h_k2t46J.d.mts} +2 -2
- package/dist/WorkSelection-CmqTuws3.mjs.map +1 -1
- package/package.json +1 -1
- package/src/MemoryMessageDeliveryStore.ts +43 -2
- package/src/MemorySubscriptionStore.ts +252 -99
- package/src/MemoryThreadStore.ts +2 -8
- package/src/internal/MemoryThreadStoreKernel.ts +1 -1
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.mjs";
|
|
2
2
|
import { compareScheduleNames } from "@yielded/agent/schedule-transition";
|
|
3
3
|
import { Clock, Effect, Layer, Ref, Result, Schema } from "effect";
|
|
4
|
-
import { AcceptedEvent, DeliveryChange, SourcePartition, SubscriptionChange, SubscriptionDelivery, SubscriptionDeliveryKey, SubscriptionError, SubscriptionFailpoint, SubscriptionKey, SubscriptionLimits, SubscriptionName, SubscriptionRecord, SubscriptionRetentionPolicy, SubscriptionScanCursors, SubscriptionStore, subscriptionDeliveryKeyString, subscriptionKeyString } from "@yielded/agent/subscription";
|
|
4
|
+
import { AcceptedEvent, DeliveryChange, SourcePartition, SubscriptionChange, SubscriptionDelivery, SubscriptionDeliveryKey, SubscriptionError, SubscriptionFailpoint, SubscriptionKey, SubscriptionLimits, SubscriptionName, SubscriptionRecord, SubscriptionRetentionPolicy, SubscriptionScanCursors, SubscriptionStore, defaultSubscriptionLimits, subscriptionDeliveryKeyString, subscriptionKeyString } from "@yielded/agent/subscription";
|
|
5
5
|
import { Digest } from "@yielded/agent/records";
|
|
6
|
-
import { applySubscriptionChange, applySubscriptionDeliveryChange, sameAcceptedEventIdentity, subscriptionCanSelect, subscriptionDeliveryCanSelect, validateEventRetention } from "@yielded/agent/subscription-transition";
|
|
6
|
+
import { applySubscriptionChange, applySubscriptionDeliveryChange, sameAcceptedEventIdentity, subscriptionCanSelect, subscriptionDeliveryCanSelect, subscriptionDeliveryUsesCapacity, subscriptionUsesCapacity, validateEventRetention } from "@yielded/agent/subscription-transition";
|
|
7
7
|
//#region src/MemorySubscriptionStore.ts
|
|
8
8
|
var MemorySubscriptionStore_exports = /* @__PURE__ */ __exportAll({ memorySubscriptionStoreLayer: () => memorySubscriptionStoreLayer });
|
|
9
9
|
const error = (reason, code) => SubscriptionError.make({
|
|
@@ -65,6 +65,41 @@ const insertKey = (keys, key) => {
|
|
|
65
65
|
...keys.slice(at)
|
|
66
66
|
];
|
|
67
67
|
};
|
|
68
|
+
const expiryUpperBound = (expiries, nowMillis) => {
|
|
69
|
+
let low = 0;
|
|
70
|
+
let high = expiries.length;
|
|
71
|
+
while (low < high) {
|
|
72
|
+
const middle = Math.floor((low + high) / 2);
|
|
73
|
+
const expiry = expiries[middle];
|
|
74
|
+
if (expiry !== void 0 && expiry <= nowMillis) low = middle + 1;
|
|
75
|
+
else high = middle;
|
|
76
|
+
}
|
|
77
|
+
return low;
|
|
78
|
+
};
|
|
79
|
+
const registrationCount = (current, nowMillis, ownerId) => {
|
|
80
|
+
const expiries = ownerId === void 0 ? current.registrationExpiries : current.ownerRegistrationExpiries.get(ownerId) ?? [];
|
|
81
|
+
return expiries.length - expiryUpperBound(expiries, nowMillis);
|
|
82
|
+
};
|
|
83
|
+
const registrationExpiriesAfter = (current, before, after) => {
|
|
84
|
+
const expiry = (record) => record !== void 0 && (record.state === "active" || record.state === "paused") ? record.configuration.expiresAtMillis ?? Number.POSITIVE_INFINITY : null;
|
|
85
|
+
const previous = expiry(before);
|
|
86
|
+
const next = expiry(after);
|
|
87
|
+
const replace = (expiries) => {
|
|
88
|
+
if (previous === next) return expiries;
|
|
89
|
+
const updated = [...expiries];
|
|
90
|
+
if (previous !== null) updated.splice(expiryUpperBound(updated, previous) - 1, 1);
|
|
91
|
+
if (next !== null) updated.splice(expiryUpperBound(updated, next), 0, next);
|
|
92
|
+
return updated;
|
|
93
|
+
};
|
|
94
|
+
const owners = new Map(current.ownerRegistrationExpiries);
|
|
95
|
+
const expiries = replace(owners.get(after.key.ownerId) ?? []);
|
|
96
|
+
if (expiries.length === 0) owners.delete(after.key.ownerId);
|
|
97
|
+
else owners.set(after.key.ownerId, expiries);
|
|
98
|
+
return {
|
|
99
|
+
registrationExpiries: replace(current.registrationExpiries),
|
|
100
|
+
ownerRegistrationExpiries: owners
|
|
101
|
+
};
|
|
102
|
+
};
|
|
68
103
|
const recoveryCountsAfter = (current, next, keys) => {
|
|
69
104
|
const counts = new Map(current.recoveryCounts);
|
|
70
105
|
for (const key of keys) {
|
|
@@ -94,10 +129,13 @@ const makeMemorySubscriptionStore = Effect.fnUntraced(function* (ownedPartition)
|
|
|
94
129
|
deliveries: /* @__PURE__ */ new Map(),
|
|
95
130
|
registrationIndex: /* @__PURE__ */ new Map(),
|
|
96
131
|
candidateIndex: /* @__PURE__ */ new Map(),
|
|
97
|
-
|
|
132
|
+
registrationExpiries: [],
|
|
133
|
+
ownerRegistrationExpiries: /* @__PURE__ */ new Map(),
|
|
98
134
|
eventIndex: /* @__PURE__ */ new Map(),
|
|
99
135
|
deliveryIndex: /* @__PURE__ */ new Map(),
|
|
100
136
|
ownerDeliveryCounts: /* @__PURE__ */ new Map(),
|
|
137
|
+
liveDeliveryCount: 0,
|
|
138
|
+
pendingEventCount: 0,
|
|
101
139
|
scanCursors: {
|
|
102
140
|
events: "",
|
|
103
141
|
deliveries: "",
|
|
@@ -112,6 +150,7 @@ const makeMemorySubscriptionStore = Effect.fnUntraced(function* (ownedPartition)
|
|
|
112
150
|
const limits = yield* validate(SubscriptionLimits, inputLimits, "register-limits");
|
|
113
151
|
yield* requirePartition(record.key, "register-partition");
|
|
114
152
|
yield* failpoint.hit("subscription:register:before");
|
|
153
|
+
const nowMillis = yield* Clock.currentTimeMillis;
|
|
115
154
|
const result = yield* Effect.uninterruptible(Ref.modify(state, (current) => {
|
|
116
155
|
const key = subscriptionKeyString(record.key);
|
|
117
156
|
const existingText = current.registrations.get(key);
|
|
@@ -123,9 +162,8 @@ const makeMemorySubscriptionStore = Effect.fnUntraced(function* (ownedPartition)
|
|
|
123
162
|
if (jsonBytes(record.configuration.context) > limits.maxContextBytes) return [Result.fail(error("capacity", "context-bytes")), current];
|
|
124
163
|
if (jsonBytes(record.configuration.parameters) > limits.maxPayloadBytes) return [Result.fail(error("capacity", "parameters-bytes")), current];
|
|
125
164
|
if (record.configuration.expiresAtMillis !== null && record.configuration.expiresAtMillis - record.createdAtMillis > limits.maxLifetimeMillis) return [Result.fail(error("capacity", "lifetime")), current];
|
|
126
|
-
if (current
|
|
127
|
-
|
|
128
|
-
if (ownerCount >= limits.maxRegistrationsPerOwner) return [Result.fail(error("capacity", "owner-registrations")), current];
|
|
165
|
+
if (subscriptionUsesCapacity(record, nowMillis) && registrationCount(current, nowMillis) >= limits.maxRegistrations) return [Result.fail(error("capacity", "registrations")), current];
|
|
166
|
+
if (subscriptionUsesCapacity(record, nowMillis) && registrationCount(current, nowMillis, record.key.ownerId) >= limits.maxRegistrationsPerOwner) return [Result.fail(error("capacity", "owner-registrations")), current];
|
|
129
167
|
const assigned = {
|
|
130
168
|
...record,
|
|
131
169
|
ordinal: current.sequence + 1
|
|
@@ -145,8 +183,6 @@ const makeMemorySubscriptionStore = Effect.fnUntraced(function* (ownedPartition)
|
|
|
145
183
|
const candidateIndex = new Map(current.candidateIndex);
|
|
146
184
|
const candidateKey = candidateIndexKey(assigned);
|
|
147
185
|
candidateIndex.set(candidateKey, [...candidateIndex.get(candidateKey) ?? [], key]);
|
|
148
|
-
const ownerRegistrationCounts = new Map(current.ownerRegistrationCounts);
|
|
149
|
-
ownerRegistrationCounts.set(assigned.key.ownerId, ownerCount + 1);
|
|
150
186
|
return [Result.succeed(assigned), {
|
|
151
187
|
...current,
|
|
152
188
|
sequence: assigned.ordinal,
|
|
@@ -154,7 +190,7 @@ const makeMemorySubscriptionStore = Effect.fnUntraced(function* (ownedPartition)
|
|
|
154
190
|
registrationIndex,
|
|
155
191
|
recoveryCounts: recoveryCountsAfter(current, registrationIndex, [key]),
|
|
156
192
|
candidateIndex,
|
|
157
|
-
|
|
193
|
+
...registrationExpiriesAfter(current, void 0, assigned)
|
|
158
194
|
}];
|
|
159
195
|
})).pipe(Effect.flatMap(Effect.fromResult));
|
|
160
196
|
yield* failpoint.hit("subscription:register:after");
|
|
@@ -178,11 +214,13 @@ const makeMemorySubscriptionStore = Effect.fnUntraced(function* (ownedPartition)
|
|
|
178
214
|
records.sort((a, b) => a.ordinal - b.ordinal);
|
|
179
215
|
return records.slice(0, limit);
|
|
180
216
|
});
|
|
181
|
-
const change = Effect.fnUntraced(function* (input, expectedRevision, inputChange) {
|
|
217
|
+
const change = Effect.fnUntraced(function* (input, expectedRevision, inputChange, inputLimits = defaultSubscriptionLimits) {
|
|
182
218
|
const key = yield* requireKey(input, "change-key");
|
|
183
219
|
const change = yield* validate(SubscriptionChange, inputChange, "change");
|
|
220
|
+
const limits = yield* validate(SubscriptionLimits, inputLimits, "change-limits");
|
|
184
221
|
yield* validate(Schema.Int.check(Schema.isGreaterThan(0)), expectedRevision, "revision");
|
|
185
222
|
yield* failpoint.hit("subscription:change:before");
|
|
223
|
+
const nowMillis = yield* Clock.currentTimeMillis;
|
|
186
224
|
const updated = yield* Effect.uninterruptible(Ref.modify(state, (current) => {
|
|
187
225
|
const storageKey = subscriptionKeyString(key);
|
|
188
226
|
const text = current.registrations.get(storageKey);
|
|
@@ -191,6 +229,10 @@ const makeMemorySubscriptionStore = Effect.fnUntraced(function* (ownedPartition)
|
|
|
191
229
|
if (Result.isFailure(existing)) return [existing, current];
|
|
192
230
|
const updated = applySubscriptionChange(existing.success, expectedRevision, change);
|
|
193
231
|
if (Result.isFailure(updated)) return [updated, current];
|
|
232
|
+
if (!subscriptionUsesCapacity(existing.success, nowMillis) && subscriptionUsesCapacity(updated.success, nowMillis)) {
|
|
233
|
+
if (registrationCount(current, nowMillis) >= limits.maxRegistrations) return [Result.fail(error("capacity", "registrations")), current];
|
|
234
|
+
if (registrationCount(current, nowMillis, key.ownerId) >= limits.maxRegistrationsPerOwner) return [Result.fail(error("capacity", "owner-registrations")), current];
|
|
235
|
+
}
|
|
194
236
|
const revised = {
|
|
195
237
|
...updated.success,
|
|
196
238
|
ordinal: current.sequence + 1
|
|
@@ -218,6 +260,7 @@ const makeMemorySubscriptionStore = Effect.fnUntraced(function* (ownedPartition)
|
|
|
218
260
|
registrations,
|
|
219
261
|
registrationIndex,
|
|
220
262
|
candidateIndex,
|
|
263
|
+
...registrationExpiriesAfter(current, existing.success, revised),
|
|
221
264
|
recoveryCounts: recoveryCountsAfter(current, registrationIndex, [storageKey])
|
|
222
265
|
}];
|
|
223
266
|
})).pipe(Effect.flatMap(Effect.fromResult));
|
|
@@ -263,6 +306,7 @@ const makeMemorySubscriptionStore = Effect.fnUntraced(function* (ownedPartition)
|
|
|
263
306
|
...current,
|
|
264
307
|
registrations,
|
|
265
308
|
registrationIndex,
|
|
309
|
+
...registrationExpiriesAfter(current, decoded.success, cancelled),
|
|
266
310
|
recoveryCounts: recoveryCountsAfter(current, registrationIndex, [storageKey])
|
|
267
311
|
}];
|
|
268
312
|
})).pipe(Effect.flatMap(Effect.fromResult));
|
|
@@ -286,7 +330,7 @@ const makeMemorySubscriptionStore = Effect.fnUntraced(function* (ownedPartition)
|
|
|
286
330
|
const horizon = validateEventRetention(event, limits, currentTimeMillis);
|
|
287
331
|
if (Result.isFailure(horizon)) return [Result.fail(horizon.failure), current];
|
|
288
332
|
if (jsonBytes(event.payload) > limits.maxPayloadBytes) return [Result.fail(error("capacity", "payload-bytes")), current];
|
|
289
|
-
if (current.
|
|
333
|
+
if (current.pendingEventCount >= limits.maxEvents) return [Result.fail(error("capacity", "events")), current];
|
|
290
334
|
const accepted = {
|
|
291
335
|
...event,
|
|
292
336
|
cutoff: current.sequence + 1,
|
|
@@ -308,6 +352,7 @@ const makeMemorySubscriptionStore = Effect.fnUntraced(function* (ownedPartition)
|
|
|
308
352
|
sequence: accepted.cutoff,
|
|
309
353
|
events,
|
|
310
354
|
eventIndex,
|
|
355
|
+
pendingEventCount: current.pendingEventCount + 1,
|
|
311
356
|
eventKeys: insertKey(current.eventKeys, accepted.eventId),
|
|
312
357
|
retentionHorizon: limits.retention?.replayHorizonMillis ?? current.retentionHorizon,
|
|
313
358
|
retentionDeadline: limits.retention === void 0 ? current.retentionDeadline : accepted.acceptedAtMillis
|
|
@@ -347,6 +392,7 @@ const makeMemorySubscriptionStore = Effect.fnUntraced(function* (ownedPartition)
|
|
|
347
392
|
const select = Effect.fnUntraced(function* (inputEvent, inputDeliveries, cursor, complete, nowMillis, inputLimits) {
|
|
348
393
|
const suppliedEvent = yield* validate(AcceptedEvent, inputEvent, "select-event");
|
|
349
394
|
const deliveries = yield* validate(Schema.Array(SubscriptionDelivery), inputDeliveries, "select-deliveries");
|
|
395
|
+
if (new Set(deliveries.map((delivery) => subscriptionDeliveryKeyString(delivery.key))).size !== deliveries.length) return yield* error("validation", "duplicate-delivery");
|
|
350
396
|
const limits = yield* validate(SubscriptionLimits, inputLimits, "select-limits");
|
|
351
397
|
yield* requirePartition(suppliedEvent, "select-partition");
|
|
352
398
|
yield* failpoint.hit("subscription:select:before");
|
|
@@ -365,6 +411,10 @@ const makeMemorySubscriptionStore = Effect.fnUntraced(function* (ownedPartition)
|
|
|
365
411
|
const additionIndex = [];
|
|
366
412
|
const registrationUpdates = [];
|
|
367
413
|
const owners = new Map(current.ownerDeliveryCounts);
|
|
414
|
+
let registrationCapacity = {
|
|
415
|
+
registrationExpiries: current.registrationExpiries,
|
|
416
|
+
ownerRegistrationExpiries: current.ownerRegistrationExpiries
|
|
417
|
+
};
|
|
368
418
|
for (const delivery of deliveries) {
|
|
369
419
|
const recordText = current.registrations.get(subscriptionKeyString(delivery.key.subscription));
|
|
370
420
|
if (recordText === void 0) return [Result.fail(error("not-found", "subscription")), current];
|
|
@@ -413,9 +463,10 @@ const makeMemorySubscriptionStore = Effect.fnUntraced(function* (ownedPartition)
|
|
|
413
463
|
recoveryAt: null,
|
|
414
464
|
recoveryKey: null
|
|
415
465
|
}]);
|
|
466
|
+
registrationCapacity = registrationExpiriesAfter(registrationCapacity, record.success, consumed);
|
|
416
467
|
}
|
|
417
468
|
}
|
|
418
|
-
if (current.
|
|
469
|
+
if (current.liveDeliveryCount + additions.length > limits.maxDeliveries) return [Result.fail(error("capacity", "deliveries")), current];
|
|
419
470
|
const registrations = new Map(current.registrations);
|
|
420
471
|
for (const [key, value] of updates) registrations.set(key, value);
|
|
421
472
|
const nextDeliveries = new Map(current.deliveries);
|
|
@@ -450,9 +501,12 @@ const makeMemorySubscriptionStore = Effect.fnUntraced(function* (ownedPartition)
|
|
|
450
501
|
events,
|
|
451
502
|
eventIndex,
|
|
452
503
|
deliveries: nextDeliveries,
|
|
504
|
+
liveDeliveryCount: current.liveDeliveryCount + additions.length,
|
|
505
|
+
pendingEventCount: current.pendingEventCount - Number(complete),
|
|
453
506
|
deliveryKeys: additions.reduce((keys, [key]) => insertKey(keys, key), current.deliveryKeys),
|
|
454
507
|
deliveryIndex,
|
|
455
|
-
ownerDeliveryCounts: owners
|
|
508
|
+
ownerDeliveryCounts: owners,
|
|
509
|
+
...registrationCapacity
|
|
456
510
|
}];
|
|
457
511
|
})).pipe(Effect.flatMap(Effect.fromResult));
|
|
458
512
|
yield* failpoint.hit("subscription:select:after");
|
|
@@ -481,7 +535,7 @@ const makeMemorySubscriptionStore = Effect.fnUntraced(function* (ownedPartition)
|
|
|
481
535
|
return sameDeliveryIdentity(existing.success, delivery) ? [Result.void, current] : [Result.fail(error("conflict", "delivery-identity")), current];
|
|
482
536
|
}
|
|
483
537
|
if (!subscriptionCanSelect(record.success, accepted.success, effectiveNowMillis, true)) return [Result.fail(error("conflict", "catch-up-eligibility")), current];
|
|
484
|
-
if (current.
|
|
538
|
+
if (current.liveDeliveryCount >= limits.maxDeliveries) return [Result.fail(error("capacity", "deliveries")), current];
|
|
485
539
|
const ownerCount = current.ownerDeliveryCounts.get(record.success.key.ownerId) ?? 0;
|
|
486
540
|
if (ownerCount >= limits.maxDeliveriesPerOwner) return [Result.fail(error("capacity", "owner-deliveries")), current];
|
|
487
541
|
const encodedDelivery = encode(SubscriptionDelivery, delivery, "catch-up-delivery-encode");
|
|
@@ -523,6 +577,8 @@ const makeMemorySubscriptionStore = Effect.fnUntraced(function* (ownedPartition)
|
|
|
523
577
|
deliveryIndex,
|
|
524
578
|
deliveryKeys: insertKey(current.deliveryKeys, key),
|
|
525
579
|
ownerDeliveryCounts,
|
|
580
|
+
...registrationExpiriesAfter(current, record.success, consumed),
|
|
581
|
+
liveDeliveryCount: current.liveDeliveryCount + 1,
|
|
526
582
|
registrations,
|
|
527
583
|
registrationIndex,
|
|
528
584
|
recoveryCounts: recoveryCountsAfter(current, registrationIndex, [consumedKey]),
|
|
@@ -586,10 +642,11 @@ const makeMemorySubscriptionStore = Effect.fnUntraced(function* (ownedPartition)
|
|
|
586
642
|
items.sort((a, b) => compareScheduleNames(subscriptionDeliveryKeyString(a.key), subscriptionDeliveryKeyString(b.key)));
|
|
587
643
|
return items.slice(0, limit);
|
|
588
644
|
});
|
|
589
|
-
const changeDelivery = Effect.fnUntraced(function* (inputKey, inputDeliveryId, inputChange) {
|
|
645
|
+
const changeDelivery = Effect.fnUntraced(function* (inputKey, inputDeliveryId, inputChange, inputLimits = defaultSubscriptionLimits) {
|
|
590
646
|
const key = yield* validate(SubscriptionDeliveryKey, inputKey, "change-delivery-key");
|
|
591
647
|
const deliveryId = yield* validate(Digest, inputDeliveryId, "change-delivery-id");
|
|
592
648
|
const change = yield* validate(DeliveryChange, inputChange, "change-delivery-change");
|
|
649
|
+
const limits = yield* validate(SubscriptionLimits, inputLimits, "change-delivery-limits");
|
|
593
650
|
yield* requirePartition(key.subscription, "change-delivery-partition");
|
|
594
651
|
yield* failpoint.hit(`subscription:delivery-${change._tag.toLowerCase()}:before`);
|
|
595
652
|
const effectiveChange = change._tag === "Prepare" ? {
|
|
@@ -610,6 +667,13 @@ const makeMemorySubscriptionStore = Effect.fnUntraced(function* (ownedPartition)
|
|
|
610
667
|
if (Result.isFailure(transition)) return [Result.fail(transition.failure), current];
|
|
611
668
|
if (transition.success === decoded.success) return [Result.succeed(decoded.success), current];
|
|
612
669
|
const updated = transition.success;
|
|
670
|
+
const capacityDelta = Number(subscriptionDeliveryUsesCapacity(updated)) - Number(subscriptionDeliveryUsesCapacity(decoded.success));
|
|
671
|
+
const ownerId = key.subscription.ownerId;
|
|
672
|
+
const ownerCount = current.ownerDeliveryCounts.get(ownerId) ?? 0;
|
|
673
|
+
if (capacityDelta > 0) {
|
|
674
|
+
if (current.liveDeliveryCount >= limits.maxDeliveries) return [Result.fail(error("capacity", "deliveries")), current];
|
|
675
|
+
if (ownerCount >= limits.maxDeliveriesPerOwner) return [Result.fail(error("capacity", "owner-deliveries")), current];
|
|
676
|
+
}
|
|
613
677
|
const encoded = encode(SubscriptionDelivery, updated, "change-delivery-encode");
|
|
614
678
|
if (Result.isFailure(encoded)) return [Result.fail(encoded.failure), current];
|
|
615
679
|
const deliveries = new Map(current.deliveries);
|
|
@@ -624,10 +688,15 @@ const makeMemorySubscriptionStore = Effect.fnUntraced(function* (ownedPartition)
|
|
|
624
688
|
observeSettlement: updated.observeSettlement ?? false,
|
|
625
689
|
nextAttemptAtMillis: updated.retry.nextAttemptAtMillis
|
|
626
690
|
});
|
|
691
|
+
const ownerDeliveryCounts = new Map(current.ownerDeliveryCounts);
|
|
692
|
+
if (ownerCount + capacityDelta === 0) ownerDeliveryCounts.delete(ownerId);
|
|
693
|
+
else ownerDeliveryCounts.set(ownerId, ownerCount + capacityDelta);
|
|
627
694
|
return [Result.succeed(updated), {
|
|
628
695
|
...current,
|
|
629
696
|
deliveries,
|
|
630
|
-
deliveryIndex
|
|
697
|
+
deliveryIndex,
|
|
698
|
+
ownerDeliveryCounts,
|
|
699
|
+
liveDeliveryCount: current.liveDeliveryCount + capacityDelta
|
|
631
700
|
}];
|
|
632
701
|
})).pipe(Effect.flatMap(Effect.fromResult));
|
|
633
702
|
yield* failpoint.hit(`subscription:delivery-${change._tag.toLowerCase()}:after`);
|
|
@@ -717,6 +786,7 @@ const makeMemorySubscriptionStore = Effect.fnUntraced(function* (ownedPartition)
|
|
|
717
786
|
const deliveryIndex = new Map(current.deliveryIndex);
|
|
718
787
|
const eventDeliveryCounts = new Map(current.eventDeliveryCounts);
|
|
719
788
|
const ownerDeliveryCounts = new Map(current.ownerDeliveryCounts);
|
|
789
|
+
let liveDeliveryCount = current.liveDeliveryCount;
|
|
720
790
|
const deliveryPage = current.deliveryKeys.slice(upperBound(current.deliveryKeys, current.maintenanceDeliveries), upperBound(current.deliveryKeys, current.maintenanceDeliveries) + limit);
|
|
721
791
|
const eventPage = current.eventKeys.slice(upperBound(current.eventKeys, current.maintenanceEvents), upperBound(current.eventKeys, current.maintenanceEvents) + limit);
|
|
722
792
|
const cutoff = nowMillis - policy.completedRetentionMillis;
|
|
@@ -755,8 +825,13 @@ const makeMemorySubscriptionStore = Effect.fnUntraced(function* (ownedPartition)
|
|
|
755
825
|
removedDeliveries.add(key);
|
|
756
826
|
deliveryIndex.delete(key);
|
|
757
827
|
eventDeliveryCounts.set(event.eventId, (eventDeliveryCounts.get(event.eventId) ?? 1) - 1);
|
|
758
|
-
|
|
759
|
-
|
|
828
|
+
if (subscriptionDeliveryUsesCapacity(delivery)) {
|
|
829
|
+
liveDeliveryCount--;
|
|
830
|
+
const owner = delivery.key.subscription.ownerId;
|
|
831
|
+
const count = (ownerDeliveryCounts.get(owner) ?? 1) - 1;
|
|
832
|
+
if (count === 0) ownerDeliveryCounts.delete(owner);
|
|
833
|
+
else ownerDeliveryCounts.set(owner, count);
|
|
834
|
+
}
|
|
760
835
|
}
|
|
761
836
|
let tombstones = current.tombstoneCount;
|
|
762
837
|
for (const key of eventPage) {
|
|
@@ -803,6 +878,7 @@ const makeMemorySubscriptionStore = Effect.fnUntraced(function* (ownedPartition)
|
|
|
803
878
|
deliveryIndex,
|
|
804
879
|
eventDeliveryCounts,
|
|
805
880
|
ownerDeliveryCounts,
|
|
881
|
+
liveDeliveryCount,
|
|
806
882
|
eventKeys: removeKeys(current.eventKeys, removedEvents),
|
|
807
883
|
deliveryKeys: removeKeys(current.deliveryKeys, removedDeliveries),
|
|
808
884
|
tombstoneCount: tombstones,
|