sen-ether-client 0.2.0 → 0.2.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/lib/client.js +14 -1
- package/lib/sen.js +63 -33
- package/package.json +1 -1
package/lib/client.js
CHANGED
|
@@ -470,6 +470,7 @@ export class EtherClient extends EventEmitter {
|
|
|
470
470
|
this.ready = false;
|
|
471
471
|
this.buses = new Map();
|
|
472
472
|
this.remoteParticipantsByBusId = new Map();
|
|
473
|
+
this.nextInterestId = randomUInt32();
|
|
473
474
|
}
|
|
474
475
|
|
|
475
476
|
/**
|
|
@@ -997,7 +998,7 @@ export class EtherClient extends EventEmitter {
|
|
|
997
998
|
*/
|
|
998
999
|
startInterest(bus, query, options = {}) {
|
|
999
1000
|
const busState = this.#getBus(bus);
|
|
1000
|
-
const id = options.id ??
|
|
1001
|
+
const id = options.id ?? this.#nextInterestId(busState);
|
|
1001
1002
|
this.#sendBusControlToRemoteParticipants(busState, {
|
|
1002
1003
|
type: 'InterestStarted',
|
|
1003
1004
|
value: { query, id }
|
|
@@ -1007,6 +1008,18 @@ export class EtherClient extends EventEmitter {
|
|
|
1007
1008
|
return { busName: busState.busName, busId: busState.busId, id, query };
|
|
1008
1009
|
}
|
|
1009
1010
|
|
|
1011
|
+
#nextInterestId(busState) {
|
|
1012
|
+
for (let attempts = 0; attempts < 0xffff_ffff; attempts += 1) {
|
|
1013
|
+
this.nextInterestId = (this.nextInterestId + 1) >>> 0;
|
|
1014
|
+
const id = this.nextInterestId || 1;
|
|
1015
|
+
if (!busState.interests.has(id)) {
|
|
1016
|
+
this.nextInterestId = id;
|
|
1017
|
+
return id;
|
|
1018
|
+
}
|
|
1019
|
+
}
|
|
1020
|
+
throw new Error('could not allocate a SEN interest id');
|
|
1021
|
+
}
|
|
1022
|
+
|
|
1010
1023
|
#restartInterestForRemote(busState) {
|
|
1011
1024
|
for (const participant of this.#remoteParticipantsForBus(busState.busId)) {
|
|
1012
1025
|
for (const interest of busState.interests.values()) {
|
package/lib/sen.js
CHANGED
|
@@ -161,8 +161,20 @@ function normalizeTimestampNs(value) {
|
|
|
161
161
|
return typeof value === 'bigint' ? value : BigInt(value);
|
|
162
162
|
}
|
|
163
163
|
|
|
164
|
-
function stateRequestKey(interestId, objectId) {
|
|
165
|
-
return `${interestId >>> 0}:${objectId
|
|
164
|
+
function stateRequestKey(interestId, ownerId, objectId) {
|
|
165
|
+
return `${interestId >>> 0}:${remoteObjectKey(ownerId, objectId)}`;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
function remoteObjectKey(ownerId, objectId) {
|
|
169
|
+
const owner = ownerId === undefined || ownerId === null ? 'unknown' : String(ownerId >>> 0);
|
|
170
|
+
return `${owner}:${objectId >>> 0}`;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
function eventOwnerId(event) {
|
|
174
|
+
if (event?.ownerId !== undefined) {
|
|
175
|
+
return event.ownerId;
|
|
176
|
+
}
|
|
177
|
+
return event?.multicast ? undefined : event?.to;
|
|
166
178
|
}
|
|
167
179
|
|
|
168
180
|
async function waitForSessionBuses(session, timeoutMs) {
|
|
@@ -1312,43 +1324,36 @@ export class SenBus extends EventEmitter {
|
|
|
1312
1324
|
}
|
|
1313
1325
|
|
|
1314
1326
|
handleObjectsPublished(event) {
|
|
1327
|
+
const ownerId = eventOwnerId(event);
|
|
1315
1328
|
const newTypeHashes = new Set();
|
|
1316
1329
|
for (const discovery of event.discoveries ?? []) {
|
|
1317
1330
|
const interest = this.interests.get(discovery.interestId);
|
|
1318
|
-
if (interest
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1331
|
+
if (!interest) {
|
|
1332
|
+
continue;
|
|
1333
|
+
}
|
|
1334
|
+
if (ownerId !== undefined) {
|
|
1335
|
+
interest.ownerId ??= ownerId;
|
|
1336
|
+
interest.ownerIds.add(ownerId >>> 0);
|
|
1324
1337
|
}
|
|
1325
1338
|
|
|
1326
1339
|
for (const info of discovery.objects ?? []) {
|
|
1327
|
-
let object = this
|
|
1328
|
-
if (object && event.ownerId !== undefined && object.ownerId !== event.ownerId) {
|
|
1329
|
-
this.#removeObjectFromAllInterests(object, {
|
|
1330
|
-
reason: 'ownerChanged',
|
|
1331
|
-
ownerId: event.ownerId,
|
|
1332
|
-
previousOwnerId: object.ownerId
|
|
1333
|
-
});
|
|
1334
|
-
object = undefined;
|
|
1335
|
-
}
|
|
1340
|
+
let object = this.#objectByOwnerAndId(ownerId, info.id);
|
|
1336
1341
|
const isNewObject = !object;
|
|
1337
1342
|
if (!object) {
|
|
1338
1343
|
object = new SenRemoteObject(this, {
|
|
1339
1344
|
...info,
|
|
1340
|
-
ownerId
|
|
1345
|
+
ownerId,
|
|
1341
1346
|
interestId: discovery.interestId
|
|
1342
1347
|
});
|
|
1343
|
-
this.objectsById.set(object.
|
|
1348
|
+
this.objectsById.set(object.key, object);
|
|
1344
1349
|
} else {
|
|
1345
1350
|
object.attachInterest(discovery.interestId);
|
|
1346
1351
|
object.updateDiscoveryInfo({
|
|
1347
1352
|
...info,
|
|
1348
|
-
ownerId
|
|
1353
|
+
ownerId
|
|
1349
1354
|
});
|
|
1350
1355
|
}
|
|
1351
|
-
interest?.objectsById.set(object.
|
|
1356
|
+
interest?.objectsById.set(object.key, object);
|
|
1352
1357
|
if (info.state?.length) {
|
|
1353
1358
|
object.applyState(info.state, 'published', info.time, { interestId: discovery.interestId });
|
|
1354
1359
|
}
|
|
@@ -1367,10 +1372,14 @@ export class SenBus extends EventEmitter {
|
|
|
1367
1372
|
}
|
|
1368
1373
|
|
|
1369
1374
|
handleObjectsRemoved(event) {
|
|
1375
|
+
const ownerId = eventOwnerId(event);
|
|
1370
1376
|
for (const removal of event.removals ?? []) {
|
|
1377
|
+
const interest = this.interests.get(removal.interestId);
|
|
1378
|
+
if (!interest) {
|
|
1379
|
+
continue;
|
|
1380
|
+
}
|
|
1371
1381
|
for (const id of removal.ids ?? []) {
|
|
1372
|
-
const object = this
|
|
1373
|
-
const interest = this.interests.get(removal.interestId);
|
|
1382
|
+
const object = this.#objectByOwnerAndId(ownerId, id);
|
|
1374
1383
|
if (object) {
|
|
1375
1384
|
this.#removeObjectFromInterest(object, removal.interestId, interest);
|
|
1376
1385
|
}
|
|
@@ -1419,14 +1428,16 @@ export class SenBus extends EventEmitter {
|
|
|
1419
1428
|
|
|
1420
1429
|
#removeObjectFromInterest(object, interestId, interest, detail = {}) {
|
|
1421
1430
|
const normalizedInterestId = interestId >>> 0;
|
|
1422
|
-
this.stateRequestedObjectIds.delete(stateRequestKey(normalizedInterestId, object.id));
|
|
1423
|
-
interest?.objectsById.delete(object.
|
|
1431
|
+
this.stateRequestedObjectIds.delete(stateRequestKey(normalizedInterestId, object.ownerId, object.id));
|
|
1432
|
+
interest?.objectsById.delete(object.key);
|
|
1424
1433
|
object.detachInterest(normalizedInterestId);
|
|
1425
1434
|
object.emit('remove', { interestId: normalizedInterestId, ...detail });
|
|
1426
1435
|
interest?.emit('remove', object);
|
|
1427
1436
|
if (object.interestIds.size === 0) {
|
|
1428
|
-
this.objectsById.delete(object.
|
|
1429
|
-
this.
|
|
1437
|
+
this.objectsById.delete(object.key);
|
|
1438
|
+
if (![...this.objectsById.values()].some(item => item.typeHash === object.typeHash)) {
|
|
1439
|
+
this.requestedTypeHashes.delete(object.typeHash);
|
|
1440
|
+
}
|
|
1430
1441
|
this.emit('remove', object);
|
|
1431
1442
|
this.sen.emit('remove', object);
|
|
1432
1443
|
}
|
|
@@ -1491,10 +1502,15 @@ export class SenBus extends EventEmitter {
|
|
|
1491
1502
|
}
|
|
1492
1503
|
|
|
1493
1504
|
handleObjectsStateResponse(event) {
|
|
1505
|
+
const ownerId = eventOwnerId(event);
|
|
1494
1506
|
for (const response of event.responses ?? []) {
|
|
1507
|
+
const interest = this.interests.get(response.interestId);
|
|
1508
|
+
if (!interest) {
|
|
1509
|
+
continue;
|
|
1510
|
+
}
|
|
1495
1511
|
for (const state of response.objectStates ?? []) {
|
|
1496
|
-
const object = this
|
|
1497
|
-
if (!object || (
|
|
1512
|
+
const object = this.#objectByOwnerAndId(ownerId, state.id);
|
|
1513
|
+
if (!object || !interest.objectsById.has(object.key)) {
|
|
1498
1514
|
continue;
|
|
1499
1515
|
}
|
|
1500
1516
|
object.applyState(state.state, 'state', state.timestamp, { interestId: response.interestId });
|
|
@@ -1503,7 +1519,7 @@ export class SenBus extends EventEmitter {
|
|
|
1503
1519
|
}
|
|
1504
1520
|
|
|
1505
1521
|
handleRuntimeObjectUpdate(event) {
|
|
1506
|
-
const object = this
|
|
1522
|
+
const object = this.#objectByOwnerAndId(eventOwnerId(event), event.update.objectId);
|
|
1507
1523
|
if (!object) {
|
|
1508
1524
|
return;
|
|
1509
1525
|
}
|
|
@@ -1511,8 +1527,9 @@ export class SenBus extends EventEmitter {
|
|
|
1511
1527
|
}
|
|
1512
1528
|
|
|
1513
1529
|
handleRuntimeEvents(event) {
|
|
1530
|
+
const ownerId = eventOwnerId(event);
|
|
1514
1531
|
for (const item of event.events ?? []) {
|
|
1515
|
-
const object = this
|
|
1532
|
+
const object = this.#objectByOwnerAndId(ownerId, item.producerId);
|
|
1516
1533
|
if (!object) {
|
|
1517
1534
|
continue;
|
|
1518
1535
|
}
|
|
@@ -1583,7 +1600,7 @@ export class SenBus extends EventEmitter {
|
|
|
1583
1600
|
if (!object.spec) {
|
|
1584
1601
|
continue;
|
|
1585
1602
|
}
|
|
1586
|
-
const key = stateRequestKey(interest.id, object.id);
|
|
1603
|
+
const key = stateRequestKey(interest.id, object.ownerId, object.id);
|
|
1587
1604
|
if (!force && this.stateRequestedObjectIds.has(key)) {
|
|
1588
1605
|
continue;
|
|
1589
1606
|
}
|
|
@@ -1656,6 +1673,14 @@ export class SenBus extends EventEmitter {
|
|
|
1656
1673
|
}
|
|
1657
1674
|
}
|
|
1658
1675
|
}
|
|
1676
|
+
|
|
1677
|
+
#objectByOwnerAndId(ownerId, objectId) {
|
|
1678
|
+
if (ownerId !== undefined && ownerId !== null) {
|
|
1679
|
+
return this.objectsById.get(remoteObjectKey(ownerId, objectId));
|
|
1680
|
+
}
|
|
1681
|
+
const id = objectId >>> 0;
|
|
1682
|
+
return [...this.objectsById.values()].find(object => object.id === id);
|
|
1683
|
+
}
|
|
1659
1684
|
}
|
|
1660
1685
|
|
|
1661
1686
|
export class SenInterest extends EventEmitter {
|
|
@@ -1665,6 +1690,7 @@ export class SenInterest extends EventEmitter {
|
|
|
1665
1690
|
this.id = id;
|
|
1666
1691
|
this.query = query;
|
|
1667
1692
|
this.ownerId = undefined;
|
|
1693
|
+
this.ownerIds = new Set();
|
|
1668
1694
|
this.options = { ...options };
|
|
1669
1695
|
this.propertyNames = normalizePropertyNames(options.properties ?? options.propertyNames);
|
|
1670
1696
|
this.changeMode = options.changeMode ?? (options.batch ? 'batch' : 'individual');
|
|
@@ -1867,6 +1893,10 @@ export class SenRemoteObject extends EventEmitter {
|
|
|
1867
1893
|
return this.propertyTimestamps.get(name);
|
|
1868
1894
|
}
|
|
1869
1895
|
|
|
1896
|
+
get key() {
|
|
1897
|
+
return remoteObjectKey(this.ownerId, this.id);
|
|
1898
|
+
}
|
|
1899
|
+
|
|
1870
1900
|
isReadyForInterest(interestId) {
|
|
1871
1901
|
return this.readyInterestIds.has(interestId >>> 0);
|
|
1872
1902
|
}
|
|
@@ -2002,7 +2032,7 @@ export class SenRemoteObject extends EventEmitter {
|
|
|
2002
2032
|
|
|
2003
2033
|
const interests = [];
|
|
2004
2034
|
for (const interest of this.bus.interests.values()) {
|
|
2005
|
-
if (interest.objectsById.has(this.id)) {
|
|
2035
|
+
if (interest.objectsById.has(this.key) || interest.objectsById.has(this.id)) {
|
|
2006
2036
|
interests.push(interest);
|
|
2007
2037
|
}
|
|
2008
2038
|
}
|