@peerbit/shared-log 10.3.2-6b5241d → 10.3.2
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.map +1 -1
- package/dist/src/index.js +26 -34
- package/dist/src/index.js.map +1 -1
- package/dist/src/ranges.d.ts +1 -1
- package/dist/src/ranges.d.ts.map +1 -1
- package/dist/src/ranges.js +45 -82
- package/dist/src/ranges.js.map +1 -1
- package/package.json +70 -70
- package/src/index.ts +27 -37
- package/src/ranges.ts +56 -100
package/src/index.ts
CHANGED
|
@@ -694,32 +694,27 @@ export class SharedLog<
|
|
|
694
694
|
|
|
695
695
|
// also merge segments that are already in the index
|
|
696
696
|
if (this.domain.canMerge) {
|
|
697
|
-
const
|
|
697
|
+
const mergable = await getAllMergeCandiates(
|
|
698
698
|
this.replicationIndex,
|
|
699
699
|
range,
|
|
700
700
|
this.indexableDomain.numbers,
|
|
701
701
|
);
|
|
702
|
-
const mergeableFiltered: ReplicationRangeIndexable<R>[] = [];
|
|
702
|
+
const mergeableFiltered: ReplicationRangeIndexable<R>[] = [range];
|
|
703
703
|
|
|
704
|
-
for (const
|
|
704
|
+
for (const mergeCandidate of mergable) {
|
|
705
705
|
if (this.domain.canMerge(mergeCandidate, range)) {
|
|
706
706
|
mergeableFiltered.push(mergeCandidate);
|
|
707
|
+
if (mergeCandidate.idString !== range.idString) {
|
|
708
|
+
rangesToUnreplicate.push(mergeCandidate);
|
|
709
|
+
}
|
|
707
710
|
}
|
|
708
711
|
}
|
|
709
|
-
|
|
710
|
-
mergeableFiltered.push(range); // * we push this last, because mergeRanges will reuse ids of the first elements
|
|
711
712
|
if (mergeableFiltered.length > 1) {
|
|
712
|
-
// ** this is important here as we want to reuse ids of what we already persist, not the new ranges, so we dont get a delet add op, but just a update op
|
|
713
713
|
range = mergeRanges(
|
|
714
714
|
mergeableFiltered,
|
|
715
715
|
this.indexableDomain.numbers,
|
|
716
716
|
);
|
|
717
717
|
}
|
|
718
|
-
for (const [_key, mergeCandidate] of mergeRangesThatAlreadyExist) {
|
|
719
|
-
if (mergeCandidate.idString !== range.idString) {
|
|
720
|
-
rangesToUnreplicate.push(mergeCandidate);
|
|
721
|
-
}
|
|
722
|
-
}
|
|
723
718
|
}
|
|
724
719
|
rangesToReplicate = [range];
|
|
725
720
|
}
|
|
@@ -1010,9 +1005,6 @@ export class SharedLog<
|
|
|
1010
1005
|
this.pendingMaturity.delete(from.hashcode());
|
|
1011
1006
|
}
|
|
1012
1007
|
}
|
|
1013
|
-
if (ranges.length === 0) {
|
|
1014
|
-
throw new Error("???");
|
|
1015
|
-
}
|
|
1016
1008
|
|
|
1017
1009
|
await this.replicationIndex.del({
|
|
1018
1010
|
query: new Or(
|
|
@@ -1311,29 +1303,24 @@ export class SharedLog<
|
|
|
1311
1303
|
logger.warn("Not allowed to replicate by canReplicate");
|
|
1312
1304
|
}
|
|
1313
1305
|
|
|
1306
|
+
let message: AllReplicatingSegmentsMessage | AddedReplicationSegmentMessage;
|
|
1307
|
+
|
|
1314
1308
|
if (change) {
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
}
|
|
1330
|
-
if (options.announce) {
|
|
1331
|
-
return options.announce(message);
|
|
1332
|
-
} else {
|
|
1333
|
-
await this.rpc.send(message, {
|
|
1334
|
-
priority: 1,
|
|
1335
|
-
});
|
|
1336
|
-
}
|
|
1309
|
+
if (options.reset) {
|
|
1310
|
+
message = new AllReplicatingSegmentsMessage({
|
|
1311
|
+
segments: range.map((x) => x.toReplicationRange()),
|
|
1312
|
+
});
|
|
1313
|
+
} else {
|
|
1314
|
+
message = new AddedReplicationSegmentMessage({
|
|
1315
|
+
segments: range.map((x) => x.toReplicationRange()),
|
|
1316
|
+
});
|
|
1317
|
+
}
|
|
1318
|
+
if (options.announce) {
|
|
1319
|
+
return options.announce(message);
|
|
1320
|
+
} else {
|
|
1321
|
+
await this.rpc.send(message, {
|
|
1322
|
+
priority: 1,
|
|
1323
|
+
});
|
|
1337
1324
|
}
|
|
1338
1325
|
}
|
|
1339
1326
|
}
|
|
@@ -2297,7 +2284,10 @@ export class SharedLog<
|
|
|
2297
2284
|
}
|
|
2298
2285
|
|
|
2299
2286
|
if (isLeader) {
|
|
2287
|
+
//console.log("IS LEADER", this.node.identity.publicKey.hashcode(), hash);
|
|
2288
|
+
|
|
2300
2289
|
hasAndIsLeader.push(hash);
|
|
2290
|
+
|
|
2301
2291
|
hasAndIsLeader.length > 0 &&
|
|
2302
2292
|
this.responseToPruneDebouncedFn.add({
|
|
2303
2293
|
hashes: hasAndIsLeader,
|
|
@@ -2494,7 +2484,6 @@ export class SharedLog<
|
|
|
2494
2484
|
msg.segmentIds,
|
|
2495
2485
|
context.from,
|
|
2496
2486
|
);
|
|
2497
|
-
|
|
2498
2487
|
await this.removeReplicationRanges(rangesToRemove, context.from);
|
|
2499
2488
|
const timestamp = BigInt(+new Date());
|
|
2500
2489
|
for (const range of rangesToRemove) {
|
|
@@ -3646,6 +3635,7 @@ export class SharedLog<
|
|
|
3646
3635
|
});
|
|
3647
3636
|
}
|
|
3648
3637
|
|
|
3638
|
+
// console.log("DELETE RESPONSE AS LEADER", this.node.identity.publicKey.hashcode(), entryReplicated.hash)
|
|
3649
3639
|
this.responseToPruneDebouncedFn.delete(entryReplicated.hash); // don't allow others to prune because of expecting me to replicating this entry
|
|
3650
3640
|
} else {
|
|
3651
3641
|
this.pruneDebouncedFn.delete(entryReplicated.hash);
|
package/src/ranges.ts
CHANGED
|
@@ -1019,112 +1019,68 @@ export const mergeRanges = <R extends "u32" | "u64">(
|
|
|
1019
1019
|
throw new Error("Segments have different publicKeyHash");
|
|
1020
1020
|
}
|
|
1021
1021
|
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
(
|
|
1034
|
-
|
|
1035
|
-
|
|
1022
|
+
const sorted = segments.sort((a, b) => Number(a.start1 - b.start1));
|
|
1023
|
+
|
|
1024
|
+
let calculateLargeGap = (): [
|
|
1025
|
+
NumberFromType<R>,
|
|
1026
|
+
number,
|
|
1027
|
+
ReplicationIntent,
|
|
1028
|
+
] => {
|
|
1029
|
+
let last = sorted[sorted.length - 1];
|
|
1030
|
+
let largestArc = numbers.zero;
|
|
1031
|
+
let largestArcIndex = -1;
|
|
1032
|
+
let mode = ReplicationIntent.NonStrict;
|
|
1033
|
+
for (let i = 0; i < sorted.length; i++) {
|
|
1034
|
+
const current = sorted[i];
|
|
1035
|
+
|
|
1036
|
+
if (current.mode === ReplicationIntent.Strict) {
|
|
1037
|
+
mode = ReplicationIntent.Strict;
|
|
1036
1038
|
}
|
|
1037
1039
|
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
// Merge them:
|
|
1043
|
-
// - end2 is the max of last.end2 and current.end2
|
|
1044
|
-
// - width is adjusted so total covers both
|
|
1045
|
-
// - mode is strict if either arc is strict
|
|
1046
|
-
const newEnd2 = last.end2 > current.end2 ? last.end2 : current.end2;
|
|
1047
|
-
const extendedWidth = Number(newEnd2 - last.start1); // safe if smaller arcs
|
|
1048
|
-
|
|
1049
|
-
// If you need to handle big widths carefully, you might do BigInt logic here.
|
|
1050
|
-
const newMode =
|
|
1051
|
-
last.mode === ReplicationIntent.Strict ||
|
|
1052
|
-
current.mode === ReplicationIntent.Strict
|
|
1053
|
-
? ReplicationIntent.Strict
|
|
1054
|
-
: ReplicationIntent.NonStrict;
|
|
1055
|
-
|
|
1056
|
-
// Create a new merged arc object (no mutation of last)
|
|
1057
|
-
const proto = segments[0].constructor as any;
|
|
1058
|
-
const mergedArc = new proto({
|
|
1059
|
-
width: extendedWidth,
|
|
1060
|
-
offset: last.start1,
|
|
1061
|
-
publicKeyHash: last.hash,
|
|
1062
|
-
mode: newMode,
|
|
1063
|
-
id: last.id, // re-use id
|
|
1064
|
-
});
|
|
1065
|
-
|
|
1066
|
-
// Return a new array with the last item replaced by mergedArc
|
|
1067
|
-
return [...acc.slice(0, -1), mergedArc];
|
|
1068
|
-
} else {
|
|
1069
|
-
// No overlap => just append current
|
|
1070
|
-
return [...acc, current];
|
|
1071
|
-
}
|
|
1072
|
-
},
|
|
1073
|
-
[],
|
|
1074
|
-
);
|
|
1040
|
+
if (current.start1 !== last.start1) {
|
|
1041
|
+
let arc = numbers.zero;
|
|
1042
|
+
if (current.start1 < last.end2) {
|
|
1043
|
+
arc += ((numbers.maxValue as any) - last.end2) as any;
|
|
1075
1044
|
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
}
|
|
1081
|
-
|
|
1082
|
-
// 3) OPTIONAL: If your existing logic always wants to produce a single ring arc
|
|
1083
|
-
// that covers "everything except the largest gap," do it here:
|
|
1084
|
-
|
|
1085
|
-
// Determine if any arc ended up Strict
|
|
1086
|
-
const finalMode = merged.some((m) => m.mode === ReplicationIntent.Strict)
|
|
1087
|
-
? ReplicationIntent.Strict
|
|
1088
|
-
: ReplicationIntent.NonStrict;
|
|
1089
|
-
|
|
1090
|
-
// Find the largest gap on a ring among these disjoint arcs
|
|
1091
|
-
const { largestGap, largestGapIndex } = merged.reduce<{
|
|
1092
|
-
largestGap: NumberFromType<R>;
|
|
1093
|
-
largestGapIndex: number;
|
|
1094
|
-
}>(
|
|
1095
|
-
(acc, arc, i, arr) => {
|
|
1096
|
-
// next arc in a ring
|
|
1097
|
-
const nextArc = arr[(i + 1) % arr.length];
|
|
1098
|
-
|
|
1099
|
-
// measure gap from arc.end2 -> nextArc.start1
|
|
1100
|
-
let gap: NumberFromType<R>;
|
|
1101
|
-
if (nextArc.start1 < arc.end2) {
|
|
1102
|
-
// wrap-around scenario
|
|
1103
|
-
gap = (numbers.maxValue -
|
|
1104
|
-
arc.end2 +
|
|
1105
|
-
(nextArc.start1 - numbers.zero)) as NumberFromType<R>;
|
|
1106
|
-
} else {
|
|
1107
|
-
gap = (nextArc.start1 - arc.end2) as NumberFromType<R>;
|
|
1108
|
-
}
|
|
1045
|
+
arc += (current.start1 - numbers.zero) as any;
|
|
1046
|
+
} else {
|
|
1047
|
+
arc += (current.start1 - last.end2) as any;
|
|
1048
|
+
}
|
|
1109
1049
|
|
|
1110
|
-
|
|
1111
|
-
|
|
1050
|
+
if (arc > largestArc) {
|
|
1051
|
+
largestArc = arc;
|
|
1052
|
+
largestArcIndex = i;
|
|
1053
|
+
}
|
|
1112
1054
|
}
|
|
1113
|
-
|
|
1114
|
-
}
|
|
1115
|
-
|
|
1116
|
-
|
|
1055
|
+
last = current;
|
|
1056
|
+
}
|
|
1057
|
+
|
|
1058
|
+
return [largestArc, largestArcIndex, mode];
|
|
1059
|
+
};
|
|
1060
|
+
const [largestArc, largestArcIndex, mode] = calculateLargeGap();
|
|
1061
|
+
|
|
1062
|
+
let totalLengthFinal: number = numbers.maxValue - largestArc;
|
|
1117
1063
|
|
|
1118
|
-
|
|
1119
|
-
const totalCoverage = (numbers.maxValue - largestGap) as number;
|
|
1120
|
-
const offset = merged[largestGapIndex].start1;
|
|
1064
|
+
const proto = segments[0].constructor;
|
|
1121
1065
|
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1066
|
+
if (largestArcIndex === -1) {
|
|
1067
|
+
if (mode !== segments[0].mode) {
|
|
1068
|
+
return new (proto as any)({
|
|
1069
|
+
width: segments[0].width,
|
|
1070
|
+
offset: segments[0].start1,
|
|
1071
|
+
publicKeyHash: segments[0].hash,
|
|
1072
|
+
mode,
|
|
1073
|
+
});
|
|
1074
|
+
}
|
|
1075
|
+
return segments[0]; // all ranges are the same
|
|
1076
|
+
}
|
|
1077
|
+
// use segments[0] constructor to create a new object
|
|
1078
|
+
|
|
1079
|
+
return new (proto as any)({
|
|
1080
|
+
width: totalLengthFinal,
|
|
1081
|
+
offset: segments[largestArcIndex].start1,
|
|
1126
1082
|
publicKeyHash: segments[0].hash,
|
|
1127
|
-
mode
|
|
1083
|
+
mode,
|
|
1128
1084
|
});
|
|
1129
1085
|
};
|
|
1130
1086
|
|
|
@@ -1846,7 +1802,7 @@ export const getAllMergeCandiates = async <R extends "u32" | "u64">(
|
|
|
1846
1802
|
id: Uint8Array;
|
|
1847
1803
|
},
|
|
1848
1804
|
numbers: Numbers<R>,
|
|
1849
|
-
): Promise<
|
|
1805
|
+
): Promise<MapIterator<ReplicationRangeIndexable<R>>> => {
|
|
1850
1806
|
const adjacent = await getAdjecentSameOwner(peers, range, numbers);
|
|
1851
1807
|
const covering = await getCoveringRangesSameOwner(peers, range).all();
|
|
1852
1808
|
|
|
@@ -1860,7 +1816,7 @@ export const getAllMergeCandiates = async <R extends "u32" | "u64">(
|
|
|
1860
1816
|
for (const range of covering) {
|
|
1861
1817
|
ret.set(range.value.idString, range.value);
|
|
1862
1818
|
}
|
|
1863
|
-
return ret;
|
|
1819
|
+
return ret.values();
|
|
1864
1820
|
};
|
|
1865
1821
|
|
|
1866
1822
|
export const isMatured = (
|