@peerbit/shared-log 13.0.4 → 13.0.5-5d63b4f
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/index.d.ts +1 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +86 -93
- package/dist/src/index.js.map +1 -1
- package/package.json +20 -20
- package/src/index.ts +94 -93
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@peerbit/shared-log",
|
|
3
|
-
"version": "13.0.
|
|
3
|
+
"version": "13.0.5-5d63b4f",
|
|
4
4
|
"description": "Shared log",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"type": "module",
|
|
@@ -54,35 +54,35 @@
|
|
|
54
54
|
"dependencies": {
|
|
55
55
|
"@dao-xyz/borsh": "^6.0.0",
|
|
56
56
|
"@libp2p/crypto": "^5.1.10",
|
|
57
|
+
"@peerbit/log": "6.0.4-5d63b4f",
|
|
58
|
+
"@peerbit/logger": "2.0.0-5d63b4f",
|
|
59
|
+
"@peerbit/program": "6.0.2-5d63b4f",
|
|
60
|
+
"@peerbit/riblt": "1.2.0-5d63b4f",
|
|
61
|
+
"@peerbit/rpc": "6.0.4-5d63b4f",
|
|
62
|
+
"@peerbit/any-store": "2.2.5-5d63b4f",
|
|
63
|
+
"@peerbit/blocks": "4.0.1-5d63b4f",
|
|
64
|
+
"@peerbit/blocks-interface": "2.0.1-5d63b4f",
|
|
65
|
+
"@peerbit/cache": "3.0.0-5d63b4f",
|
|
66
|
+
"@peerbit/crypto": "3.0.0-5d63b4f",
|
|
67
|
+
"@peerbit/indexer-interface": "3.0.0-5d63b4f",
|
|
68
|
+
"@peerbit/indexer-sqlite3": "3.0.0-5d63b4f",
|
|
69
|
+
"@peerbit/pubsub": "5.0.2-5d63b4f",
|
|
70
|
+
"@peerbit/pubsub-interface": "5.0.1-5d63b4f",
|
|
71
|
+
"@peerbit/stream-interface": "6.0.1-5d63b4f",
|
|
72
|
+
"@peerbit/time": "3.0.0-5d63b4f",
|
|
57
73
|
"json-stringify-deterministic": "^1.0.7",
|
|
58
74
|
"p-each-series": "^3.0.0",
|
|
59
75
|
"p-defer": "^4.0.0",
|
|
60
76
|
"p-queue": "^8.0.1",
|
|
61
77
|
"pidusage": "^4.0.1",
|
|
62
78
|
"pino": "^9.4.0",
|
|
63
|
-
"uint8arrays": "^5.1.0"
|
|
64
|
-
"@peerbit/log": "6.0.3",
|
|
65
|
-
"@peerbit/logger": "2.0.0",
|
|
66
|
-
"@peerbit/program": "6.0.1",
|
|
67
|
-
"@peerbit/riblt": "1.2.0",
|
|
68
|
-
"@peerbit/rpc": "6.0.3",
|
|
69
|
-
"@peerbit/any-store": "2.2.5",
|
|
70
|
-
"@peerbit/blocks-interface": "2.0.0",
|
|
71
|
-
"@peerbit/blocks": "4.0.0",
|
|
72
|
-
"@peerbit/cache": "3.0.0",
|
|
73
|
-
"@peerbit/crypto": "3.0.0",
|
|
74
|
-
"@peerbit/indexer-interface": "3.0.0",
|
|
75
|
-
"@peerbit/indexer-sqlite3": "3.0.0",
|
|
76
|
-
"@peerbit/pubsub": "5.0.1",
|
|
77
|
-
"@peerbit/stream-interface": "6.0.0",
|
|
78
|
-
"@peerbit/pubsub-interface": "5.0.0",
|
|
79
|
-
"@peerbit/time": "3.0.0"
|
|
79
|
+
"uint8arrays": "^5.1.0"
|
|
80
80
|
},
|
|
81
81
|
"devDependencies": {
|
|
82
|
+
"@peerbit/test-utils": "3.0.4-5d63b4f",
|
|
82
83
|
"@types/libsodium-wrappers": "^0.7.14",
|
|
83
84
|
"@types/pidusage": "^2.0.5",
|
|
84
|
-
"uuid": "^10.0.0"
|
|
85
|
-
"@peerbit/test-utils": "3.0.3"
|
|
85
|
+
"uuid": "^10.0.0"
|
|
86
86
|
},
|
|
87
87
|
"scripts": {
|
|
88
88
|
"clean": "aegir clean",
|
package/src/index.ts
CHANGED
|
@@ -50,6 +50,7 @@ import { RPC, type RequestContext } from "@peerbit/rpc";
|
|
|
50
50
|
import {
|
|
51
51
|
AcknowledgeDelivery,
|
|
52
52
|
AnyWhere,
|
|
53
|
+
createRequestTransportContext,
|
|
53
54
|
DataMessage,
|
|
54
55
|
MessageHeader,
|
|
55
56
|
NotStartedError,
|
|
@@ -868,6 +869,7 @@ export class SharedLog<
|
|
|
868
869
|
await this.onMessage(message, {
|
|
869
870
|
from,
|
|
870
871
|
message: contextMessage,
|
|
872
|
+
transport: createRequestTransportContext(contextMessage),
|
|
871
873
|
});
|
|
872
874
|
}
|
|
873
875
|
|
|
@@ -899,6 +901,7 @@ export class SharedLog<
|
|
|
899
901
|
await this.onMessage(message, {
|
|
900
902
|
from,
|
|
901
903
|
message: contextMessage,
|
|
904
|
+
transport: createRequestTransportContext(contextMessage),
|
|
902
905
|
});
|
|
903
906
|
}
|
|
904
907
|
|
|
@@ -2884,17 +2887,14 @@ export class SharedLog<
|
|
|
2884
2887
|
// ignore discovery failures
|
|
2885
2888
|
}
|
|
2886
2889
|
|
|
2887
|
-
// 2)
|
|
2888
|
-
|
|
2889
|
-
|
|
2890
|
-
|
|
2891
|
-
|
|
2892
|
-
|
|
2893
|
-
|
|
2894
|
-
|
|
2895
|
-
if (out.length >= 32) break;
|
|
2896
|
-
}
|
|
2897
|
-
return out;
|
|
2890
|
+
// 2) reuse the same per-hash / replicator / subscriber fallback used by
|
|
2891
|
+
// entry loads so block retries can widen beyond stale explicit hints.
|
|
2892
|
+
return (
|
|
2893
|
+
(await this.resolveCandidatePeersForHash(cid, {
|
|
2894
|
+
signal: opts?.signal,
|
|
2895
|
+
maxPeers: 8,
|
|
2896
|
+
})) ?? []
|
|
2897
|
+
);
|
|
2898
2898
|
},
|
|
2899
2899
|
onPut: async (cid) => {
|
|
2900
2900
|
// Best-effort directory announce for "get without remote.from" workflows.
|
|
@@ -3021,87 +3021,11 @@ export class SharedLog<
|
|
|
3021
3021
|
|
|
3022
3022
|
await this.log.open(this.remoteBlocks, this.node.identity, {
|
|
3023
3023
|
keychain: this.node.services.keychain,
|
|
3024
|
-
resolveRemotePeers:
|
|
3025
|
-
|
|
3026
|
-
|
|
3027
|
-
|
|
3028
|
-
|
|
3029
|
-
const seed = hashToSeed32(hash);
|
|
3030
|
-
|
|
3031
|
-
// Best hint: peers that have recently confirmed having this entry hash.
|
|
3032
|
-
const hinted = this._requestIPruneResponseReplicatorSet.get(hash);
|
|
3033
|
-
if (hinted && hinted.size > 0) {
|
|
3034
|
-
const peers = [...hinted].filter((p) => p !== self);
|
|
3035
|
-
return peers.length > 0
|
|
3036
|
-
? pickDeterministicSubset(peers, seed, maxPeers)
|
|
3037
|
-
: undefined;
|
|
3038
|
-
}
|
|
3039
|
-
|
|
3040
|
-
// Next: peers we already contacted about this hash (may still have it).
|
|
3041
|
-
const contacted = this._requestIPruneSent.get(hash);
|
|
3042
|
-
if (contacted && contacted.size > 0) {
|
|
3043
|
-
const peers = [...contacted].filter((p) => p !== self);
|
|
3044
|
-
return peers.length > 0
|
|
3045
|
-
? pickDeterministicSubset(peers, seed, maxPeers)
|
|
3046
|
-
: undefined;
|
|
3047
|
-
}
|
|
3048
|
-
|
|
3049
|
-
let candidates: string[] | undefined;
|
|
3050
|
-
|
|
3051
|
-
// Prefer the replicator cache; fall back to subscribers if we have no other signal.
|
|
3052
|
-
const replicatorCandidates = [...this.uniqueReplicators].filter(
|
|
3053
|
-
(p) => p !== self,
|
|
3054
|
-
);
|
|
3055
|
-
if (replicatorCandidates.length > 0) {
|
|
3056
|
-
candidates = replicatorCandidates;
|
|
3057
|
-
} else {
|
|
3058
|
-
try {
|
|
3059
|
-
const subscribers = await this._getTopicSubscribers(this.topic);
|
|
3060
|
-
const subscriberCandidates =
|
|
3061
|
-
subscribers?.map((k) => k.hashcode()).filter((p) => p !== self) ??
|
|
3062
|
-
[];
|
|
3063
|
-
candidates =
|
|
3064
|
-
subscriberCandidates.length > 0 ? subscriberCandidates : undefined;
|
|
3065
|
-
} catch {
|
|
3066
|
-
// Best-effort only.
|
|
3067
|
-
}
|
|
3068
|
-
|
|
3069
|
-
if (!candidates || candidates.length === 0) {
|
|
3070
|
-
// Last resort: peers we are already directly connected to. This avoids
|
|
3071
|
-
// depending on global membership knowledge in early-join scenarios.
|
|
3072
|
-
const peerMap = (this.node.services.pubsub as any)?.peers;
|
|
3073
|
-
if (peerMap?.keys) {
|
|
3074
|
-
candidates = [...peerMap.keys()];
|
|
3075
|
-
}
|
|
3076
|
-
}
|
|
3077
|
-
|
|
3078
|
-
if (!candidates || candidates.length === 0) {
|
|
3079
|
-
// Even if the pubsub stream has no established peer streams yet, we may
|
|
3080
|
-
// still have a libp2p connection to one or more peers (e.g. bootstrap).
|
|
3081
|
-
const connectionManager = (this.node.services.pubsub as any)?.components
|
|
3082
|
-
?.connectionManager;
|
|
3083
|
-
const connections = connectionManager?.getConnections?.() ?? [];
|
|
3084
|
-
const connectionHashes: string[] = [];
|
|
3085
|
-
for (const conn of connections) {
|
|
3086
|
-
const peerId = conn?.remotePeer;
|
|
3087
|
-
if (!peerId) continue;
|
|
3088
|
-
try {
|
|
3089
|
-
connectionHashes.push(getPublicKeyFromPeerId(peerId).hashcode());
|
|
3090
|
-
} catch {
|
|
3091
|
-
// Best-effort only.
|
|
3092
|
-
}
|
|
3093
|
-
}
|
|
3094
|
-
if (connectionHashes.length > 0) {
|
|
3095
|
-
candidates = connectionHashes;
|
|
3096
|
-
}
|
|
3097
|
-
}
|
|
3098
|
-
}
|
|
3099
|
-
|
|
3100
|
-
if (!candidates || candidates.length === 0) return undefined;
|
|
3101
|
-
const peers = candidates.filter((p) => p !== self);
|
|
3102
|
-
if (peers.length === 0) return undefined;
|
|
3103
|
-
return pickDeterministicSubset(peers, seed, maxPeers);
|
|
3104
|
-
},
|
|
3024
|
+
resolveRemotePeers: (hash, options) =>
|
|
3025
|
+
this.resolveCandidatePeersForHash(hash, {
|
|
3026
|
+
signal: options?.signal,
|
|
3027
|
+
maxPeers: 8,
|
|
3028
|
+
}),
|
|
3105
3029
|
...this._logProperties,
|
|
3106
3030
|
onChange: async (change) => {
|
|
3107
3031
|
await this.onChange(change);
|
|
@@ -3489,6 +3413,80 @@ export class SharedLog<
|
|
|
3489
3413
|
this._replicatorLivenessTargetsSize = -1;
|
|
3490
3414
|
}
|
|
3491
3415
|
|
|
3416
|
+
private async resolveCandidatePeersForHash(
|
|
3417
|
+
hash: string,
|
|
3418
|
+
options?: { signal?: AbortSignal; maxPeers?: number },
|
|
3419
|
+
): Promise<string[] | undefined> {
|
|
3420
|
+
if (options?.signal?.aborted) return undefined;
|
|
3421
|
+
|
|
3422
|
+
const maxPeers = options?.maxPeers ?? 8;
|
|
3423
|
+
const self = this.node.identity.publicKey.hashcode();
|
|
3424
|
+
const seed = hashToSeed32(hash);
|
|
3425
|
+
|
|
3426
|
+
const hinted = this._requestIPruneResponseReplicatorSet.get(hash);
|
|
3427
|
+
if (hinted && hinted.size > 0) {
|
|
3428
|
+
const peers = [...hinted].filter((p) => p !== self);
|
|
3429
|
+
return peers.length > 0
|
|
3430
|
+
? pickDeterministicSubset(peers, seed, maxPeers)
|
|
3431
|
+
: undefined;
|
|
3432
|
+
}
|
|
3433
|
+
|
|
3434
|
+
const contacted = this._requestIPruneSent.get(hash);
|
|
3435
|
+
if (contacted && contacted.size > 0) {
|
|
3436
|
+
const peers = [...contacted].filter((p) => p !== self);
|
|
3437
|
+
return peers.length > 0
|
|
3438
|
+
? pickDeterministicSubset(peers, seed, maxPeers)
|
|
3439
|
+
: undefined;
|
|
3440
|
+
}
|
|
3441
|
+
|
|
3442
|
+
let candidates: string[] | undefined;
|
|
3443
|
+
const replicatorCandidates = [...this.uniqueReplicators].filter((p) => p !== self);
|
|
3444
|
+
if (replicatorCandidates.length > 0) {
|
|
3445
|
+
candidates = replicatorCandidates;
|
|
3446
|
+
} else {
|
|
3447
|
+
try {
|
|
3448
|
+
const subscribers = await this._getTopicSubscribers(this.topic);
|
|
3449
|
+
const subscriberCandidates =
|
|
3450
|
+
subscribers?.map((k) => k.hashcode()).filter((p) => p !== self) ?? [];
|
|
3451
|
+
candidates =
|
|
3452
|
+
subscriberCandidates.length > 0 ? subscriberCandidates : undefined;
|
|
3453
|
+
} catch {
|
|
3454
|
+
// Best-effort only.
|
|
3455
|
+
}
|
|
3456
|
+
|
|
3457
|
+
if (!candidates || candidates.length === 0) {
|
|
3458
|
+
const peerMap = (this.node.services.pubsub as any)?.peers;
|
|
3459
|
+
if (peerMap?.keys) {
|
|
3460
|
+
candidates = [...peerMap.keys()];
|
|
3461
|
+
}
|
|
3462
|
+
}
|
|
3463
|
+
|
|
3464
|
+
if (!candidates || candidates.length === 0) {
|
|
3465
|
+
const connectionManager = (this.node.services.pubsub as any)?.components
|
|
3466
|
+
?.connectionManager;
|
|
3467
|
+
const connections = connectionManager?.getConnections?.() ?? [];
|
|
3468
|
+
const connectionHashes: string[] = [];
|
|
3469
|
+
for (const conn of connections) {
|
|
3470
|
+
const peerId = conn?.remotePeer;
|
|
3471
|
+
if (!peerId) continue;
|
|
3472
|
+
try {
|
|
3473
|
+
connectionHashes.push(getPublicKeyFromPeerId(peerId).hashcode());
|
|
3474
|
+
} catch {
|
|
3475
|
+
// Best-effort only.
|
|
3476
|
+
}
|
|
3477
|
+
}
|
|
3478
|
+
if (connectionHashes.length > 0) {
|
|
3479
|
+
candidates = connectionHashes;
|
|
3480
|
+
}
|
|
3481
|
+
}
|
|
3482
|
+
}
|
|
3483
|
+
|
|
3484
|
+
if (!candidates || candidates.length === 0) return undefined;
|
|
3485
|
+
const peers = candidates.filter((p) => p !== self);
|
|
3486
|
+
if (peers.length === 0) return undefined;
|
|
3487
|
+
return pickDeterministicSubset(peers, seed, maxPeers);
|
|
3488
|
+
}
|
|
3489
|
+
|
|
3492
3490
|
private async runReplicatorLivenessSweep() {
|
|
3493
3491
|
if (this.closed || this._closeController.signal.aborted) {
|
|
3494
3492
|
return;
|
|
@@ -4290,7 +4288,10 @@ export class SharedLog<
|
|
|
4290
4288
|
} else if (msg instanceof BlocksMessage) {
|
|
4291
4289
|
await this.remoteBlocks.onMessage(
|
|
4292
4290
|
msg.message,
|
|
4293
|
-
|
|
4291
|
+
{
|
|
4292
|
+
from: context.from!.hashcode(),
|
|
4293
|
+
transport: createRequestTransportContext(context.message),
|
|
4294
|
+
},
|
|
4294
4295
|
);
|
|
4295
4296
|
} else if (msg instanceof ReplicationPingMessage) {
|
|
4296
4297
|
// No-op: used as an ACKed unicast liveness probe.
|