@peerbit/shared-log 16.0.2 → 16.0.3
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/coordinate-persistence.d.ts +18 -1
- package/dist/src/coordinate-persistence.d.ts.map +1 -1
- package/dist/src/coordinate-persistence.js +61 -4
- package/dist/src/coordinate-persistence.js.map +1 -1
- package/dist/src/index.d.ts +7 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +261 -200
- package/dist/src/index.js.map +1 -1
- package/package.json +8 -8
- package/src/coordinate-persistence.ts +66 -5
- package/src/index.ts +345 -257
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@peerbit/shared-log",
|
|
3
|
-
"version": "16.0.
|
|
3
|
+
"version": "16.0.3",
|
|
4
4
|
"description": "Shared log",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"type": "module",
|
|
@@ -62,23 +62,23 @@
|
|
|
62
62
|
"pidusage": "^4.0.1",
|
|
63
63
|
"pino": "^9.4.0",
|
|
64
64
|
"uint8arrays": "^5.1.0",
|
|
65
|
+
"@peerbit/any-store": "2.2.14",
|
|
65
66
|
"@peerbit/blocks": "4.2.10",
|
|
66
|
-
"@peerbit/cache": "3.1.1",
|
|
67
67
|
"@peerbit/blocks-interface": "2.1.5",
|
|
68
|
+
"@peerbit/cache": "3.1.1",
|
|
68
69
|
"@peerbit/crypto": "3.1.5",
|
|
69
|
-
"@peerbit/any-store": "2.2.14",
|
|
70
70
|
"@peerbit/indexer-interface": "3.0.9",
|
|
71
|
+
"@peerbit/logger": "2.0.1",
|
|
71
72
|
"@peerbit/indexer-sqlite3": "3.0.14",
|
|
72
|
-
"@peerbit/log": "6.2.17",
|
|
73
73
|
"@peerbit/diagnostics": "0.0.1",
|
|
74
|
-
"@peerbit/
|
|
74
|
+
"@peerbit/log": "6.2.17",
|
|
75
75
|
"@peerbit/pubsub": "5.4.1",
|
|
76
76
|
"@peerbit/program": "6.0.49",
|
|
77
|
+
"@peerbit/pubsub-interface": "5.2.1",
|
|
77
78
|
"@peerbit/riblt": "1.2.0",
|
|
78
79
|
"@peerbit/stream-interface": "6.0.15",
|
|
79
80
|
"@peerbit/rpc": "6.1.17",
|
|
80
|
-
"@peerbit/time": "3.0.1"
|
|
81
|
-
"@peerbit/pubsub-interface": "5.2.1"
|
|
81
|
+
"@peerbit/time": "3.0.1"
|
|
82
82
|
},
|
|
83
83
|
"optionalDependencies": {
|
|
84
84
|
"@peerbit/native-backbone": "0.2.5",
|
|
@@ -88,9 +88,9 @@
|
|
|
88
88
|
"@types/libsodium-wrappers": "^0.7.14",
|
|
89
89
|
"@types/pidusage": "^2.0.5",
|
|
90
90
|
"uuid": "^11.1.1",
|
|
91
|
+
"@peerbit/any-store-rust": "0.1.4",
|
|
91
92
|
"@peerbit/indexer-rust": "1.0.7",
|
|
92
93
|
"peerbit": "5.3.23",
|
|
93
|
-
"@peerbit/any-store-rust": "0.1.4",
|
|
94
94
|
"@peerbit/test-utils": "3.1.23"
|
|
95
95
|
},
|
|
96
96
|
"repository": {
|
|
@@ -207,7 +207,20 @@ export class CoordinatePersistenceCoordinator<R extends "u32" | "u64"> {
|
|
|
207
207
|
// roll back only while that generation is still current, so a rollback
|
|
208
208
|
// superseded by a newer mutation is a strict no-op. The map deliberately
|
|
209
209
|
// survives open/close cycles of the same instance.
|
|
210
|
-
|
|
210
|
+
//
|
|
211
|
+
// Each row is hold-counted: `snapshotResidentCoordinateEntries` takes one
|
|
212
|
+
// hold per hash per token, and `settleResidentCoordinateSnapshot` releases
|
|
213
|
+
// it once the token can no longer be rolled back, deleting the row at zero
|
|
214
|
+
// holds. That bounds the map by the outstanding rollback tokens instead of
|
|
215
|
+
// by lifetime throughput. Deleting a row that still has a live token would
|
|
216
|
+
// make its rollback fail open (or, worse, ABA-clobber newer state), so
|
|
217
|
+
// eviction is refcount-driven only — never TTL, LRU or a size cap. A
|
|
218
|
+
// MISSED settle merely retains a row, which is the pre-refcount behavior
|
|
219
|
+
// and therefore never a regression.
|
|
220
|
+
_nativeCoordinateMutationGenerations?: Map<
|
|
221
|
+
string,
|
|
222
|
+
{ generation: number; holds: number }
|
|
223
|
+
>;
|
|
211
224
|
|
|
212
225
|
/**
|
|
213
226
|
* Wall-clock watermark of the last settled native coordinate journal
|
|
@@ -567,6 +580,11 @@ export class CoordinatePersistenceCoordinator<R extends "u32" | "u64"> {
|
|
|
567
580
|
} catch (error) {
|
|
568
581
|
this.rollbackBackboneOnlyReceiveCoordinateBatch(batch);
|
|
569
582
|
throw error;
|
|
583
|
+
} finally {
|
|
584
|
+
// The token cannot escape this function: both outcomes are
|
|
585
|
+
// observed here, and the catch arm has already consumed it by the
|
|
586
|
+
// time this runs.
|
|
587
|
+
this.settleResidentCoordinateSnapshot(batch.rollbackCoordinateEntries);
|
|
570
588
|
}
|
|
571
589
|
}
|
|
572
590
|
|
|
@@ -1012,8 +1030,14 @@ export class CoordinatePersistenceCoordinator<R extends "u32" | "u64"> {
|
|
|
1012
1030
|
const mutationGenerations = (this._nativeCoordinateMutationGenerations ??=
|
|
1013
1031
|
new Map());
|
|
1014
1032
|
for (const hash of uniqueHashes) {
|
|
1015
|
-
|
|
1016
|
-
|
|
1033
|
+
// `uniqueHashes` is a Set, so this is exactly one hold per token
|
|
1034
|
+
// per hash; `settleResidentCoordinateSnapshot` releases it.
|
|
1035
|
+
const row = mutationGenerations.get(hash);
|
|
1036
|
+
const generation = (row?.generation ?? 0) + 1;
|
|
1037
|
+
mutationGenerations.set(hash, {
|
|
1038
|
+
generation,
|
|
1039
|
+
holds: (row?.holds ?? 0) + 1,
|
|
1040
|
+
});
|
|
1017
1041
|
generations.set(hash, generation);
|
|
1018
1042
|
const entry = this._residentEntryCoordinatesByHash?.get(hash);
|
|
1019
1043
|
if (entry) {
|
|
@@ -1023,6 +1047,43 @@ export class CoordinatePersistenceCoordinator<R extends "u32" | "u64"> {
|
|
|
1023
1047
|
return { hashes: uniqueHashes, entries, generations };
|
|
1024
1048
|
}
|
|
1025
1049
|
|
|
1050
|
+
/**
|
|
1051
|
+
* Release the holds a rollback token took on the mutation-generation map.
|
|
1052
|
+
*
|
|
1053
|
+
* Call this only where the token is TERMINAL — after the last point at
|
|
1054
|
+
* which any code path could still roll it back. A premature settle deletes
|
|
1055
|
+
* a row that a live token still needs, which silently turns that token's
|
|
1056
|
+
* rollback into a no-op (phantom coordinates) or, if the hash cycles back
|
|
1057
|
+
* to the same generation, lets it clobber newer state. A missed settle
|
|
1058
|
+
* only retains the row, which is the pre-refcount behavior.
|
|
1059
|
+
*
|
|
1060
|
+
* Idempotent by design: `settled` is set FIRST so a second settle of the
|
|
1061
|
+
* same token cannot consume another token's hold on a shared hash.
|
|
1062
|
+
*/
|
|
1063
|
+
settleResidentCoordinateSnapshot(
|
|
1064
|
+
rollback?: NativeBackboneCoordinateRollback<R>,
|
|
1065
|
+
): void {
|
|
1066
|
+
if (!rollback || rollback.settled) {
|
|
1067
|
+
return;
|
|
1068
|
+
}
|
|
1069
|
+
rollback.settled = true;
|
|
1070
|
+
const mutationGenerations = this._nativeCoordinateMutationGenerations;
|
|
1071
|
+
if (!mutationGenerations) {
|
|
1072
|
+
return;
|
|
1073
|
+
}
|
|
1074
|
+
for (const hash of rollback.hashes) {
|
|
1075
|
+
const row = mutationGenerations.get(hash);
|
|
1076
|
+
if (!row) {
|
|
1077
|
+
continue;
|
|
1078
|
+
}
|
|
1079
|
+
if (row.holds <= 1) {
|
|
1080
|
+
mutationGenerations.delete(hash);
|
|
1081
|
+
} else {
|
|
1082
|
+
row.holds -= 1;
|
|
1083
|
+
}
|
|
1084
|
+
}
|
|
1085
|
+
}
|
|
1086
|
+
|
|
1026
1087
|
rollbackNativeBackboneCoordinateAppend(
|
|
1027
1088
|
appendHash: string,
|
|
1028
1089
|
rollback?: NativeBackboneCoordinateRollback<R>,
|
|
@@ -1038,7 +1099,7 @@ export class CoordinatePersistenceCoordinator<R extends "u32" | "u64"> {
|
|
|
1038
1099
|
const expectedGeneration = rollback?.generations.get(hash);
|
|
1039
1100
|
if (
|
|
1040
1101
|
expectedGeneration !== undefined &&
|
|
1041
|
-
mutationGenerations.get(hash) !== expectedGeneration
|
|
1102
|
+
mutationGenerations.get(hash)?.generation !== expectedGeneration
|
|
1042
1103
|
) {
|
|
1043
1104
|
continue;
|
|
1044
1105
|
}
|
|
@@ -1096,7 +1157,7 @@ export class CoordinatePersistenceCoordinator<R extends "u32" | "u64"> {
|
|
|
1096
1157
|
const expectedGeneration = rollback?.generations.get(hash);
|
|
1097
1158
|
if (
|
|
1098
1159
|
expectedGeneration !== undefined &&
|
|
1099
|
-
mutationGenerations.get(hash) !== expectedGeneration
|
|
1160
|
+
mutationGenerations.get(hash)?.generation !== expectedGeneration
|
|
1100
1161
|
) {
|
|
1101
1162
|
continue;
|
|
1102
1163
|
}
|