@zlink-systems/framework 0.28.0 → 0.29.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/.tsbuildinfo +1 -1
- package/dist/contracts/Configuration/Builders.d.ts +2 -0
- package/dist/contracts/Configuration/InternalDefaults.d.ts +3 -0
- package/dist/contracts/Configuration/InternalDefaults.js +4 -1
- package/dist/contracts/Configuration/RegistrationBuilders.js +9 -0
- package/dist/contracts/Configuration/RegistrationNormalizers.d.ts +1 -0
- package/dist/contracts/Configuration/RegistrationNormalizers.js +16 -0
- package/dist/contracts/Configuration/RegistrationTypes.d.ts +3 -0
- package/dist/runtime/actors/actor-mailbox.d.ts +2 -2
- package/dist/runtime/actors/actor-mailbox.js +2 -2
- package/dist/runtime/actors/actor-runtime-contracts.d.ts +1 -0
- package/dist/runtime/actors/index.d.ts +2 -0
- package/dist/runtime/actors/index.js +21 -6
- package/dist/runtime/backend/node/node-raw-mesh-backend.js +1 -3
- package/dist/runtime/execution/serial-execution-queue.d.ts +12 -3
- package/dist/runtime/execution/serial-execution-queue.js +116 -28
- package/dist/runtime/foundation/operation-registry.d.ts +3 -2
- package/dist/runtime/foundation/operation-registry.js +5 -1
- package/dist/runtime/foundation/service-authority-payload-codec.d.ts +0 -2
- package/dist/runtime/foundation/service-authority-payload-codec.js +0 -43
- package/dist/runtime/foundation/service-stateful-registry.d.ts +4 -3
- package/dist/runtime/foundation/service-stateful-registry.js +5 -2
- package/dist/runtime/foundation/service-stateful-runtime.d.ts +1 -8
- package/dist/runtime/foundation/service-stateful-runtime.js +105 -145
- package/dist/runtime/foundation/service-stateful-wire-codec.d.ts +0 -11
- package/dist/runtime/foundation/service-stateful-wire-codec.js +1 -23
- package/dist/runtime/foundation/service-topology-registry.d.ts +5 -0
- package/dist/runtime/foundation/service-topology-registry.js +16 -17
- package/dist/runtime/handlers/handler-instance-scope.js +1 -1
- package/dist/runtime/host/actor-placement-coordinator.d.ts +2 -1
- package/dist/runtime/host/actor-placement-coordinator.js +2 -1
- package/dist/runtime/host/actor-runtime-options-factory.d.ts +2 -1
- package/dist/runtime/host/actor-runtime-options-factory.js +1 -0
- package/dist/runtime/host/index.d.ts +1 -1
- package/dist/runtime/host/index.js +3 -2
- package/dist/runtime/host/instance-activation-authority.d.ts +0 -1
- package/dist/runtime/host/instance-activation-authority.js +46 -97
- package/dist/runtime/host/spot-address-transport.js +1 -1
- package/dist/runtime/host/stateful-authority-route-runtime.d.ts +1 -0
- package/dist/runtime/host/stateful-authority-route-runtime.js +17 -9
- package/dist/runtime/locations/domain-store-contract.d.ts +3 -1
- package/dist/runtime/locations/in-memory-authority-store.d.ts +3 -0
- package/dist/runtime/locations/in-memory-authority-store.js +47 -12
- package/dist/runtime/locations/in-memory-location-store.d.ts +2 -1
- package/dist/runtime/locations/in-memory-location-store.js +15 -10
- package/dist/runtime/locations/internal-location-contracts.d.ts +5 -0
- package/dist/runtime/locations/internal-store-contracts.d.ts +1 -1
- package/dist/runtime/locations/location-store-repository.d.ts +2 -0
- package/dist/runtime/locations/location-store-repository.js +130 -54
- package/dist/runtime/spots/spot-entry-activation.d.ts +1 -0
- package/dist/runtime/spots/spot-entry-activation.js +3 -0
- package/dist/runtime/spots/spot-node-runtime-manager.d.ts +1 -0
- package/dist/runtime/spots/spot-node-runtime-manager.js +6 -0
- package/dist/runtime/spots/spot-serial-executor.d.ts +1 -0
- package/dist/runtime/spots/spot-serial-executor.js +14 -2
- package/dist/runtime/spots/spot-serial-turn-executor.d.ts +3 -0
- package/dist/runtime/spots/spot-serial-turn-executor.js +5 -0
- package/dist/runtime/streams/index.d.ts +0 -1
- package/dist/runtime/streams/index.js +4 -3
- package/dist/runtime/streams/protocol.js +0 -9
- package/dist/runtime/streams/session-context.d.ts +0 -4
- package/dist/runtime/streams/session-context.js +0 -26
- package/dist/runtime/streams/session-serial-executor.d.ts +0 -1
- package/dist/runtime/streams/session-serial-executor.js +0 -3
- package/dist/runtime/streams/stream-message-utils.d.ts +0 -1
- package/dist/runtime/streams/stream-message-utils.js +0 -20
- package/dist/runtime/streams/stream-session-runtime.d.ts +6 -3
- package/dist/runtime/streams/stream-session-runtime.js +40 -85
- package/package.json +3 -3
- package/src/contracts/Configuration/Builders.ts +2 -0
- package/src/contracts/Configuration/InternalDefaults.ts +4 -0
- package/src/contracts/Configuration/RegistrationBuilders.ts +13 -0
- package/src/contracts/Configuration/RegistrationNormalizers.ts +25 -0
- package/src/contracts/Configuration/RegistrationTypes.ts +3 -0
- package/src/runtime/actors/actor-mailbox.ts +7 -2
- package/src/runtime/actors/actor-runtime-contracts.ts +4 -0
- package/src/runtime/actors/index.ts +77 -42
- package/src/runtime/backend/node/node-raw-mesh-backend.ts +1 -7
- package/src/runtime/execution/serial-execution-queue.ts +117 -29
- package/src/runtime/foundation/operation-registry.ts +16 -9
- package/src/runtime/foundation/service-authority-payload-codec.ts +0 -46
- package/src/runtime/foundation/service-stateful-registry.ts +10 -5
- package/src/runtime/foundation/service-stateful-runtime.ts +152 -224
- package/src/runtime/foundation/service-stateful-wire-codec.ts +0 -25
- package/src/runtime/foundation/service-topology-registry.ts +30 -20
- package/src/runtime/handlers/handler-instance-scope.ts +2 -1
- package/src/runtime/host/actor-placement-coordinator.ts +8 -2
- package/src/runtime/host/actor-runtime-options-factory.ts +6 -0
- package/src/runtime/host/index.ts +6 -2
- package/src/runtime/host/instance-activation-authority.ts +58 -125
- package/src/runtime/host/spot-address-transport.ts +1 -1
- package/src/runtime/host/stateful-authority-route-runtime.ts +22 -9
- package/src/runtime/locations/domain-store-contract.ts +6 -1
- package/src/runtime/locations/in-memory-authority-store.ts +83 -12
- package/src/runtime/locations/in-memory-location-store.ts +22 -10
- package/src/runtime/locations/internal-location-contracts.ts +6 -0
- package/src/runtime/locations/internal-store-contracts.ts +1 -0
- package/src/runtime/locations/location-store-repository.ts +182 -69
- package/src/runtime/protocol/service_wire_pilot_codec.generated.ts +1 -1
- package/src/runtime/spots/spot-entry-activation.ts +4 -0
- package/src/runtime/spots/spot-node-runtime-manager.ts +7 -0
- package/src/runtime/spots/spot-serial-executor.ts +14 -5
- package/src/runtime/spots/spot-serial-turn-executor.ts +10 -0
- package/src/runtime/streams/index.ts +3 -1
- package/src/runtime/streams/protocol.ts +0 -13
- package/src/runtime/streams/session-context.ts +0 -32
- package/src/runtime/streams/session-serial-executor.ts +0 -8
- package/src/runtime/streams/stream-message-utils.ts +1 -27
- package/src/runtime/streams/stream-session-runtime.ts +54 -97
- package/dist/runtime/streams/session-requests.d.ts +0 -25
- package/dist/runtime/streams/session-requests.js +0 -101
- package/src/runtime/streams/session-requests.ts +0 -110
|
@@ -7,6 +7,7 @@ import { UINT64_MAX } from '@zlink-systems/stream-wire';
|
|
|
7
7
|
import { ZLINK_MAX_ROUTING_ID_BYTES } from '../../contracts/Common/CoreTypes';
|
|
8
8
|
import { ZLINK_PROVIDER_MAX_PAGE_SIZE } from '../../contracts/Locations/Stores';
|
|
9
9
|
import { randomUUID } from 'node:crypto';
|
|
10
|
+
import { ZLinkFrameworkException, ZLinkFrameworkErrorKind } from '../../contracts';
|
|
10
11
|
import { SHA256_DIGEST_BYTES } from '../foundation/actor-join-recovery-codec';
|
|
11
12
|
import type {
|
|
12
13
|
ZLinkAggregateAbortResult,
|
|
@@ -41,13 +42,16 @@ import type {
|
|
|
41
42
|
} from './internal-location-contracts';
|
|
42
43
|
import { encodeAuthorityKey } from './authority-key-codec';
|
|
43
44
|
import { creationTerminalPreimage } from './opaque-record-key';
|
|
45
|
+
import { ServiceRelocationAuthorityPayloadCodec } from '../foundation/service-relocation-runtime';
|
|
44
46
|
|
|
45
47
|
const MAX_GENERATION = 0x7fff_ffff_ffff_ffffn;
|
|
46
48
|
|
|
47
49
|
const CREATION_TERMINAL_RETENTION_MS = 5 * 60 * 1000;
|
|
48
50
|
const MAX_U64 = UINT64_MAX;
|
|
51
|
+
const relocationAuthorityCodec = new ServiceRelocationAuthorityPayloadCodec();
|
|
49
52
|
|
|
50
53
|
export interface ZLinkInMemoryAuthorityValidation {
|
|
54
|
+
isOwnerLive(owner: ZLinkLocationOwnerToken): boolean;
|
|
51
55
|
isTargetLive(
|
|
52
56
|
descriptor: ZLinkMeshNodeDescriptorKey,
|
|
53
57
|
lifecycleGeneration: bigint,
|
|
@@ -276,6 +280,75 @@ export class ZLinkInMemoryAuthorityStore {
|
|
|
276
280
|
return BigInt(removed);
|
|
277
281
|
}
|
|
278
282
|
|
|
283
|
+
async releaseEndedReservation(
|
|
284
|
+
key: ZLinkAuthorityKey,
|
|
285
|
+
expectedStoreVersion: string,
|
|
286
|
+
signal?: AbortSignal
|
|
287
|
+
): Promise<boolean> {
|
|
288
|
+
signal?.throwIfAborted();
|
|
289
|
+
return this.tryReleaseEndedReservation(key, expectedStoreVersion);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
private tryReleaseEndedReservation(
|
|
293
|
+
key: ZLinkAuthorityKey,
|
|
294
|
+
expectedStoreVersion: string,
|
|
295
|
+
request?: ZLinkObjectReserveRequest
|
|
296
|
+
): boolean {
|
|
297
|
+
const current = this.rows.get(key.value);
|
|
298
|
+
if (
|
|
299
|
+
current === undefined ||
|
|
300
|
+
current.snapshot.storeVersion.value !== expectedStoreVersion ||
|
|
301
|
+
(current.snapshot.allocation.state === 'active'
|
|
302
|
+
? request?.key.kind !== 'actor'
|
|
303
|
+
: current.creation === undefined)
|
|
304
|
+
)
|
|
305
|
+
return false;
|
|
306
|
+
if (current.snapshot.allocation.state === 'active') {
|
|
307
|
+
for (const aggregate of this.aggregates.values()) {
|
|
308
|
+
if (
|
|
309
|
+
aggregate.state === 'prepared' &&
|
|
310
|
+
aggregate.request.participants.some(
|
|
311
|
+
(participant) => participant.authorityKey.value === key.value
|
|
312
|
+
)
|
|
313
|
+
)
|
|
314
|
+
return false;
|
|
315
|
+
}
|
|
316
|
+
if (relocationAuthorityCodec.read(current.snapshot.payload) !== undefined) return false;
|
|
317
|
+
if (
|
|
318
|
+
this.validation.isOwnerLive({
|
|
319
|
+
ownerId: current.snapshot.ownerId,
|
|
320
|
+
leaseGeneration: current.snapshot.ownerLeaseGeneration
|
|
321
|
+
})
|
|
322
|
+
)
|
|
323
|
+
return false;
|
|
324
|
+
if (request?.actorRelocationPolicy !== 'disabled')
|
|
325
|
+
throw new ZLinkFrameworkException(
|
|
326
|
+
ZLinkFrameworkErrorKind.Unavailable,
|
|
327
|
+
'Actor owner lease is unavailable.'
|
|
328
|
+
);
|
|
329
|
+
} else if (
|
|
330
|
+
this.validation.isTargetLive(
|
|
331
|
+
current.snapshot.allocation.descriptor,
|
|
332
|
+
current.snapshot.allocation.descriptorLifecycleGeneration,
|
|
333
|
+
{
|
|
334
|
+
ownerId: current.snapshot.ownerId,
|
|
335
|
+
leaseGeneration: current.snapshot.ownerLeaseGeneration
|
|
336
|
+
}
|
|
337
|
+
)
|
|
338
|
+
)
|
|
339
|
+
return false;
|
|
340
|
+
this.adjustCapacity(
|
|
341
|
+
current.snapshot.allocation.state === 'active' ? this.activeCapacity : this.pendingCapacity,
|
|
342
|
+
current.snapshot.allocation,
|
|
343
|
+
-1
|
|
344
|
+
);
|
|
345
|
+
this.rows.delete(key.value);
|
|
346
|
+
if (current.snapshot.allocation.state === 'reserved' && current.creation !== undefined)
|
|
347
|
+
this.creationTerminals.set(current.creation.reservationId, 'aborted');
|
|
348
|
+
this.scanRevision++;
|
|
349
|
+
return true;
|
|
350
|
+
}
|
|
351
|
+
|
|
279
352
|
async reserve(
|
|
280
353
|
request: ZLinkObjectReserveRequest,
|
|
281
354
|
signal?: AbortSignal
|
|
@@ -294,18 +367,16 @@ export class ZLinkInMemoryAuthorityStore {
|
|
|
294
367
|
) {
|
|
295
368
|
return { kind: 'typeMismatch', current: this.snapshot(current.snapshot) };
|
|
296
369
|
}
|
|
297
|
-
if (
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
this.creationTerminals.set(current.creation.reservationId, 'aborted');
|
|
308
|
-
this.scanRevision++;
|
|
370
|
+
if (
|
|
371
|
+
!this.tryReleaseEndedReservation(
|
|
372
|
+
encodeAuthorityKey(request.key.kind, request.key.globalId),
|
|
373
|
+
current.snapshot.storeVersion.value,
|
|
374
|
+
request
|
|
375
|
+
)
|
|
376
|
+
)
|
|
377
|
+
return current.snapshot.allocation.state === 'active'
|
|
378
|
+
? { kind: 'alreadyExists', current: this.snapshot(current.snapshot) }
|
|
379
|
+
: { kind: 'conflict', current: this.read(key) };
|
|
309
380
|
}
|
|
310
381
|
const target = creationTarget(request);
|
|
311
382
|
if (
|
|
@@ -99,11 +99,14 @@ export class ZLinkInMemoryLocationStore
|
|
|
99
99
|
private readonly authority: ZLinkInMemoryAuthorityStore;
|
|
100
100
|
|
|
101
101
|
constructor(private readonly now: () => Date = () => new Date()) {
|
|
102
|
+
const isOwnerLive = (owner: ZLinkLocationOwnerToken): boolean =>
|
|
103
|
+
this.liveOwnerLease(owner.ownerId, this.now())?.token.leaseGeneration ===
|
|
104
|
+
owner.leaseGeneration;
|
|
102
105
|
this.authority = new ZLinkInMemoryAuthorityStore(
|
|
103
106
|
{
|
|
107
|
+
isOwnerLive,
|
|
104
108
|
isTargetLive: (key, lifecycleGeneration, owner) => {
|
|
105
109
|
const descriptor = this.meshNodes.rows.get(meshNodeKey(key.meshName, key.rid));
|
|
106
|
-
const lease = this.leases.get(owner.ownerId);
|
|
107
110
|
return (
|
|
108
111
|
descriptor !== undefined &&
|
|
109
112
|
descriptor.lifecycleGeneration === lifecycleGeneration &&
|
|
@@ -111,9 +114,7 @@ export class ZLinkInMemoryLocationStore
|
|
|
111
114
|
descriptor.leaseGeneration === owner.leaseGeneration &&
|
|
112
115
|
descriptor.objectRole === ZLinkObjectRole.Server &&
|
|
113
116
|
descriptor.state === ZLinkFrameworkRuntimeState.Serving &&
|
|
114
|
-
|
|
115
|
-
lease.token.leaseGeneration === owner.leaseGeneration &&
|
|
116
|
-
lease.leaseExpiresAt.getTime() > this.now().getTime()
|
|
117
|
+
isOwnerLive(owner)
|
|
117
118
|
);
|
|
118
119
|
},
|
|
119
120
|
placementCapacityAvailable: (key, requested, reserved, active) => {
|
|
@@ -201,6 +202,14 @@ export class ZLinkInMemoryLocationStore
|
|
|
201
202
|
return this.authority.readCreationTerminal(operation, signal);
|
|
202
203
|
}
|
|
203
204
|
|
|
205
|
+
async releaseEndedReservation(
|
|
206
|
+
key: ZLinkAuthorityKey,
|
|
207
|
+
expectedStoreVersion: string,
|
|
208
|
+
signal?: AbortSignal
|
|
209
|
+
): Promise<boolean> {
|
|
210
|
+
return this.authority.releaseEndedReservation(key, expectedStoreVersion, signal);
|
|
211
|
+
}
|
|
212
|
+
|
|
204
213
|
async abort(
|
|
205
214
|
request: ZLinkObjectAbortRequest,
|
|
206
215
|
signal?: AbortSignal
|
|
@@ -558,7 +567,8 @@ export class ZLinkInMemoryLocationStore
|
|
|
558
567
|
const storeNow = this.now();
|
|
559
568
|
return pageRows(
|
|
560
569
|
this.fanoutPublishers,
|
|
561
|
-
(row) =>
|
|
570
|
+
(row) =>
|
|
571
|
+
row.channelName === channelName && this.liveOwnerLease(row.ownerId, storeNow) !== undefined,
|
|
562
572
|
page
|
|
563
573
|
);
|
|
564
574
|
}
|
|
@@ -620,7 +630,7 @@ export class ZLinkInMemoryLocationStore
|
|
|
620
630
|
if (
|
|
621
631
|
intent === ZLinkLocationWriteIntent.NewClaim &&
|
|
622
632
|
current !== undefined &&
|
|
623
|
-
this.
|
|
633
|
+
this.liveOwnerLease(current.ownerId, updatedAt) !== undefined
|
|
624
634
|
) {
|
|
625
635
|
return rejectedConflict();
|
|
626
636
|
}
|
|
@@ -698,7 +708,7 @@ export class ZLinkInMemoryLocationStore
|
|
|
698
708
|
if (
|
|
699
709
|
intent === ZLinkLocationWriteIntent.NewClaim &&
|
|
700
710
|
current !== undefined &&
|
|
701
|
-
this.
|
|
711
|
+
this.liveOwnerLease(current.ownerId, updatedAt) !== undefined
|
|
702
712
|
) {
|
|
703
713
|
return rejectedConflict();
|
|
704
714
|
}
|
|
@@ -1147,7 +1157,7 @@ export class ZLinkInMemoryLocationStore
|
|
|
1147
1157
|
if (
|
|
1148
1158
|
intent === ZLinkLocationWriteIntent.NewClaim &&
|
|
1149
1159
|
current !== undefined &&
|
|
1150
|
-
this.
|
|
1160
|
+
this.liveOwnerLease(ownerOf(current), updatedAt) !== undefined
|
|
1151
1161
|
) {
|
|
1152
1162
|
return rejectedConflict();
|
|
1153
1163
|
}
|
|
@@ -1244,9 +1254,11 @@ export class ZLinkInMemoryLocationStore
|
|
|
1244
1254
|
return removed;
|
|
1245
1255
|
}
|
|
1246
1256
|
|
|
1247
|
-
private
|
|
1257
|
+
private liveOwnerLease(ownerId: string, now: Date): InMemoryOwnerLease | undefined {
|
|
1248
1258
|
const lease = this.leases.get(ownerId);
|
|
1249
|
-
return lease !== undefined && lease.leaseExpiresAt.getTime() > now.getTime()
|
|
1259
|
+
return lease !== undefined && lease.leaseExpiresAt.getTime() > now.getTime()
|
|
1260
|
+
? lease
|
|
1261
|
+
: undefined;
|
|
1250
1262
|
}
|
|
1251
1263
|
|
|
1252
1264
|
private bump(kind: ZLinkLocationKind, meshName: string | undefined): void {
|
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
export * from '../../contracts/Locations';
|
|
2
|
+
import type { ZLinkObjectReserveRequest as ReserveRequest } from '../../contracts/Locations/Authority';
|
|
3
|
+
import type { ZLinkRelocationConfiguration } from '../../contracts/Configuration/RegistrationTypes';
|
|
4
|
+
|
|
5
|
+
export interface ZLinkObjectReserveRequest extends ReserveRequest {
|
|
6
|
+
readonly actorRelocationPolicy?: ZLinkRelocationConfiguration<unknown>['kind'];
|
|
7
|
+
}
|
|
2
8
|
export type * from '../../contracts/Locations/Authority';
|
|
3
9
|
export type {
|
|
4
10
|
ZLinkActorLocation,
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ServiceRelocationAuthorityPayloadCodec } from '../foundation/service-relocation-runtime';
|
|
1
2
|
import { UINT64_MAX } from '@zlink-systems/stream-wire';
|
|
2
3
|
import { createHash, randomUUID } from 'node:crypto';
|
|
3
4
|
import { zlinkRuntimeDefaultLocationOptions } from '../../contracts/Locations/Options';
|
|
@@ -17,6 +18,8 @@ import {
|
|
|
17
18
|
type ZLinkStoreScanCursor,
|
|
18
19
|
type ZLinkStoreVersion,
|
|
19
20
|
type ZLinkStoreWriteRequest,
|
|
21
|
+
ZLinkFrameworkException,
|
|
22
|
+
ZLinkFrameworkErrorKind,
|
|
20
23
|
ZLinkFrameworkRuntimeState,
|
|
21
24
|
ZLinkObjectRole
|
|
22
25
|
} from '../../contracts';
|
|
@@ -204,7 +207,30 @@ export class ZLinkLocationStoreRepository extends ZLinkInMemoryLocationStore {
|
|
|
204
207
|
private readonly nowProvider: () => Date = () => new Date()
|
|
205
208
|
) {
|
|
206
209
|
super(nowProvider);
|
|
207
|
-
|
|
210
|
+
// Classify only failures of the opaque SPI, before interpreting its records.
|
|
211
|
+
this.provider = {
|
|
212
|
+
async read(key, signal) {
|
|
213
|
+
try {
|
|
214
|
+
return await provider.read(key, signal);
|
|
215
|
+
} catch (error) {
|
|
216
|
+
throw locationStoreProviderFailure(error, signal);
|
|
217
|
+
}
|
|
218
|
+
},
|
|
219
|
+
async write(request, signal) {
|
|
220
|
+
try {
|
|
221
|
+
return await provider.write(request, signal);
|
|
222
|
+
} catch (error) {
|
|
223
|
+
throw locationStoreProviderFailure(error, signal);
|
|
224
|
+
}
|
|
225
|
+
},
|
|
226
|
+
async scan(request, signal) {
|
|
227
|
+
try {
|
|
228
|
+
return await provider.scan(request, signal);
|
|
229
|
+
} catch (error) {
|
|
230
|
+
throw locationStoreProviderFailure(error, signal);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
};
|
|
208
234
|
this.aggregateInventory = new ZLinkAggregateInventoryStore(this.provider);
|
|
209
235
|
}
|
|
210
236
|
|
|
@@ -1099,6 +1125,118 @@ export class ZLinkLocationStoreRepository extends ZLinkInMemoryLocationStore {
|
|
|
1099
1125
|
}
|
|
1100
1126
|
}
|
|
1101
1127
|
|
|
1128
|
+
override async releaseEndedReservation(
|
|
1129
|
+
key: ZLinkAuthorityKey,
|
|
1130
|
+
expectedStoreVersion: string,
|
|
1131
|
+
signal?: AbortSignal
|
|
1132
|
+
): Promise<boolean> {
|
|
1133
|
+
return (
|
|
1134
|
+
(await this.tryReleaseEndedReservation(key, expectedStoreVersion, signal)) === 'reclaimed'
|
|
1135
|
+
);
|
|
1136
|
+
}
|
|
1137
|
+
|
|
1138
|
+
private async tryReleaseEndedReservation(
|
|
1139
|
+
key: ZLinkAuthorityKey,
|
|
1140
|
+
expectedStoreVersion: string,
|
|
1141
|
+
signal?: AbortSignal,
|
|
1142
|
+
request?: ZLinkObjectReserveRequest
|
|
1143
|
+
): Promise<'notReclaimable' | 'conflict' | 'reclaimed'> {
|
|
1144
|
+
const rowKey = authorityKey(key.value);
|
|
1145
|
+
const current = await this.provider.read(rowKey, signal);
|
|
1146
|
+
if (current.kind === 'missing' || current.value.version.value !== expectedStoreVersion)
|
|
1147
|
+
return 'conflict';
|
|
1148
|
+
const record = decodeAuthorityRecord(current.value.bytes);
|
|
1149
|
+
const snapshot = record.snapshot;
|
|
1150
|
+
if (
|
|
1151
|
+
(snapshot.allocation.state === 'active'
|
|
1152
|
+
? request?.key.kind !== 'actor'
|
|
1153
|
+
: snapshot.pendingCreation === undefined) ||
|
|
1154
|
+
record.aggregate !== undefined ||
|
|
1155
|
+
hasRelocationAuthority(snapshot.payload)
|
|
1156
|
+
)
|
|
1157
|
+
return 'notReclaimable';
|
|
1158
|
+
const leaseKey = ownerKey(snapshot.ownerId);
|
|
1159
|
+
const descriptorKey = meshKey(
|
|
1160
|
+
snapshot.allocation.descriptor.meshName,
|
|
1161
|
+
snapshot.allocation.descriptor.rid
|
|
1162
|
+
);
|
|
1163
|
+
const capacityRowKey = capacityKey(
|
|
1164
|
+
snapshot.allocation.descriptor.meshName,
|
|
1165
|
+
String(snapshot.allocation.descriptor.rid)
|
|
1166
|
+
);
|
|
1167
|
+
const [lease, descriptor, capacity] = await Promise.all([
|
|
1168
|
+
this.provider.read(leaseKey, signal),
|
|
1169
|
+
this.provider.read(descriptorKey, signal),
|
|
1170
|
+
this.provider.read(capacityRowKey, signal)
|
|
1171
|
+
]);
|
|
1172
|
+
if (lease.kind === 'found' && lease.value.expiresAt === undefined)
|
|
1173
|
+
throw new Error('Location Store owner lease record is invalid.');
|
|
1174
|
+
const ownerLive = sameLiveOwner(lease, snapshot);
|
|
1175
|
+
if (snapshot.allocation.state === 'active') {
|
|
1176
|
+
if (ownerLive) return 'notReclaimable';
|
|
1177
|
+
if (request?.actorRelocationPolicy !== 'disabled')
|
|
1178
|
+
throw new ZLinkFrameworkException(
|
|
1179
|
+
ZLinkFrameworkErrorKind.Unavailable,
|
|
1180
|
+
'Actor owner lease is unavailable.'
|
|
1181
|
+
);
|
|
1182
|
+
} else if (
|
|
1183
|
+
ownerLive &&
|
|
1184
|
+
descriptor.kind === 'found' &&
|
|
1185
|
+
reviveMeshDescriptor(
|
|
1186
|
+
decodeCanonicalDescriptorRecord<ZLinkMeshNodeDescriptor>(descriptor.value.bytes).descriptor
|
|
1187
|
+
).lifecycleGeneration === snapshot.allocation.descriptorLifecycleGeneration
|
|
1188
|
+
)
|
|
1189
|
+
return 'notReclaimable';
|
|
1190
|
+
const mutations: ZLinkStoreWriteRequest['mutations'][number][] = [
|
|
1191
|
+
{ kind: 'delete', key: rowKey }
|
|
1192
|
+
];
|
|
1193
|
+
if (capacity.kind === 'found') {
|
|
1194
|
+
const stored = decodeJson<CapacityRecord>(capacity.value.bytes);
|
|
1195
|
+
try {
|
|
1196
|
+
mutations.push({
|
|
1197
|
+
kind: 'put',
|
|
1198
|
+
key: capacityRowKey,
|
|
1199
|
+
bytes: encodeJson({
|
|
1200
|
+
active:
|
|
1201
|
+
snapshot.allocation.state === 'active'
|
|
1202
|
+
? subtractCapacity(stored.active, snapshot.allocation.capacity)
|
|
1203
|
+
: stored.active,
|
|
1204
|
+
pending:
|
|
1205
|
+
snapshot.allocation.state === 'reserved'
|
|
1206
|
+
? subtractCapacity(stored.pending, snapshot.allocation.capacity)
|
|
1207
|
+
: stored.pending
|
|
1208
|
+
} satisfies CapacityRecord)
|
|
1209
|
+
});
|
|
1210
|
+
} catch (error) {
|
|
1211
|
+
if (
|
|
1212
|
+
!(error instanceof ZLinkFrameworkException) ||
|
|
1213
|
+
error.kind !== ZLinkFrameworkErrorKind.DataLost
|
|
1214
|
+
)
|
|
1215
|
+
throw error;
|
|
1216
|
+
const observed = await this.provider.read(rowKey, signal);
|
|
1217
|
+
if (
|
|
1218
|
+
observed.kind === 'missing' ||
|
|
1219
|
+
observed.value.version.value !== current.value.version.value
|
|
1220
|
+
)
|
|
1221
|
+
return 'conflict';
|
|
1222
|
+
throw error;
|
|
1223
|
+
}
|
|
1224
|
+
}
|
|
1225
|
+
const result = await this.provider.write(
|
|
1226
|
+
{
|
|
1227
|
+
conditions: [
|
|
1228
|
+
{ kind: 'version', key: rowKey, expected: current.value.version },
|
|
1229
|
+
conditionFor(leaseKey, lease),
|
|
1230
|
+
conditionFor(descriptorKey, descriptor),
|
|
1231
|
+
conditionFor(capacityRowKey, capacity)
|
|
1232
|
+
],
|
|
1233
|
+
mutations
|
|
1234
|
+
},
|
|
1235
|
+
signal
|
|
1236
|
+
);
|
|
1237
|
+
return result.kind === 'applied' ? 'reclaimed' : 'conflict';
|
|
1238
|
+
}
|
|
1239
|
+
|
|
1102
1240
|
override async reserve(
|
|
1103
1241
|
request: ZLinkObjectReserveRequest,
|
|
1104
1242
|
signal?: AbortSignal,
|
|
@@ -1106,6 +1244,7 @@ export class ZLinkLocationStoreRepository extends ZLinkInMemoryLocationStore {
|
|
|
1106
1244
|
): Promise<ZLinkObjectReserveResult> {
|
|
1107
1245
|
const encodedAuthorityKey = encodeAuthorityKey(request.key.kind, request.key.globalId);
|
|
1108
1246
|
const reservationId = randomUUID();
|
|
1247
|
+
let reclaimVersion: string | undefined;
|
|
1109
1248
|
for (;;) {
|
|
1110
1249
|
throwIfOperationExpired(signal, deadlineUnixMs);
|
|
1111
1250
|
const rowKey = authorityKey(encodedAuthorityKey.value);
|
|
@@ -1126,68 +1265,23 @@ export class ZLinkLocationStoreRepository extends ZLinkInMemoryLocationStore {
|
|
|
1126
1265
|
) {
|
|
1127
1266
|
return { kind: 'typeMismatch', current: snapshot };
|
|
1128
1267
|
}
|
|
1129
|
-
if (snapshot.
|
|
1130
|
-
return { kind: 'alreadyExists', current: snapshot };
|
|
1131
|
-
}
|
|
1132
|
-
if (
|
|
1133
|
-
record.aggregate !== undefined ||
|
|
1134
|
-
isCanonicalAuthorityPayload(record.snapshot.payload)
|
|
1135
|
-
) {
|
|
1136
|
-
// A relocation record carries its own recovery protocol. Reserve
|
|
1137
|
-
// may reclaim only an unfinished plain creation.
|
|
1268
|
+
if (reclaimVersion !== undefined && snapshot.storeVersion.value !== reclaimVersion)
|
|
1138
1269
|
return { kind: 'conflict', current: snapshot };
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
const staleCapacityKey = capacityKey(
|
|
1145
|
-
snapshot.allocation.descriptor.meshName,
|
|
1146
|
-
String(snapshot.allocation.descriptor.rid)
|
|
1147
|
-
);
|
|
1148
|
-
const [staleOwnerRead, staleCapacityRead] = await Promise.all([
|
|
1149
|
-
this.provider.read(staleOwnerKey, signal),
|
|
1150
|
-
this.provider.read(staleCapacityKey, signal)
|
|
1151
|
-
]);
|
|
1152
|
-
if (staleOwnerRead.kind === 'found' && staleOwnerRead.value.expiresAt === undefined) {
|
|
1153
|
-
// A lease is always written with a positive TTL, so a missing
|
|
1154
|
-
// expiry is a corrupt record. Reclaiming deletes authority state,
|
|
1155
|
-
// so refuse rather than read the absence as expiry.
|
|
1156
|
-
throw new Error('Location Store owner lease record is invalid.');
|
|
1157
|
-
}
|
|
1158
|
-
if (sameLiveOwner(staleOwnerRead, record.snapshot)) {
|
|
1159
|
-
return { kind: 'conflict', current: snapshot };
|
|
1160
|
-
}
|
|
1161
|
-
const staleCapacity =
|
|
1162
|
-
staleCapacityRead.kind === 'missing'
|
|
1163
|
-
? emptyCapacityRecord()
|
|
1164
|
-
: decodeJson<CapacityRecord>(staleCapacityRead.value.bytes);
|
|
1165
|
-
await this.provider.write(
|
|
1166
|
-
{
|
|
1167
|
-
conditions: [
|
|
1168
|
-
{ kind: 'version', key: rowKey, expected: current.value.version },
|
|
1169
|
-
versionCondition(staleOwnerKey, staleOwnerRead),
|
|
1170
|
-
conditionFor(staleCapacityKey, staleCapacityRead)
|
|
1171
|
-
],
|
|
1172
|
-
mutations: [
|
|
1173
|
-
{ kind: 'delete', key: rowKey },
|
|
1174
|
-
{
|
|
1175
|
-
kind: 'put',
|
|
1176
|
-
key: staleCapacityKey,
|
|
1177
|
-
bytes: encodeJson({
|
|
1178
|
-
active: staleCapacity.active,
|
|
1179
|
-
pending: subtractCapacity(
|
|
1180
|
-
staleCapacity.pending,
|
|
1181
|
-
record.snapshot.allocation.capacity
|
|
1182
|
-
)
|
|
1183
|
-
} satisfies CapacityRecord)
|
|
1184
|
-
}
|
|
1185
|
-
]
|
|
1186
|
-
},
|
|
1187
|
-
signal
|
|
1270
|
+
const reclaim = await this.tryReleaseEndedReservation(
|
|
1271
|
+
encodedAuthorityKey,
|
|
1272
|
+
current.value.version.value,
|
|
1273
|
+
signal,
|
|
1274
|
+
request
|
|
1188
1275
|
);
|
|
1276
|
+
if (reclaim === 'notReclaimable')
|
|
1277
|
+
return snapshot.allocation.state === 'active'
|
|
1278
|
+
? { kind: 'alreadyExists', current: snapshot }
|
|
1279
|
+
: { kind: 'conflict', current: snapshot };
|
|
1280
|
+
reclaimVersion = reclaim === 'conflict' ? snapshot.storeVersion.value : undefined;
|
|
1189
1281
|
continue;
|
|
1190
1282
|
}
|
|
1283
|
+
if (reclaimVersion !== undefined)
|
|
1284
|
+
return { kind: 'conflict', current: { kind: 'missing', storeNow: current.storeNow } };
|
|
1191
1285
|
const [descriptorRead, leaseRead] = await Promise.all([
|
|
1192
1286
|
this.provider.read(descriptorKey, signal),
|
|
1193
1287
|
this.provider.read(leaseKey, signal)
|
|
@@ -3992,13 +4086,21 @@ function adjustCapacity(
|
|
|
3992
4086
|
if (delta.spotType !== undefined) {
|
|
3993
4087
|
const key = capacityTypeKey(delta.spotType);
|
|
3994
4088
|
const next = (spotTypes[key] ?? 0) + direction * delta.spotType.count;
|
|
3995
|
-
if (next < 0)
|
|
4089
|
+
if (next < 0)
|
|
4090
|
+
throw new ZLinkFrameworkException(
|
|
4091
|
+
ZLinkFrameworkErrorKind.DataLost,
|
|
4092
|
+
'Provider capacity counter underflow.'
|
|
4093
|
+
);
|
|
3996
4094
|
if (next === 0) delete spotTypes[key];
|
|
3997
4095
|
else spotTypes[key] = next;
|
|
3998
4096
|
}
|
|
3999
4097
|
const actors = usage.actors + direction * delta.actors;
|
|
4000
4098
|
const spots = usage.spots + direction * delta.spots;
|
|
4001
|
-
if (actors < 0 || spots < 0)
|
|
4099
|
+
if (actors < 0 || spots < 0)
|
|
4100
|
+
throw new ZLinkFrameworkException(
|
|
4101
|
+
ZLinkFrameworkErrorKind.DataLost,
|
|
4102
|
+
'Provider capacity counter underflow.'
|
|
4103
|
+
);
|
|
4002
4104
|
return { actors, spots, spotTypes };
|
|
4003
4105
|
}
|
|
4004
4106
|
|
|
@@ -4037,15 +4139,10 @@ function sameCreationTarget(
|
|
|
4037
4139
|
);
|
|
4038
4140
|
}
|
|
4039
4141
|
|
|
4040
|
-
const
|
|
4142
|
+
const relocationAuthorityCodec = new ServiceRelocationAuthorityPayloadCodec();
|
|
4041
4143
|
|
|
4042
|
-
function
|
|
4043
|
-
return (
|
|
4044
|
-
payload.byteLength >= CANONICAL_AUTHORITY_MAGIC.byteLength &&
|
|
4045
|
-
Buffer.from(payload.buffer, payload.byteOffset, CANONICAL_AUTHORITY_MAGIC.byteLength).equals(
|
|
4046
|
-
CANONICAL_AUTHORITY_MAGIC
|
|
4047
|
-
)
|
|
4048
|
-
);
|
|
4144
|
+
function hasRelocationAuthority(payload: Uint8Array): boolean {
|
|
4145
|
+
return relocationAuthorityCodec.read(payload) !== undefined;
|
|
4049
4146
|
}
|
|
4050
4147
|
|
|
4051
4148
|
function sameLiveOwner(lease: ZLinkStoreReadResult, snapshot: StoredAuthoritySnapshot): boolean {
|
|
@@ -4441,3 +4538,19 @@ function throwIfOperationExpired(signal?: AbortSignal, deadlineUnixMs?: bigint):
|
|
|
4441
4538
|
throw new DOMException('Operation deadline exceeded.', 'TimeoutError');
|
|
4442
4539
|
}
|
|
4443
4540
|
}
|
|
4541
|
+
|
|
4542
|
+
// Store SPI §6: preserve caller failures and classify provider failures once.
|
|
4543
|
+
function locationStoreProviderFailure(error: unknown, signal?: AbortSignal): unknown {
|
|
4544
|
+
if (
|
|
4545
|
+
error instanceof ZLinkFrameworkException ||
|
|
4546
|
+
error instanceof TypeError ||
|
|
4547
|
+
error instanceof RangeError ||
|
|
4548
|
+
signal?.aborted === true
|
|
4549
|
+
)
|
|
4550
|
+
return error;
|
|
4551
|
+
return new ZLinkFrameworkException(
|
|
4552
|
+
ZLinkFrameworkErrorKind.Unavailable,
|
|
4553
|
+
'Location Store provider is unavailable.',
|
|
4554
|
+
error
|
|
4555
|
+
);
|
|
4556
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// <auto-generated> DO NOT EDIT. schema-sha256:
|
|
1
|
+
// <auto-generated> DO NOT EDIT. schema-sha256: 818fcd2f767793be8b5f626e5ac688807e671e546af2b11786e6fbaa02010ba5
|
|
2
2
|
export interface ServiceWireRouteFence { readonly id: string; readonly generation: bigint; readonly targetNodeRid: Uint8Array; readonly targetNodeGeneration: bigint; readonly expectedAuthorityOwnerGeneration: bigint; readonly expectedOwnerLeaseGeneration: bigint; }
|
|
3
3
|
export interface ApplicationPayloadEnvelopeV1 { readonly packetName: string; readonly contentType: string; readonly payload: Uint8Array; }
|
|
4
4
|
export interface ActorJoin28 { readonly correlation: bigint; readonly actor: ServiceWireRouteFence; readonly entry: boolean; readonly targetSpot: ServiceWireRouteFence; readonly payload?: ApplicationPayloadEnvelopeV1; }
|
|
@@ -378,6 +378,10 @@ export class ZLinkEntrySpotActivation {
|
|
|
378
378
|
return this.spotSerialExecutor.executeActor(actorId, operation);
|
|
379
379
|
}
|
|
380
380
|
|
|
381
|
+
terminateActor(actorId: string, terminal: () => Promise<void>): Promise<void> {
|
|
382
|
+
return this.spotSerialExecutor.terminateActor(actorId, terminal);
|
|
383
|
+
}
|
|
384
|
+
|
|
381
385
|
/**
|
|
382
386
|
* Entry Spot membership does not have an application admission callback.
|
|
383
387
|
* The shared core round-trip therefore accepts a valid returning Actor and
|
|
@@ -783,6 +783,13 @@ export class ZLinkSpotNodeRuntimeManager {
|
|
|
783
783
|
return activation?.notifyJoinActor(actor, signal) ?? Promise.resolve();
|
|
784
784
|
}
|
|
785
785
|
|
|
786
|
+
terminateActorActivation(actor: ZLinkActor, terminal: () => Promise<void>): Promise<void> {
|
|
787
|
+
const activation = this.entryActivations.get(actor.context.meshName);
|
|
788
|
+
return activation === undefined
|
|
789
|
+
? terminal()
|
|
790
|
+
: activation.terminateActor(actor.context.actorId, terminal);
|
|
791
|
+
}
|
|
792
|
+
|
|
786
793
|
notifyPrimaryEntrySpotActorLeft(
|
|
787
794
|
actor: ZLinkActor,
|
|
788
795
|
signal?: AbortSignal,
|
|
@@ -51,10 +51,8 @@ export class ZLinkSpotSerialExecutor {
|
|
|
51
51
|
operation: (serial: ZLinkSpotSerialTurnExecutor) => Promise<T> | T,
|
|
52
52
|
workOptions?: ZLinkSerialWorkOptions
|
|
53
53
|
): Promise<T> {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
workOptions
|
|
57
|
-
);
|
|
54
|
+
const serial = this.actorSerial(actorId);
|
|
55
|
+
return this.actorExecutor(actorId).execute(() => operation(serial), workOptions);
|
|
58
56
|
}
|
|
59
57
|
|
|
60
58
|
/** @internal Restores a durable Actor FIFO prefix without starting it. */
|
|
@@ -102,6 +100,14 @@ export class ZLinkSpotSerialExecutor {
|
|
|
102
100
|
return this.spotSerial.execute(operation, { ...workOptions, lane: 'lifecycle' });
|
|
103
101
|
}
|
|
104
102
|
|
|
103
|
+
async terminateActor(actorId: string, terminal: () => Promise<void>): Promise<void> {
|
|
104
|
+
const executor = this.actorExecutor(actorId);
|
|
105
|
+
await executor.close();
|
|
106
|
+
await terminal();
|
|
107
|
+
if (this.actorExecutors.get(actorId) === executor) this.actorExecutors.delete(actorId);
|
|
108
|
+
this.actorSerials.delete(actorId);
|
|
109
|
+
}
|
|
110
|
+
|
|
105
111
|
/**
|
|
106
112
|
* Makes all child queues unreachable and completes them in one synchronous
|
|
107
113
|
* ownership turn. Already accepted work remains drainable.
|
|
@@ -134,7 +140,10 @@ export class ZLinkSpotSerialExecutor {
|
|
|
134
140
|
this.throwIfClosing();
|
|
135
141
|
let executor = this.actorExecutors.get(actorId);
|
|
136
142
|
if (executor === undefined) {
|
|
137
|
-
executor =
|
|
143
|
+
executor =
|
|
144
|
+
this.executionMode === ZLinkUserSpotExecutionMode.SpotWide
|
|
145
|
+
? this.spotSerial.createActorExecutor(actorId, this.sourceSpotId, this.actorOptions)
|
|
146
|
+
: new ZLinkActorSerialExecutor(actorId, this.sourceSpotId, this.actorOptions);
|
|
138
147
|
this.actorExecutors.set(actorId, executor);
|
|
139
148
|
}
|
|
140
149
|
return executor;
|
|
@@ -19,6 +19,7 @@ import {
|
|
|
19
19
|
type ZLinkSerialWorkRecord
|
|
20
20
|
} from '../execution/serial-execution-queue';
|
|
21
21
|
import type { ZLinkSerialLifecycleContext } from '../execution/serial-execution-queue';
|
|
22
|
+
import { ZLinkActorSerialExecutor } from '../actors/actor-mailbox';
|
|
22
23
|
|
|
23
24
|
export type ZLinkSpotApplicationTurnContext = ZLinkExecutionBarrierClaim & {
|
|
24
25
|
readonly replay?: (failure?: unknown) => Promise<unknown> | unknown;
|
|
@@ -53,6 +54,15 @@ export class ZLinkSpotSerialTurnExecutor {
|
|
|
53
54
|
return this.depth > 0;
|
|
54
55
|
}
|
|
55
56
|
|
|
57
|
+
/** Creates a passive Actor mailbox consumed by this Spot's scheduler. */
|
|
58
|
+
createActorExecutor(
|
|
59
|
+
actorId: string,
|
|
60
|
+
sourceSpotId: unknown,
|
|
61
|
+
options?: ZLinkSerialSchedulerOptions
|
|
62
|
+
): ZLinkActorSerialExecutor {
|
|
63
|
+
return new ZLinkActorSerialExecutor(actorId, sourceSpotId, options, this.scheduler);
|
|
64
|
+
}
|
|
65
|
+
|
|
56
66
|
get isCurrentTurn(): boolean {
|
|
57
67
|
return this.depth > 0 && isCurrentZLinkSpotSerialTurn(this);
|
|
58
68
|
}
|
|
@@ -87,7 +87,6 @@ import {
|
|
|
87
87
|
type ZLinkStreamSessionRuntimeOptions as ZLinkStreamSessionRuntimeCoreOptions
|
|
88
88
|
} from './stream-session-runtime';
|
|
89
89
|
const DEFAULT_STREAM_SERVICE_SHUTDOWN_TIMEOUT_MS = 1000;
|
|
90
|
-
export { ZLinkPendingSessionRequest } from './session-requests';
|
|
91
90
|
export { ZLinkActorSessionLifecycleCoordinator } from './actor-session-lifecycle-coordinator';
|
|
92
91
|
export { ZLinkActorSessionBindingRegistry } from './actor-session-binding-registry';
|
|
93
92
|
export { zlinkStreamLz4CompressionCodec } from './stream-frame-factory';
|
|
@@ -305,6 +304,9 @@ export class ZLinkStreamRuntimeManager {
|
|
|
305
304
|
const readablePoller = streamAdapter.createReadablePoller(socket);
|
|
306
305
|
const runtime = new ZLinkStreamSessionNodeRuntimeCore({
|
|
307
306
|
nodeName,
|
|
307
|
+
heartbeatIntervalMs: streamNode.heartbeatIntervalMs,
|
|
308
|
+
heartbeatTimeoutMs: streamNode.heartbeatTimeoutMs,
|
|
309
|
+
idleTimeoutMs: streamNode.idleTimeoutMs,
|
|
308
310
|
socket,
|
|
309
311
|
createPacket: () => streamAdapter.createStreamPacket(),
|
|
310
312
|
readablePoller,
|