@olane/o-node 0.7.13-alpha.0 → 0.7.13-alpha.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/src/connection/interfaces/o-node-connection-manager.config.d.ts +1 -0
- package/dist/src/connection/interfaces/o-node-connection-manager.config.d.ts.map +1 -1
- package/dist/src/connection/o-node-connection.d.ts +0 -1
- package/dist/src/connection/o-node-connection.d.ts.map +1 -1
- package/dist/src/connection/o-node-connection.js +0 -8
- package/dist/src/connection/o-node-connection.manager.d.ts +33 -4
- package/dist/src/connection/o-node-connection.manager.d.ts.map +1 -1
- package/dist/src/connection/o-node-connection.manager.js +153 -44
- package/dist/src/connection/stream-handler.d.ts.map +1 -1
- package/dist/src/connection/stream-handler.js +0 -2
- package/dist/src/managers/o-connection-heartbeat.manager.d.ts.map +1 -1
- package/dist/src/managers/o-connection-heartbeat.manager.js +15 -1
- package/dist/src/managers/o-reconnection.manager.d.ts.map +1 -1
- package/dist/src/managers/o-reconnection.manager.js +12 -7
- package/dist/src/o-node.d.ts +5 -0
- package/dist/src/o-node.d.ts.map +1 -1
- package/dist/src/o-node.js +46 -8
- package/dist/src/o-node.tool.d.ts.map +1 -1
- package/dist/src/o-node.tool.js +5 -0
- package/dist/src/router/o-node.router.d.ts.map +1 -1
- package/dist/src/router/o-node.router.js +16 -6
- package/dist/src/router/o-node.routing-policy.d.ts.map +1 -1
- package/dist/src/router/o-node.routing-policy.js +4 -0
- package/dist/test/connection-management.spec.d.ts +2 -0
- package/dist/test/connection-management.spec.d.ts.map +1 -0
- package/dist/test/connection-management.spec.js +370 -0
- package/dist/test/helpers/connection-spy.d.ts +124 -0
- package/dist/test/helpers/connection-spy.d.ts.map +1 -0
- package/dist/test/helpers/connection-spy.js +229 -0
- package/dist/test/helpers/index.d.ts +6 -0
- package/dist/test/helpers/index.d.ts.map +1 -0
- package/dist/test/helpers/index.js +12 -0
- package/dist/test/helpers/network-builder.d.ts +109 -0
- package/dist/test/helpers/network-builder.d.ts.map +1 -0
- package/dist/test/helpers/network-builder.js +309 -0
- package/dist/test/helpers/simple-node-builder.d.ts +50 -0
- package/dist/test/helpers/simple-node-builder.d.ts.map +1 -0
- package/dist/test/helpers/simple-node-builder.js +66 -0
- package/dist/test/helpers/test-environment.d.ts +140 -0
- package/dist/test/helpers/test-environment.d.ts.map +1 -0
- package/dist/test/helpers/test-environment.js +184 -0
- package/dist/test/helpers/test-node.tool.d.ts +31 -0
- package/dist/test/helpers/test-node.tool.d.ts.map +1 -1
- package/dist/test/helpers/test-node.tool.js +49 -0
- package/dist/test/network-communication.spec.d.ts +2 -0
- package/dist/test/network-communication.spec.d.ts.map +1 -0
- package/dist/test/network-communication.spec.js +256 -0
- package/dist/test/o-node.spec.d.ts +2 -0
- package/dist/test/o-node.spec.d.ts.map +1 -0
- package/dist/test/o-node.spec.js +247 -0
- package/dist/test/parent-child-registration.spec.d.ts +2 -0
- package/dist/test/parent-child-registration.spec.d.ts.map +1 -0
- package/dist/test/parent-child-registration.spec.js +177 -0
- package/dist/test/search-resolver.spec.d.ts +2 -0
- package/dist/test/search-resolver.spec.d.ts.map +1 -0
- package/dist/test/search-resolver.spec.js +648 -0
- package/package.json +12 -7
|
@@ -3,5 +3,6 @@ import { Libp2p } from '@olane/o-config';
|
|
|
3
3
|
export interface oNodeConnectionManagerConfig extends oConnectionManagerConfig {
|
|
4
4
|
p2pNode: Libp2p;
|
|
5
5
|
runOnLimitedConnection?: boolean;
|
|
6
|
+
originAddress?: string;
|
|
6
7
|
}
|
|
7
8
|
//# sourceMappingURL=o-node-connection-manager.config.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"o-node-connection-manager.config.d.ts","sourceRoot":"","sources":["../../../../src/connection/interfaces/o-node-connection-manager.config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,MAAM,eAAe,CAAC;AACzD,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAEzC,MAAM,WAAW,4BAA6B,SAAQ,wBAAwB;IAC5E,OAAO,EAAE,MAAM,CAAC;IAChB,sBAAsB,CAAC,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"o-node-connection-manager.config.d.ts","sourceRoot":"","sources":["../../../../src/connection/interfaces/o-node-connection-manager.config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,MAAM,eAAe,CAAC;AACzD,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAEzC,MAAM,WAAW,4BAA6B,SAAQ,wBAAwB;IAC5E,OAAO,EAAE,MAAM,CAAC;IAChB,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB"}
|
|
@@ -7,7 +7,6 @@ export declare class oNodeConnection extends oConnection {
|
|
|
7
7
|
p2pConnection: Connection;
|
|
8
8
|
protected streamHandler: StreamHandler;
|
|
9
9
|
constructor(config: oNodeConnectionConfig);
|
|
10
|
-
setupConnectionListeners(): void;
|
|
11
10
|
validate(stream?: Stream): void;
|
|
12
11
|
getOrCreateStream(): Promise<Stream>;
|
|
13
12
|
transmit(request: oRequest): Promise<oResponse>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"o-node-connection.d.ts","sourceRoot":"","sources":["../../../src/connection/o-node-connection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,EAEL,WAAW,EAGX,QAAQ,EACR,SAAS,EACV,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,qBAAqB,EAAE,MAAM,0CAA0C,CAAC;AACjF,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAGpD,qBAAa,eAAgB,SAAQ,WAAW;IAIlC,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,qBAAqB;IAHrD,aAAa,EAAE,UAAU,CAAC;IACjC,SAAS,CAAC,aAAa,EAAE,aAAa,CAAC;gBAER,MAAM,EAAE,qBAAqB;
|
|
1
|
+
{"version":3,"file":"o-node-connection.d.ts","sourceRoot":"","sources":["../../../src/connection/o-node-connection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,EAEL,WAAW,EAGX,QAAQ,EACR,SAAS,EACV,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,qBAAqB,EAAE,MAAM,0CAA0C,CAAC;AACjF,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAGpD,qBAAa,eAAgB,SAAQ,WAAW;IAIlC,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,qBAAqB;IAHrD,aAAa,EAAE,UAAU,CAAC;IACjC,SAAS,CAAC,aAAa,EAAE,aAAa,CAAC;gBAER,MAAM,EAAE,qBAAqB;IAM5D,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM;IAmBlB,iBAAiB,IAAI,OAAO,CAAC,MAAM,CAAC;IAkBpC,QAAQ,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,SAAS,CAAC;IA0C/C,YAAY,CAAC,MAAM,EAAE,MAAM;IAQ3B,KAAK,CAAC,KAAK,EAAE,KAAK;IAMlB,KAAK;CAKZ"}
|
|
@@ -6,14 +6,6 @@ export class oNodeConnection extends oConnection {
|
|
|
6
6
|
this.config = config;
|
|
7
7
|
this.p2pConnection = config.p2pConnection;
|
|
8
8
|
this.streamHandler = new StreamHandler(this.logger);
|
|
9
|
-
this.setupConnectionListeners();
|
|
10
|
-
}
|
|
11
|
-
setupConnectionListeners() {
|
|
12
|
-
this.logger.debug('Setting up connection listeners for address: ' +
|
|
13
|
-
this.nextHopAddress.toString());
|
|
14
|
-
this.p2pConnection?.addEventListener('close', () => {
|
|
15
|
-
this.logger.debug('Connection closed for address: ' + this.nextHopAddress.toString());
|
|
16
|
-
});
|
|
17
9
|
}
|
|
18
10
|
validate(stream) {
|
|
19
11
|
if (this.config.p2pConnection.status !== 'open') {
|
|
@@ -7,9 +7,21 @@ export declare class oNodeConnectionManager extends oConnectionManager {
|
|
|
7
7
|
protected p2pNode: Libp2p;
|
|
8
8
|
private defaultReadTimeoutMs?;
|
|
9
9
|
private defaultDrainTimeoutMs?;
|
|
10
|
-
private
|
|
10
|
+
private connectionsByPeerId;
|
|
11
|
+
private pendingDialsByPeerId;
|
|
11
12
|
constructor(config: oNodeConnectionManagerConfig);
|
|
13
|
+
/**
|
|
14
|
+
* Set up listeners to maintain connection cache state
|
|
15
|
+
*/
|
|
16
|
+
private setupConnectionListeners;
|
|
17
|
+
/**
|
|
18
|
+
* Extract peer ID string from an address
|
|
19
|
+
* @param address - The address to extract peer ID from
|
|
20
|
+
* @returns The peer ID string or null if not found
|
|
21
|
+
*/
|
|
22
|
+
private getPeerIdFromAddress;
|
|
12
23
|
getOrCreateConnection(nextHopAddress: oAddress, address: oAddress): Promise<Connection>;
|
|
24
|
+
private performDial;
|
|
13
25
|
/**
|
|
14
26
|
* Connect to a given address, reusing libp2p connections when possible
|
|
15
27
|
* @param config - Connection configuration
|
|
@@ -17,16 +29,33 @@ export declare class oNodeConnectionManager extends oConnectionManager {
|
|
|
17
29
|
*/
|
|
18
30
|
connect(config: oConnectionConfig): Promise<oNodeConnection>;
|
|
19
31
|
/**
|
|
20
|
-
* Check if
|
|
32
|
+
* Check if we have an active connection to the target peer
|
|
21
33
|
* @param address - The address to check
|
|
22
34
|
* @returns true if an active connection exists
|
|
23
35
|
*/
|
|
24
36
|
isCached(address: oAddress): boolean;
|
|
25
37
|
/**
|
|
26
|
-
* Get an existing
|
|
38
|
+
* Get an existing connection to the target peer (from cache or libp2p)
|
|
27
39
|
* @param address - The address to get a connection for
|
|
28
|
-
* @returns The
|
|
40
|
+
* @returns The Connection object or null if not found
|
|
29
41
|
*/
|
|
30
42
|
getCachedLibp2pConnection(address: oAddress): Connection | null;
|
|
43
|
+
/**
|
|
44
|
+
* Get cache statistics for monitoring and debugging
|
|
45
|
+
* @returns Object containing cache statistics
|
|
46
|
+
*/
|
|
47
|
+
getCacheStats(): {
|
|
48
|
+
cachedConnections: number;
|
|
49
|
+
pendingDials: number;
|
|
50
|
+
connectionsByPeer: Array<{
|
|
51
|
+
peerId: string;
|
|
52
|
+
status: string;
|
|
53
|
+
}>;
|
|
54
|
+
};
|
|
55
|
+
/**
|
|
56
|
+
* Clean up all stale (non-open) connections from cache
|
|
57
|
+
* @returns Number of connections removed
|
|
58
|
+
*/
|
|
59
|
+
cleanupStaleConnections(): number;
|
|
31
60
|
}
|
|
32
61
|
//# sourceMappingURL=o-node-connection.manager.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"o-node-connection.manager.d.ts","sourceRoot":"","sources":["../../../src/connection/o-node-connection.manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAChF,OAAO,EAAE,MAAM,EAAE,UAAU,EAAU,MAAM,iBAAiB,CAAC;AAC7D,OAAO,EAAE,4BAA4B,EAAE,MAAM,kDAAkD,CAAC;AAEhG,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAGzD,qBAAa,sBAAuB,SAAQ,kBAAkB;
|
|
1
|
+
{"version":3,"file":"o-node-connection.manager.d.ts","sourceRoot":"","sources":["../../../src/connection/o-node-connection.manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAChF,OAAO,EAAE,MAAM,EAAE,UAAU,EAAU,MAAM,iBAAiB,CAAC;AAC7D,OAAO,EAAE,4BAA4B,EAAE,MAAM,kDAAkD,CAAC;AAEhG,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAGzD,qBAAa,sBAAuB,SAAQ,kBAAkB;IAOhD,QAAQ,CAAC,MAAM,EAAE,4BAA4B;IANzD,SAAS,CAAC,OAAO,EAAE,MAAM,CAAC;IAC1B,OAAO,CAAC,oBAAoB,CAAC,CAAS;IACtC,OAAO,CAAC,qBAAqB,CAAC,CAAS;IACvC,OAAO,CAAC,mBAAmB,CAAsC;IACjE,OAAO,CAAC,oBAAoB,CAA+C;gBAEtD,MAAM,EAAE,4BAA4B;IAWzD;;OAEG;IACH,OAAO,CAAC,wBAAwB;IAUhC;;;;OAIG;IACH,OAAO,CAAC,oBAAoB;IAatB,qBAAqB,CACzB,cAAc,EAAE,QAAQ,EACxB,OAAO,EAAE,QAAQ,GAChB,OAAO,CAAC,UAAU,CAAC;YAmDR,WAAW;IAwBzB;;;;OAIG;IACG,OAAO,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,eAAe,CAAC;IA8BlE;;;;OAIG;IACH,QAAQ,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO;IAmCpC;;;;OAIG;IACH,yBAAyB,CAAC,OAAO,EAAE,QAAQ,GAAG,UAAU,GAAG,IAAI;IA0C/D;;;OAGG;IACH,aAAa,IAAI;QACf,iBAAiB,EAAE,MAAM,CAAC;QAC1B,YAAY,EAAE,MAAM,CAAC;QACrB,iBAAiB,EAAE,KAAK,CAAC;YAAE,MAAM,EAAE,MAAM,CAAC;YAAC,MAAM,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;KAC9D;IAaD;;;OAGG;IACH,uBAAuB,IAAI,MAAM;CAalC"}
|
|
@@ -4,32 +4,100 @@ export class oNodeConnectionManager extends oConnectionManager {
|
|
|
4
4
|
constructor(config) {
|
|
5
5
|
super(config);
|
|
6
6
|
this.config = config;
|
|
7
|
-
this.
|
|
7
|
+
this.connectionsByPeerId = new Map();
|
|
8
|
+
this.pendingDialsByPeerId = new Map();
|
|
8
9
|
this.p2pNode = config.p2pNode;
|
|
9
10
|
this.defaultReadTimeoutMs = config.defaultReadTimeoutMs;
|
|
10
11
|
this.defaultDrainTimeoutMs = config.defaultDrainTimeoutMs;
|
|
12
|
+
this.logger.setNamespace(`oNodeConnectionManager[${config.originAddress}]`);
|
|
13
|
+
// Set up connection lifecycle listeners for cache management
|
|
14
|
+
this.setupConnectionListeners();
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Set up listeners to maintain connection cache state
|
|
18
|
+
*/
|
|
19
|
+
setupConnectionListeners() {
|
|
20
|
+
this.p2pNode.addEventListener('connection:close', (event) => {
|
|
21
|
+
const peerId = event.detail?.remotePeer?.toString();
|
|
22
|
+
if (peerId && this.connectionsByPeerId.has(peerId)) {
|
|
23
|
+
this.logger.debug('Connection closed, removing from cache:', peerId);
|
|
24
|
+
this.connectionsByPeerId.delete(peerId);
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Extract peer ID string from an address
|
|
30
|
+
* @param address - The address to extract peer ID from
|
|
31
|
+
* @returns The peer ID string or null if not found
|
|
32
|
+
*/
|
|
33
|
+
getPeerIdFromAddress(address) {
|
|
34
|
+
try {
|
|
35
|
+
const nodeAddress = address;
|
|
36
|
+
if (!nodeAddress.libp2pTransports?.length) {
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
return nodeAddress.libp2pTransports[0].toPeerId() || null;
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
this.logger.debug('Error extracting peer ID from address:', error);
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
11
45
|
}
|
|
12
46
|
async getOrCreateConnection(nextHopAddress, address) {
|
|
13
|
-
//
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
this.logger.debug('Reusing existing libp2p connection for address: ' +
|
|
18
|
-
nextHopAddress.toString());
|
|
19
|
-
p2pConnection = existingConnection;
|
|
47
|
+
// Extract peer ID as the cache key
|
|
48
|
+
const peerId = this.getPeerIdFromAddress(nextHopAddress);
|
|
49
|
+
if (!peerId) {
|
|
50
|
+
throw new Error(`Unable to extract peer ID from address: ${nextHopAddress.toString()}`);
|
|
20
51
|
}
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
52
|
+
// Check if we have a cached connection by peer ID
|
|
53
|
+
const cachedConnection = this.connectionsByPeerId.get(peerId);
|
|
54
|
+
if (cachedConnection && cachedConnection.status === 'open') {
|
|
55
|
+
this.logger.debug('Reusing cached connection for peer:', peerId);
|
|
56
|
+
return cachedConnection;
|
|
25
57
|
}
|
|
26
|
-
if
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
58
|
+
// Clean up stale connection if it exists but is not open
|
|
59
|
+
if (cachedConnection && cachedConnection.status !== 'open') {
|
|
60
|
+
this.logger.debug('Removing stale connection for peer:', peerId);
|
|
61
|
+
this.connectionsByPeerId.delete(peerId);
|
|
62
|
+
}
|
|
63
|
+
// Check if libp2p has an active connection to this peer
|
|
64
|
+
const libp2pConnection = this.getCachedLibp2pConnection(nextHopAddress);
|
|
65
|
+
if (libp2pConnection && libp2pConnection.status === 'open') {
|
|
66
|
+
this.logger.debug('Caching existing libp2p connection for peer:', peerId);
|
|
67
|
+
this.connectionsByPeerId.set(peerId, libp2pConnection);
|
|
68
|
+
return libp2pConnection;
|
|
69
|
+
}
|
|
70
|
+
// Check if dial is already in progress for this peer
|
|
71
|
+
const pendingDial = this.pendingDialsByPeerId.get(peerId);
|
|
72
|
+
if (pendingDial) {
|
|
73
|
+
this.logger.debug('Awaiting existing dial for peer:', peerId);
|
|
74
|
+
return pendingDial;
|
|
75
|
+
}
|
|
76
|
+
// Start new dial and cache the promise by peer ID
|
|
77
|
+
const dialPromise = this.performDial(nextHopAddress, peerId);
|
|
78
|
+
this.pendingDialsByPeerId.set(peerId, dialPromise);
|
|
79
|
+
try {
|
|
80
|
+
const connection = await dialPromise;
|
|
81
|
+
// Cache the established connection by peer ID
|
|
82
|
+
this.connectionsByPeerId.set(peerId, connection);
|
|
83
|
+
return connection;
|
|
31
84
|
}
|
|
32
|
-
|
|
85
|
+
finally {
|
|
86
|
+
this.pendingDialsByPeerId.delete(peerId);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
async performDial(nextHopAddress, peerId) {
|
|
90
|
+
this.logger.debug('Dialing new connection', {
|
|
91
|
+
address: nextHopAddress.value,
|
|
92
|
+
peerId,
|
|
93
|
+
});
|
|
94
|
+
const connection = await this.p2pNode.dial(nextHopAddress.libp2pTransports.map((ma) => ma.toMultiaddr()));
|
|
95
|
+
this.logger.debug('Successfully dialed connection', {
|
|
96
|
+
peerId,
|
|
97
|
+
status: connection.status,
|
|
98
|
+
remotePeer: connection.remotePeer?.toString(),
|
|
99
|
+
});
|
|
100
|
+
return connection;
|
|
33
101
|
}
|
|
34
102
|
/**
|
|
35
103
|
* Connect to a given address, reusing libp2p connections when possible
|
|
@@ -54,27 +122,34 @@ export class oNodeConnectionManager extends oConnectionManager {
|
|
|
54
122
|
return connection;
|
|
55
123
|
}
|
|
56
124
|
/**
|
|
57
|
-
* Check if
|
|
125
|
+
* Check if we have an active connection to the target peer
|
|
58
126
|
* @param address - The address to check
|
|
59
127
|
* @returns true if an active connection exists
|
|
60
128
|
*/
|
|
61
129
|
isCached(address) {
|
|
62
130
|
try {
|
|
63
|
-
const
|
|
64
|
-
if (!
|
|
65
|
-
nodeAddress.libp2pTransports.length === 0) {
|
|
131
|
+
const peerId = this.getPeerIdFromAddress(address);
|
|
132
|
+
if (!peerId) {
|
|
66
133
|
return false;
|
|
67
134
|
}
|
|
68
|
-
//
|
|
69
|
-
const
|
|
70
|
-
if (
|
|
71
|
-
return
|
|
135
|
+
// Check our peer ID-based cache first
|
|
136
|
+
const cachedConnection = this.connectionsByPeerId.get(peerId);
|
|
137
|
+
if (cachedConnection?.status === 'open') {
|
|
138
|
+
return true;
|
|
72
139
|
}
|
|
73
|
-
|
|
140
|
+
// Fall back to checking libp2p's connections
|
|
74
141
|
// the following works since the peer id param is not really required: https://github.com/libp2p/js-libp2p/blob/0bbf5021b53938b2bffcffca6c13c479a95c2a60/packages/libp2p/src/connection-manager/index.ts#L508
|
|
75
|
-
const connections = this.p2pNode.getConnections(
|
|
142
|
+
const connections = this.p2pNode.getConnections(peerId); // ignore since converting to a proper peer id breaks the browser implementation
|
|
76
143
|
// Check if we have at least one open connection
|
|
77
|
-
|
|
144
|
+
const hasOpenConnection = connections.some((conn) => conn.status === 'open');
|
|
145
|
+
// If libp2p has an open connection, update our cache
|
|
146
|
+
if (hasOpenConnection) {
|
|
147
|
+
const openConnection = connections.find((conn) => conn.status === 'open');
|
|
148
|
+
if (openConnection) {
|
|
149
|
+
this.connectionsByPeerId.set(peerId, openConnection);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
return hasOpenConnection;
|
|
78
153
|
}
|
|
79
154
|
catch (error) {
|
|
80
155
|
this.logger.debug('Error checking cached connection:', error);
|
|
@@ -82,37 +157,71 @@ export class oNodeConnectionManager extends oConnectionManager {
|
|
|
82
157
|
}
|
|
83
158
|
}
|
|
84
159
|
/**
|
|
85
|
-
* Get an existing
|
|
160
|
+
* Get an existing connection to the target peer (from cache or libp2p)
|
|
86
161
|
* @param address - The address to get a connection for
|
|
87
|
-
* @returns The
|
|
162
|
+
* @returns The Connection object or null if not found
|
|
88
163
|
*/
|
|
89
164
|
getCachedLibp2pConnection(address) {
|
|
90
165
|
try {
|
|
91
|
-
const
|
|
92
|
-
if (!
|
|
166
|
+
const peerId = this.getPeerIdFromAddress(address);
|
|
167
|
+
if (!peerId) {
|
|
93
168
|
return null;
|
|
94
169
|
}
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
170
|
+
// Check peer ID-based cache first
|
|
171
|
+
const cachedConnection = this.connectionsByPeerId.get(peerId);
|
|
172
|
+
if (cachedConnection?.status === 'open') {
|
|
173
|
+
return cachedConnection;
|
|
98
174
|
}
|
|
99
|
-
|
|
100
|
-
const
|
|
101
|
-
|
|
175
|
+
// Query libp2p for connections to this peer
|
|
176
|
+
const connections = this.p2pNode.getConnections();
|
|
177
|
+
const filteredConnections = connections.filter((conn) => conn.remotePeer?.toString() === peerId);
|
|
178
|
+
// Find the first open connection
|
|
102
179
|
const openConnection = filteredConnections.find((conn) => conn.status === 'open');
|
|
180
|
+
// If we found an open connection in libp2p, cache it by peer ID
|
|
103
181
|
if (openConnection) {
|
|
182
|
+
this.connectionsByPeerId.set(peerId, openConnection);
|
|
104
183
|
return openConnection;
|
|
105
184
|
}
|
|
106
|
-
|
|
107
|
-
if (
|
|
108
|
-
|
|
185
|
+
// Clean up stale cache entry if connection is no longer open
|
|
186
|
+
if (cachedConnection) {
|
|
187
|
+
this.connectionsByPeerId.delete(peerId);
|
|
109
188
|
}
|
|
110
|
-
|
|
111
|
-
return connection ?? null;
|
|
189
|
+
return null;
|
|
112
190
|
}
|
|
113
191
|
catch (error) {
|
|
114
192
|
this.logger.debug('Error getting cached connection:', error);
|
|
115
193
|
return null;
|
|
116
194
|
}
|
|
117
195
|
}
|
|
196
|
+
/**
|
|
197
|
+
* Get cache statistics for monitoring and debugging
|
|
198
|
+
* @returns Object containing cache statistics
|
|
199
|
+
*/
|
|
200
|
+
getCacheStats() {
|
|
201
|
+
return {
|
|
202
|
+
cachedConnections: this.connectionsByPeerId.size,
|
|
203
|
+
pendingDials: this.pendingDialsByPeerId.size,
|
|
204
|
+
connectionsByPeer: Array.from(this.connectionsByPeerId.entries()).map(([peerId, conn]) => ({
|
|
205
|
+
peerId,
|
|
206
|
+
status: conn.status,
|
|
207
|
+
})),
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Clean up all stale (non-open) connections from cache
|
|
212
|
+
* @returns Number of connections removed
|
|
213
|
+
*/
|
|
214
|
+
cleanupStaleConnections() {
|
|
215
|
+
let removed = 0;
|
|
216
|
+
for (const [peerId, connection] of this.connectionsByPeerId.entries()) {
|
|
217
|
+
if (connection.status !== 'open') {
|
|
218
|
+
this.connectionsByPeerId.delete(peerId);
|
|
219
|
+
removed++;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
if (removed > 0) {
|
|
223
|
+
this.logger.debug(`Cleaned up ${removed} stale connections`);
|
|
224
|
+
}
|
|
225
|
+
return removed;
|
|
226
|
+
}
|
|
118
227
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stream-handler.d.ts","sourceRoot":"","sources":["../../../src/connection/stream-handler.ts"],"names":[],"mappings":";AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,EACL,QAAQ,EACR,SAAS,EAIT,MAAM,EAEP,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAGtE;;;;;;;GAOG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAS;gBAEX,MAAM,CAAC,EAAE,MAAM;IAI3B;;;OAGG;IACH,SAAS,CAAC,OAAO,EAAE,GAAG,GAAG,OAAO;IAIhC;;;OAGG;IACH,UAAU,CAAC,OAAO,EAAE,GAAG,GAAG,OAAO;IAIjC;;OAEG;IACG,aAAa,CAAC,KAAK,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;IAI7C;;;;;;OAMG;IACG,iBAAiB,CACrB,UAAU,EAAE,UAAU,EACtB,QAAQ,EAAE,MAAM,EAChB,MAAM,GAAE,mBAAwB,GAC/B,OAAO,CAAC,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"stream-handler.d.ts","sourceRoot":"","sources":["../../../src/connection/stream-handler.ts"],"names":[],"mappings":";AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,EACL,QAAQ,EACR,SAAS,EAIT,MAAM,EAEP,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAGtE;;;;;;;GAOG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAS;gBAEX,MAAM,CAAC,EAAE,MAAM;IAI3B;;;OAGG;IACH,SAAS,CAAC,OAAO,EAAE,GAAG,GAAG,OAAO;IAIhC;;;OAGG;IACH,UAAU,CAAC,OAAO,EAAE,GAAG,GAAG,OAAO;IAIjC;;OAEG;IACG,aAAa,CAAC,KAAK,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;IAI7C;;;;;;OAMG;IACG,iBAAiB,CACrB,UAAU,EAAE,UAAU,EACtB,QAAQ,EAAE,MAAM,EAChB,MAAM,GAAE,mBAAwB,GAC/B,OAAO,CAAC,MAAM,CAAC;IAoClB;;;;;;OAMG;IACG,IAAI,CACR,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,UAAU,EAChB,MAAM,GAAE,mBAAwB,GAC/B,OAAO,CAAC,IAAI,CAAC;IAiBhB;;;;;OAKG;IACG,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,GAAE,mBAAwB,GAAG,OAAO,CAAC,IAAI,CAAC;IAkB5E;;;;;;;;OAQG;IACG,oBAAoB,CACxB,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,UAAU,EACtB,YAAY,EAAE,CAAC,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,SAAS,CAAC,GACtE,OAAO,CAAC,IAAI,CAAC;IAuChB;;;;;;OAMG;YACW,oBAAoB;IA4BlC;;;;;;;;;;;OAWG;IACG,oBAAoB,CACxB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,YAAY,EACrB,MAAM,GAAE,mBAAwB,EAChC,cAAc,CAAC,EAAE,CAAC,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,SAAS,CAAC,EAC1E,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,GAC1B,OAAO,CAAC,SAAS,CAAC;IA+GrB;;;;;;;OAOG;IACG,cAAc,CAClB,OAAO,EAAE,cAAc,EACvB,cAAc,EAAE,MAAM,EACtB,MAAM,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,WAAW,CAAC,GAChD,OAAO,CAAC,IAAI,CAAC;CAyBjB"}
|
|
@@ -43,7 +43,6 @@ export class StreamHandler {
|
|
|
43
43
|
throw new oError(oErrorCodes.INVALID_STATE, 'Connection not open');
|
|
44
44
|
}
|
|
45
45
|
const reusePolicy = config.reusePolicy ?? 'none';
|
|
46
|
-
this.logger.debug('Reuse policy:', reusePolicy);
|
|
47
46
|
// Check for existing stream if reuse is enabled
|
|
48
47
|
if (reusePolicy === 'reuse') {
|
|
49
48
|
const existingStream = connection.streams.find((stream) => stream.status === 'open' &&
|
|
@@ -56,7 +55,6 @@ export class StreamHandler {
|
|
|
56
55
|
}
|
|
57
56
|
}
|
|
58
57
|
// Create new stream
|
|
59
|
-
this.logger.debug('Creating new stream');
|
|
60
58
|
const stream = await connection.newStream(protocol, {
|
|
61
59
|
signal: config.signal,
|
|
62
60
|
maxOutboundStreams: config.maxOutboundStreams ?? 1000,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"o-connection-heartbeat.manager.d.ts","sourceRoot":"","sources":["../../../src/managers/o-connection-heartbeat.manager.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,OAAO,EAOR,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,EAAE,kBAAkB,EAAE,MAAM,uCAAuC,CAAC;AAE3E,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,gBAAgB,EAAE,MAAM,CAAC;IACzB,aAAa,EAAE,OAAO,CAAC;IACvB,WAAW,EAAE,OAAO,CAAC;IACrB,WAAW,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,YAAY,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,kBAAkB,EAAE,MAAM,CAAC;IAC3B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,SAAS,GAAG,UAAU,GAAG,MAAM,CAAC;CACzC;AAED;;;;;;;;;;;;;;GAcG;AACH,qBAAa,2BAA4B,SAAQ,OAAO;IAMpD,OAAO,CAAC,IAAI;IACZ,OAAO,CAAC,MAAM;IANhB,OAAO,CAAC,iBAAiB,CAAC,CAAiB;IAC3C,OAAO,CAAC,SAAS,CAAuC;IACxD,OAAO,CAAC,SAAS,CAAS;gBAGhB,IAAI,EAAE,kBAAkB,EACxB,MAAM,EAAE,eAAe;IAK3B,KAAK;IAqBL,IAAI;YAQI,uBAAuB;IAgDrC;;;OAGG;IACH,OAAO,CAAC,qBAAqB;
|
|
1
|
+
{"version":3,"file":"o-connection-heartbeat.manager.d.ts","sourceRoot":"","sources":["../../../src/managers/o-connection-heartbeat.manager.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,OAAO,EAOR,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,EAAE,kBAAkB,EAAE,MAAM,uCAAuC,CAAC;AAE3E,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,gBAAgB,EAAE,MAAM,CAAC;IACzB,aAAa,EAAE,OAAO,CAAC;IACvB,WAAW,EAAE,OAAO,CAAC;IACrB,WAAW,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,YAAY,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,kBAAkB,EAAE,MAAM,CAAC;IAC3B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,SAAS,GAAG,UAAU,GAAG,MAAM,CAAC;CACzC;AAED;;;;;;;;;;;;;;GAcG;AACH,qBAAa,2BAA4B,SAAQ,OAAO;IAMpD,OAAO,CAAC,IAAI;IACZ,OAAO,CAAC,MAAM;IANhB,OAAO,CAAC,iBAAiB,CAAC,CAAiB;IAC3C,OAAO,CAAC,SAAS,CAAuC;IACxD,OAAO,CAAC,SAAS,CAAS;gBAGhB,IAAI,EAAE,kBAAkB,EACxB,MAAM,EAAE,eAAe;IAK3B,KAAK;IAqBL,IAAI;YAQI,uBAAuB;IAgDrC;;;OAGG;IACH,OAAO,CAAC,qBAAqB;YA8Cf,WAAW;IAoEzB,OAAO,CAAC,oBAAoB;IAyD5B,OAAO,CAAC,2BAA2B;IAmBnC,OAAO,CAAC,4BAA4B;IAiBpC;;OAEG;IACH,eAAe,IAAI,gBAAgB,EAAE;IAIrC;;OAEG;IACH,mBAAmB,CAAC,OAAO,EAAE,YAAY,GAAG,gBAAgB,GAAG,SAAS;IAIxE;;OAEG;IACH,SAAS,IAAI,eAAe;CAG7B"}
|
|
@@ -95,7 +95,21 @@ export class oConnectionHeartbeatManager extends oObject {
|
|
|
95
95
|
// Note: Using 'as any' since converting to proper PeerId breaks browser implementation
|
|
96
96
|
const connections = this.node.p2pNode.getConnections(peerIdString);
|
|
97
97
|
// Check if any connection is open
|
|
98
|
-
|
|
98
|
+
const existing = connections.some((conn) => conn.status === 'open');
|
|
99
|
+
if (existing) {
|
|
100
|
+
return true;
|
|
101
|
+
}
|
|
102
|
+
// check via ping
|
|
103
|
+
const pingResponse = this.node.use(address, {
|
|
104
|
+
method: 'ping'
|
|
105
|
+
}).catch((err) => {
|
|
106
|
+
if (err.message === 'Can not dial self') {
|
|
107
|
+
return true;
|
|
108
|
+
}
|
|
109
|
+
this.logger.warn('Could not reach address in heartbeat:' + address.value, err);
|
|
110
|
+
return null;
|
|
111
|
+
});
|
|
112
|
+
return !!pingResponse;
|
|
99
113
|
}
|
|
100
114
|
catch (error) {
|
|
101
115
|
this.logger.debug(`Error checking connection status for ${address}`, error);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"o-reconnection.manager.d.ts","sourceRoot":"","sources":["../../../src/managers/o-reconnection.manager.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,OAAO,EASR,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,kBAAkB,EAAE,MAAM,uCAAuC,CAAC;AAI3E,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,iBAAiB,EAAE,OAAO,CAAC;IAC3B,yBAAyB,EAAE,MAAM,CAAC;IAClC,yBAAyB,EAAE,MAAM,CAAC;CACnC;AAED;;;;;;;;;;;GAWG;AACH,qBAAa,oBAAqB,SAAQ,OAAO;IAI7C,OAAO,CAAC,IAAI;IACZ,OAAO,CAAC,MAAM;IAJhB,OAAO,CAAC,YAAY,CAAS;gBAGnB,IAAI,EAAE,kBAAkB,EACxB,MAAM,EAAE,kBAAkB;IAMpC,OAAO,CAAC,mBAAmB;IAyBrB,mBAAmB,CAAC,KAAK,EAAE,GAAG;YAatB,wBAAwB;YAaxB,wBAAwB;YAexB,wBAAwB;IAehC,mBAAmB;YAgDX,2BAA2B;YAiB3B,iBAAiB;IAkB/B;;;OAGG;YACW,yBAAyB;IAiFvC;;OAEG;IACG,yBAAyB;
|
|
1
|
+
{"version":3,"file":"o-reconnection.manager.d.ts","sourceRoot":"","sources":["../../../src/managers/o-reconnection.manager.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,OAAO,EASR,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,kBAAkB,EAAE,MAAM,uCAAuC,CAAC;AAI3E,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,iBAAiB,EAAE,OAAO,CAAC;IAC3B,yBAAyB,EAAE,MAAM,CAAC;IAClC,yBAAyB,EAAE,MAAM,CAAC;CACnC;AAED;;;;;;;;;;;GAWG;AACH,qBAAa,oBAAqB,SAAQ,OAAO;IAI7C,OAAO,CAAC,IAAI;IACZ,OAAO,CAAC,MAAM;IAJhB,OAAO,CAAC,YAAY,CAAS;gBAGnB,IAAI,EAAE,kBAAkB,EACxB,MAAM,EAAE,kBAAkB;IAMpC,OAAO,CAAC,mBAAmB;IAyBrB,mBAAmB,CAAC,KAAK,EAAE,GAAG;YAatB,wBAAwB;YAaxB,wBAAwB;YAexB,wBAAwB;IAehC,mBAAmB;YAgDX,2BAA2B;YAiB3B,iBAAiB;IAkB/B;;;OAGG;YACW,yBAAyB;IAiFvC;;OAEG;IACG,yBAAyB;IAwG/B,OAAO,CAAC,yBAAyB;IAajC,OAAO,CAAC,kBAAkB;IAI1B,OAAO,CAAC,qBAAqB;IAK7B,OAAO,CAAC,KAAK;CAGd"}
|
|
@@ -189,6 +189,9 @@ export class oReconnectionManager extends oObject {
|
|
|
189
189
|
const startTime = Date.now();
|
|
190
190
|
let attempt = 0;
|
|
191
191
|
let currentDelay = this.config.parentDiscoveryIntervalMs;
|
|
192
|
+
if (!this.node.config.leader) {
|
|
193
|
+
throw new Error('Cannot connect to parent without leader');
|
|
194
|
+
}
|
|
192
195
|
// Infinite retry loop - keep trying until parent is found
|
|
193
196
|
while (true) {
|
|
194
197
|
attempt++;
|
|
@@ -196,18 +199,20 @@ export class oReconnectionManager extends oObject {
|
|
|
196
199
|
this.logger.info(`Parent discovery attempt ${attempt} (elapsed: ${elapsedMinutes}m)`);
|
|
197
200
|
try {
|
|
198
201
|
// Query registry for parent by its known address
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
202
|
+
if (!this.node.config.parent) {
|
|
203
|
+
throw new Error('Invalid parent definition');
|
|
204
|
+
}
|
|
205
|
+
const response = await this.node.use(this.node.config.parent, {
|
|
206
|
+
method: 'identify',
|
|
207
|
+
params: {},
|
|
204
208
|
});
|
|
205
|
-
|
|
209
|
+
this.logger.debug('Identify parent response:', response.result.data);
|
|
210
|
+
const { address: parentAddress, transports: parentTransports } = response.result.data;
|
|
206
211
|
// Check if parent was found in registry
|
|
207
212
|
if (parentAddress && parentTransports && parentTransports.length > 0) {
|
|
208
213
|
this.logger.info(`Parent found in registry: ${parentAddress} with ${parentTransports.length} transports`);
|
|
209
214
|
// Update parent reference with fresh transports
|
|
210
|
-
this.node.config.parent = new oNodeAddress(parentAddress, parentTransports.map((
|
|
215
|
+
this.node.config.parent = new oNodeAddress(parentAddress, parentTransports.map((value) => new oNodeTransport(value)));
|
|
211
216
|
// Attempt to register with parent and re-register with registry
|
|
212
217
|
try {
|
|
213
218
|
await this.tryDirectParentReconnection();
|
package/dist/src/o-node.d.ts
CHANGED
|
@@ -54,6 +54,11 @@ export declare class oNode extends oToolBase {
|
|
|
54
54
|
* Override use() to wrap leader/registry requests with retry logic
|
|
55
55
|
*/
|
|
56
56
|
teardown(): Promise<void>;
|
|
57
|
+
/**
|
|
58
|
+
* Reset node state to allow restart after stop
|
|
59
|
+
* Called at the end of teardown()
|
|
60
|
+
*/
|
|
61
|
+
protected resetState(): void;
|
|
57
62
|
getLeaders(): oNodeAddress[];
|
|
58
63
|
getParents(): oNodeAddress[];
|
|
59
64
|
getChildren(): oNodeAddress[];
|
package/dist/src/o-node.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"o-node.d.ts","sourceRoot":"","sources":["../../src/o-node.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,MAAM,EACN,YAAY,EAEb,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAEzC,OAAO,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AACtE,OAAO,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AAC5D,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAC9D,OAAO,EAKL,QAAQ,EAER,oBAAoB,EAGrB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC1D,OAAO,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC;AACpE,OAAO,EAAE,sBAAsB,EAAE,MAAM,2CAA2C,CAAC;AAEnF,OAAO,EAAmB,SAAS,EAAE,MAAM,eAAe,CAAC;AAG3D,OAAO,EAAE,2BAA2B,EAAE,MAAM,8CAA8C,CAAC;AAC3F,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EAAE,oBAAoB,EAAE,MAAM,sCAAsC,CAAC;AAE5E,qBAAa,KAAM,SAAQ,SAAS;IAC3B,MAAM,EAAG,MAAM,CAAC;IAChB,OAAO,EAAG,MAAM,CAAC;IACjB,OAAO,EAAG,YAAY,CAAC;IACvB,MAAM,EAAE,WAAW,CAAC;IACpB,iBAAiB,EAAG,sBAAsB,CAAC;IAC3C,gBAAgB,EAAG,qBAAqB,CAAC;IACzC,0BAA0B,CAAC,EAAE,2BAA2B,CAAC;IAChE,SAAS,CAAC,mBAAmB,CAAC,EAAE,oBAAoB,CAAC;IACrD,SAAS,CAAC,WAAW,EAAE,OAAO,CAAS;gBAE3B,MAAM,EAAE,WAAW;IAK/B,IAAI,MAAM,IAAI,YAAY,GAAG,IAAI,CAEhC;IAED,IAAI,aAAa,IAAI,YAAY,CAKhC;IAED,IAAI,YAAY,IAAI,MAAM,GAAG,IAAI,CAOhC;IAED,mBAAmB,IAAI,GAAG,EAAE;IAItB,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC;IASvC,SAAS,CAAC,yBAAyB,IAAI,oBAAoB;IAQ3D,IAAI,aAAa,IAAI,YAAY,CAEhC;IAED,IAAI,gBAAgB,IAAI,cAAc,EAAE,CAEvC;IAED,IAAI,UAAU,IAAI,cAAc,EAAE,CAIjC;IAEK,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAwD3B,eAAe,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAoCrD,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"o-node.d.ts","sourceRoot":"","sources":["../../src/o-node.ts"],"names":[],"mappings":"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"}
|
package/dist/src/o-node.js
CHANGED
|
@@ -135,6 +135,10 @@ export class oNode extends oToolBase {
|
|
|
135
135
|
this.logger.debug('Skipping parent registration, node is leader');
|
|
136
136
|
return;
|
|
137
137
|
}
|
|
138
|
+
if (!this.parent) {
|
|
139
|
+
this.logger.warn('no parent, skipping registration');
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
138
142
|
if (!this.parent?.libp2pTransports?.length) {
|
|
139
143
|
this.logger.debug('Parent has no transports, waiting for reconnection & leader ack');
|
|
140
144
|
if (this.parent?.toString() === oAddress.leader().toString()) {
|
|
@@ -149,7 +153,8 @@ export class oNode extends oToolBase {
|
|
|
149
153
|
// TODO: should we remove the transports check to make this more consistent?
|
|
150
154
|
if (this.config.parent) {
|
|
151
155
|
this.logger.debug('Registering node with parent...', this.config.parent?.toString());
|
|
152
|
-
|
|
156
|
+
// avoid transports to ensure we do not try direct connection, we need to route via the leader for proper access controls
|
|
157
|
+
await this.use(new oNodeAddress(this.config.parent.value), {
|
|
153
158
|
method: 'child_register',
|
|
154
159
|
params: {
|
|
155
160
|
address: this.address.toString(),
|
|
@@ -162,6 +167,11 @@ export class oNode extends oToolBase {
|
|
|
162
167
|
}
|
|
163
168
|
}
|
|
164
169
|
async registerLeader() {
|
|
170
|
+
this.logger.info('Register leader called...');
|
|
171
|
+
if (!this.leader) {
|
|
172
|
+
this.logger.warn('No leader defined, skipping registration');
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
165
175
|
const address = oAddress.registry();
|
|
166
176
|
const params = {
|
|
167
177
|
method: 'commit',
|
|
@@ -187,6 +197,7 @@ export class oNode extends oToolBase {
|
|
|
187
197
|
}
|
|
188
198
|
this.didRegister = true;
|
|
189
199
|
this.logger.debug('Registering node...');
|
|
200
|
+
await this.registerParent();
|
|
190
201
|
// register with the leader global registry
|
|
191
202
|
if (!this.config.leader) {
|
|
192
203
|
this.logger.warn('No leaders found, skipping registration');
|
|
@@ -195,7 +206,6 @@ export class oNode extends oToolBase {
|
|
|
195
206
|
else {
|
|
196
207
|
this.logger.debug('Registering node with leader...');
|
|
197
208
|
}
|
|
198
|
-
await this.registerParent();
|
|
199
209
|
await this.registerLeader();
|
|
200
210
|
this.logger.debug('Registration successful');
|
|
201
211
|
}
|
|
@@ -290,7 +300,6 @@ export class oNode extends oToolBase {
|
|
|
290
300
|
if (this.config.type === NodeType.LEADER) {
|
|
291
301
|
return false;
|
|
292
302
|
}
|
|
293
|
-
// deny everything else
|
|
294
303
|
return true;
|
|
295
304
|
},
|
|
296
305
|
// allow the user to override the default connection gater
|
|
@@ -305,9 +314,8 @@ export class oNode extends oToolBase {
|
|
|
305
314
|
maxParallelReconnects: 10,
|
|
306
315
|
};
|
|
307
316
|
// handle the address encapsulation
|
|
308
|
-
if (this.config.
|
|
309
|
-
|
|
310
|
-
const parentAddress = this.config.parent || this.config.leader;
|
|
317
|
+
if (this.config.parent) {
|
|
318
|
+
const parentAddress = this.config.parent;
|
|
311
319
|
this.address = CoreUtils.childAddress(parentAddress, this.address);
|
|
312
320
|
}
|
|
313
321
|
return params;
|
|
@@ -342,6 +350,7 @@ export class oNode extends oToolBase {
|
|
|
342
350
|
defaultReadTimeoutMs: this.config.connectionTimeouts?.readTimeoutMs,
|
|
343
351
|
defaultDrainTimeoutMs: this.config.connectionTimeouts?.drainTimeoutMs,
|
|
344
352
|
runOnLimitedConnection: this.config.runOnLimitedConnection ?? false,
|
|
353
|
+
originAddress: this.address?.value
|
|
345
354
|
});
|
|
346
355
|
}
|
|
347
356
|
async hookInitializeFinished() { }
|
|
@@ -360,7 +369,7 @@ export class oNode extends oToolBase {
|
|
|
360
369
|
}
|
|
361
370
|
async initialize() {
|
|
362
371
|
this.logger.debug('Initializing node...');
|
|
363
|
-
if (this.
|
|
372
|
+
if (this.state !== NodeState.STOPPED && this.state !== NodeState.STARTING) {
|
|
364
373
|
throw new Error('Node is not in a valid state to be initialized');
|
|
365
374
|
}
|
|
366
375
|
if (!this.address.validate()) {
|
|
@@ -379,7 +388,7 @@ export class oNode extends oToolBase {
|
|
|
379
388
|
this.router.addResolver(new oMethodResolver(this.address));
|
|
380
389
|
this.router.addResolver(new oNodeResolver(this.address));
|
|
381
390
|
// setup a fallback resolver for non-leader nodes
|
|
382
|
-
if (this.isLeader === false) {
|
|
391
|
+
if (this.isLeader === false && !!this.leader) {
|
|
383
392
|
this.logger.debug('Adding leader resolver fallback...');
|
|
384
393
|
this.router.addResolver(new oLeaderResolverFallback(this.address));
|
|
385
394
|
}
|
|
@@ -421,6 +430,35 @@ export class oNode extends oToolBase {
|
|
|
421
430
|
if (this.p2pNode) {
|
|
422
431
|
await this.p2pNode.stop();
|
|
423
432
|
}
|
|
433
|
+
// Reset state to allow restart
|
|
434
|
+
this.resetState();
|
|
435
|
+
}
|
|
436
|
+
/**
|
|
437
|
+
* Reset node state to allow restart after stop
|
|
438
|
+
* Called at the end of teardown()
|
|
439
|
+
*/
|
|
440
|
+
resetState() {
|
|
441
|
+
// Reset registration flag
|
|
442
|
+
this.didRegister = false;
|
|
443
|
+
// Clear peer references
|
|
444
|
+
this.peerId = undefined;
|
|
445
|
+
this.p2pNode = undefined;
|
|
446
|
+
// Clear managers
|
|
447
|
+
this.connectionManager = undefined;
|
|
448
|
+
this.connectionHeartbeatManager = undefined;
|
|
449
|
+
this.reconnectionManager = undefined;
|
|
450
|
+
// Reset address to staticAddress with no transports
|
|
451
|
+
this.address = new oNodeAddress(this.staticAddress.value, []);
|
|
452
|
+
// Reset hierarchy manager
|
|
453
|
+
this.hierarchyManager = new oNodeHierarchyManager({
|
|
454
|
+
leaders: this.config.leader ? [this.config.leader] : [],
|
|
455
|
+
parents: this.config.parent ? [this.config.parent] : [],
|
|
456
|
+
children: [],
|
|
457
|
+
});
|
|
458
|
+
// Clear router (will be recreated in initialize)
|
|
459
|
+
this.router = undefined;
|
|
460
|
+
// Call parent reset
|
|
461
|
+
super.resetState();
|
|
424
462
|
}
|
|
425
463
|
// IHeartbeatableNode interface methods
|
|
426
464
|
getLeaders() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"o-node.tool.d.ts","sourceRoot":"","sources":["../../src/o-node.tool.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EACR,QAAQ,EAET,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;;AAKrD;;;;GAIG;AACH,qBAAa,SAAU,SAAQ,cAAkB;IAC/C,OAAO,CAAC,aAAa,CAAiB;IAEhC,cAAc,CAAC,OAAO,EAAE,QAAQ;
|
|
1
|
+
{"version":3,"file":"o-node.tool.d.ts","sourceRoot":"","sources":["../../src/o-node.tool.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EACR,QAAQ,EAET,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;;AAKrD;;;;GAIG;AACH,qBAAa,SAAU,SAAQ,cAAkB;IAC/C,OAAO,CAAC,aAAa,CAAiB;IAEhC,cAAc,CAAC,OAAO,EAAE,QAAQ;IAehC,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAY3B,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IA0BnE,cAAc,IAAI,OAAO,CAAC,GAAG,CAAC;IAQ9B,oBAAoB,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC;CA2B5D"}
|