@peerbit/log 1.0.14 → 2.0.0
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/esm/clock.d.ts +1 -1
- package/lib/esm/clock.js +11 -13
- package/lib/esm/clock.js.map +1 -1
- package/lib/esm/encoding.js +1 -1
- package/lib/esm/entry-index.d.ts +5 -2
- package/lib/esm/entry-index.js +9 -3
- package/lib/esm/entry-index.js.map +1 -1
- package/lib/esm/entry.d.ts +40 -27
- package/lib/esm/entry.js +115 -115
- package/lib/esm/entry.js.map +1 -1
- package/lib/esm/heads-cache.js +1 -1
- package/lib/esm/heads.d.ts +13 -8
- package/lib/esm/heads.js +52 -44
- package/lib/esm/heads.js.map +1 -1
- package/lib/esm/log-sorting.d.ts +3 -3
- package/lib/esm/log-sorting.js +2 -2
- package/lib/esm/log-sorting.js.map +1 -1
- package/lib/esm/log.d.ts +10 -6
- package/lib/esm/log.js +40 -52
- package/lib/esm/log.js.map +1 -1
- package/lib/esm/trim.d.ts +2 -2
- package/lib/esm/trim.js +10 -9
- package/lib/esm/trim.js.map +1 -1
- package/lib/esm/values.d.ts +5 -11
- package/lib/esm/values.js +17 -17
- package/lib/esm/values.js.map +1 -1
- package/package.json +5 -5
- package/src/clock.ts +11 -13
- package/src/encoding.ts +1 -1
- package/src/entry-index.ts +13 -6
- package/src/entry.ts +139 -138
- package/src/heads-cache.ts +1 -1
- package/src/heads.ts +76 -57
- package/src/log-sorting.ts +20 -16
- package/src/log.ts +61 -59
- package/src/trim.ts +14 -12
- package/src/values.ts +24 -32
- package/lib/esm/is-defined.d.ts +0 -1
- package/lib/esm/is-defined.js +0 -2
- package/lib/esm/is-defined.js.map +0 -1
- package/src/is-defined.ts +0 -1
package/lib/esm/heads.js
CHANGED
|
@@ -1,21 +1,23 @@
|
|
|
1
|
-
import { Entry } from "./entry.js";
|
|
2
1
|
import { HeadsCache } from "./heads-cache.js";
|
|
2
|
+
import { logger } from "./logger.js";
|
|
3
3
|
export class HeadsIndex {
|
|
4
4
|
_id;
|
|
5
5
|
_index = new Set();
|
|
6
|
-
_gids;
|
|
6
|
+
_gids; // gid -> hash -> entry
|
|
7
7
|
_headsCache;
|
|
8
8
|
_config;
|
|
9
|
+
_onGidRemoved;
|
|
9
10
|
constructor(id) {
|
|
10
11
|
this._gids = new Map();
|
|
11
12
|
this._id = id;
|
|
12
13
|
}
|
|
13
|
-
async init(
|
|
14
|
-
this._config =
|
|
14
|
+
async init(log, options = {}) {
|
|
15
|
+
this._config = log;
|
|
16
|
+
this._onGidRemoved = options.onGidRemoved;
|
|
15
17
|
await this.reset(options?.entries || []);
|
|
16
|
-
if (
|
|
18
|
+
if (log.memory) {
|
|
17
19
|
this._headsCache = new HeadsCache(this);
|
|
18
|
-
return this._headsCache.init(await
|
|
20
|
+
return this._headsCache.init(await log.memory.sublevel("heads"));
|
|
19
21
|
}
|
|
20
22
|
}
|
|
21
23
|
async load(options) {
|
|
@@ -27,20 +29,17 @@ export class HeadsIndex {
|
|
|
27
29
|
if (!heads) {
|
|
28
30
|
return;
|
|
29
31
|
}
|
|
30
|
-
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
const q = 123;
|
|
42
|
-
throw error;
|
|
43
|
-
}
|
|
32
|
+
const entries = await Promise.all(heads.map(async (x) => {
|
|
33
|
+
const entry = await this._config.entryIndex.get(x, { load: true });
|
|
34
|
+
if (!entry) {
|
|
35
|
+
logger.error("Failed to load entry from head with hash: " + x);
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
await entry.getMeta(); // TODO types,decrypt gid
|
|
39
|
+
return entry;
|
|
40
|
+
}));
|
|
41
|
+
await this.reset(entries.filter((x) => !!x));
|
|
42
|
+
return entries;
|
|
44
43
|
}
|
|
45
44
|
get headsCache() {
|
|
46
45
|
return this._headsCache;
|
|
@@ -65,22 +64,26 @@ export class HeadsIndex {
|
|
|
65
64
|
}
|
|
66
65
|
async reset(entries, options = { cache: { reset: true, update: true } }) {
|
|
67
66
|
this._index.clear();
|
|
67
|
+
const gidKeys = [...this._gids.keys()];
|
|
68
68
|
this._gids = new Map();
|
|
69
|
-
if (entries) {
|
|
69
|
+
if (entries?.length > 0) {
|
|
70
70
|
await this.putAll(entries, options); // reset cache = true
|
|
71
71
|
}
|
|
72
|
+
if (gidKeys.length > 0) {
|
|
73
|
+
this._onGidRemoved?.(gidKeys);
|
|
74
|
+
}
|
|
72
75
|
}
|
|
73
76
|
has(cid) {
|
|
74
77
|
return this._index.has(cid);
|
|
75
78
|
}
|
|
76
79
|
async put(entry, options) {
|
|
77
|
-
this._putOne(entry);
|
|
80
|
+
await this._putOne(entry);
|
|
78
81
|
if (options?.cache?.update) {
|
|
79
82
|
await this._headsCache?.queue({ added: [entry] }, options.cache.reset);
|
|
80
83
|
}
|
|
81
84
|
}
|
|
82
85
|
async putAll(entries, options) {
|
|
83
|
-
this._putAll(entries);
|
|
86
|
+
await this._putAll(entries);
|
|
84
87
|
if (options?.cache?.update) {
|
|
85
88
|
await this._headsCache?.queue({ added: entries }, options.cache.reset);
|
|
86
89
|
}
|
|
@@ -91,7 +94,7 @@ export class HeadsIndex {
|
|
|
91
94
|
async updateHeadsCache(change = {}, reset) {
|
|
92
95
|
await this._headsCache?.queue(change, reset);
|
|
93
96
|
}
|
|
94
|
-
_putOne(entry) {
|
|
97
|
+
async _putOne(entry) {
|
|
95
98
|
if (!entry.hash) {
|
|
96
99
|
throw new Error("Missing hash");
|
|
97
100
|
}
|
|
@@ -99,44 +102,49 @@ export class HeadsIndex {
|
|
|
99
102
|
return;
|
|
100
103
|
}
|
|
101
104
|
this._index.add(entry.hash);
|
|
102
|
-
|
|
103
|
-
|
|
105
|
+
const map = this._gids.get(entry.meta.gid);
|
|
106
|
+
if (!map) {
|
|
107
|
+
const newMap = new Map();
|
|
108
|
+
this._gids.set(entry.meta.gid, newMap);
|
|
109
|
+
newMap.set(entry.hash, entry);
|
|
104
110
|
}
|
|
105
111
|
else {
|
|
106
|
-
|
|
112
|
+
map.set(entry.hash, entry);
|
|
113
|
+
}
|
|
114
|
+
for (const next of entry.next) {
|
|
115
|
+
const indexedEntry = this._config.entryIndex.getShallow(next);
|
|
116
|
+
if (indexedEntry) {
|
|
117
|
+
await this.del(indexedEntry);
|
|
118
|
+
}
|
|
107
119
|
}
|
|
108
120
|
}
|
|
109
|
-
_putAll(entries) {
|
|
121
|
+
async _putAll(entries) {
|
|
110
122
|
for (const entry of entries) {
|
|
111
|
-
this._putOne(entry);
|
|
123
|
+
await this._putOne(entry);
|
|
112
124
|
}
|
|
113
125
|
}
|
|
114
126
|
async del(entry, options) {
|
|
115
127
|
const wasHead = this._index.delete(entry.hash);
|
|
116
128
|
if (!wasHead) {
|
|
117
|
-
return
|
|
118
|
-
lastWithGid: false,
|
|
119
|
-
removed: false,
|
|
120
|
-
};
|
|
129
|
+
return false;
|
|
121
130
|
}
|
|
122
|
-
|
|
123
|
-
const
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
this._gids.set(entry.gid, newValue);
|
|
131
|
+
let removedGids = undefined;
|
|
132
|
+
const map = this._gids.get(entry.meta.gid);
|
|
133
|
+
map.delete(entry.hash);
|
|
134
|
+
if (map.size <= 0) {
|
|
135
|
+
this._gids.delete(entry.meta.gid);
|
|
136
|
+
(removedGids || (removedGids = new Set())).add(entry.meta.gid);
|
|
129
137
|
}
|
|
130
138
|
if (!entry.hash) {
|
|
131
139
|
throw new Error("Missing hash");
|
|
132
140
|
}
|
|
141
|
+
if (removedGids) {
|
|
142
|
+
await this._onGidRemoved?.([...removedGids]);
|
|
143
|
+
}
|
|
133
144
|
if (wasHead && options?.cache?.update) {
|
|
134
145
|
await this._headsCache?.queue({ removed: [entry.hash] }, options.cache.reset);
|
|
135
146
|
}
|
|
136
|
-
return
|
|
137
|
-
removed: wasHead,
|
|
138
|
-
lastWithGid: lastWithGid,
|
|
139
|
-
};
|
|
147
|
+
return wasHead;
|
|
140
148
|
// this._headsCache = undefined; // TODO do smarter things here, only remove the element needed (?)
|
|
141
149
|
}
|
|
142
150
|
}
|
package/lib/esm/heads.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"heads.js","sourceRoot":"","sources":["../../src/heads.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"heads.js","sourceRoot":"","sources":["../../src/heads.ts"],"names":[],"mappings":"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"}
|
package/lib/esm/log-sorting.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export type ISortFunction = <T>(a:
|
|
1
|
+
import { ShallowEntry } from "./entry.js";
|
|
2
|
+
export type ISortFunction = <T>(a: ShallowEntry, b: ShallowEntry, resolveConflict?: (a: ShallowEntry, b: ShallowEntry) => number) => number;
|
|
3
3
|
/**
|
|
4
4
|
* Sort two entries as Last-Write-Wins (LWW).
|
|
5
5
|
*
|
|
@@ -41,4 +41,4 @@ export declare const SortByClockId: ISortFunction;
|
|
|
41
41
|
* @returns {function(a, b)} 1 if a is greater, -1 if b is greater
|
|
42
42
|
* @throws {Error} if func ever returns 0
|
|
43
43
|
*/
|
|
44
|
-
export declare const NoZeroes: (func: ISortFunction) => <T>(a:
|
|
44
|
+
export declare const NoZeroes: (func: ISortFunction) => <T>(a: ShallowEntry, b: ShallowEntry) => number;
|
package/lib/esm/log-sorting.js
CHANGED
|
@@ -48,7 +48,7 @@ export const SortByEntryHash = (a, b) => {
|
|
|
48
48
|
*/
|
|
49
49
|
export const SortByClocks = (a, b, resolveConflict) => {
|
|
50
50
|
// Compare the clocks
|
|
51
|
-
const diff = Clock.compare(a.
|
|
51
|
+
const diff = Clock.compare(a.meta.clock, b.meta.clock);
|
|
52
52
|
// If the clocks are concurrent, use the provided
|
|
53
53
|
// conflict resolution function to determine which comes first
|
|
54
54
|
return diff === 0 ? (resolveConflict || First)(a, b) : diff;
|
|
@@ -63,7 +63,7 @@ export const SortByClocks = (a, b, resolveConflict) => {
|
|
|
63
63
|
export const SortByClockId = (a, b, resolveConflict) => {
|
|
64
64
|
// Sort by ID if clocks are concurrent,
|
|
65
65
|
// take the entry with a "greater" clock id
|
|
66
|
-
const clockCompare = compare(a.
|
|
66
|
+
const clockCompare = compare(a.meta.clock.id, b.meta.clock.id);
|
|
67
67
|
return clockCompare === 0 ? (resolveConflict || First)(a, b) : clockCompare;
|
|
68
68
|
};
|
|
69
69
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"log-sorting.js","sourceRoot":"","sources":["../../src/log-sorting.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,IAAI,KAAK,EAAE,MAAM,YAAY,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAE/C,MAAM,KAAK,GAAG,CAAC,CAAM,EAAE,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC;AAOpC;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,aAAa,GAAkB,
|
|
1
|
+
{"version":3,"file":"log-sorting.js","sourceRoot":"","sources":["../../src/log-sorting.ts"],"names":[],"mappings":"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"}
|
package/lib/esm/log.d.ts
CHANGED
|
@@ -13,6 +13,7 @@ import { EntryWithRefs } from "./entry-with-refs.js";
|
|
|
13
13
|
import { Blocks } from "@peerbit/blocks-interface";
|
|
14
14
|
export type LogEvents<T> = {
|
|
15
15
|
onChange?: (change: Change<T>) => void;
|
|
16
|
+
onGidRemoved?: (gids: string[]) => Promise<void> | void;
|
|
16
17
|
};
|
|
17
18
|
export type MemoryProperties = {
|
|
18
19
|
cache?: SimpleLevel;
|
|
@@ -27,17 +28,19 @@ export type LogProperties<T> = {
|
|
|
27
28
|
};
|
|
28
29
|
export type LogOptions<T> = LogProperties<T> & LogEvents<T> & MemoryProperties;
|
|
29
30
|
export type AppendOptions<T> = {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
meta?: {
|
|
32
|
+
type?: EntryType;
|
|
33
|
+
gidSeed?: Uint8Array;
|
|
34
|
+
data?: Uint8Array;
|
|
35
|
+
timestamp?: Timestamp;
|
|
36
|
+
next?: Entry<any>[];
|
|
37
|
+
};
|
|
33
38
|
identity?: Identity;
|
|
34
39
|
signers?: ((data: Uint8Array) => Promise<SignatureWithKey> | SignatureWithKey)[];
|
|
35
|
-
onGidsShadowed?: (gids: string[]) => void;
|
|
36
40
|
trim?: TrimOptions;
|
|
37
|
-
timestamp?: Timestamp;
|
|
38
41
|
encryption?: {
|
|
39
42
|
keypair: X25519Keypair;
|
|
40
|
-
|
|
43
|
+
receiver: EncryptionTemplateMaybeEncrypted;
|
|
41
44
|
};
|
|
42
45
|
};
|
|
43
46
|
export declare class Log<T> {
|
|
@@ -73,6 +76,7 @@ export declare class Log<T> {
|
|
|
73
76
|
*/
|
|
74
77
|
get length(): number;
|
|
75
78
|
get values(): Values<T>;
|
|
79
|
+
get canAppend(): CanAppend<T> | undefined;
|
|
76
80
|
/**
|
|
77
81
|
* Checks if a entry is part of the log
|
|
78
82
|
* @param {string} hash The hash of the entry
|
package/lib/esm/log.js
CHANGED
|
@@ -13,7 +13,6 @@ import { Cache } from "@peerbit/cache";
|
|
|
13
13
|
import { EntryIndex } from "./entry-index.js";
|
|
14
14
|
import * as LogError from "./log-errors.js";
|
|
15
15
|
import * as Sorting from "./log-sorting.js";
|
|
16
|
-
import { isDefined } from "./is-defined.js";
|
|
17
16
|
import { findUniques } from "./find-uniques.js";
|
|
18
17
|
import { Entry, EntryType, } from "./entry.js";
|
|
19
18
|
import { HLC, LamportClock as Clock, } from "./clock.js";
|
|
@@ -51,18 +50,18 @@ export let Log = Log_1 = class Log {
|
|
|
51
50
|
this._id = properties?.id || randomBytes(32);
|
|
52
51
|
}
|
|
53
52
|
async open(store, identity, options = {}) {
|
|
54
|
-
if (
|
|
53
|
+
if (store == null) {
|
|
55
54
|
throw LogError.BlockStoreNotDefinedError();
|
|
56
55
|
}
|
|
57
|
-
if (
|
|
56
|
+
if (identity == null) {
|
|
58
57
|
throw new Error("Identity is required");
|
|
59
58
|
}
|
|
60
59
|
if (this.closed === false) {
|
|
61
60
|
throw new Error("Already open");
|
|
62
61
|
}
|
|
63
|
-
const { encoding, trim, keychain, cache } = options;
|
|
62
|
+
const { encoding, trim, keychain, cache, onGidRemoved } = options;
|
|
64
63
|
let { sortFn } = options;
|
|
65
|
-
if (
|
|
64
|
+
if (sortFn == null) {
|
|
66
65
|
sortFn = LastWriteWins;
|
|
67
66
|
}
|
|
68
67
|
sortFn = sortFn;
|
|
@@ -86,7 +85,7 @@ export let Log = Log_1 = class Log {
|
|
|
86
85
|
throw new Error("Id not set");
|
|
87
86
|
}
|
|
88
87
|
this._headsIndex = new HeadsIndex(id);
|
|
89
|
-
await this._headsIndex.init(this);
|
|
88
|
+
await this._headsIndex.init(this, { onGidRemoved });
|
|
90
89
|
this._entryCache = new Cache({ max: ENTRY_CACHE_MAX });
|
|
91
90
|
this._entryIndex = new EntryIndex({
|
|
92
91
|
store: this._storage,
|
|
@@ -97,15 +96,15 @@ export let Log = Log_1 = class Log {
|
|
|
97
96
|
this._trim = new Trim({
|
|
98
97
|
deleteNode: async (node) => {
|
|
99
98
|
// TODO check if we have before delete?
|
|
100
|
-
const entry = await this.get(node.value
|
|
99
|
+
const entry = await this.get(node.value);
|
|
101
100
|
//f (!!entry)
|
|
102
101
|
const a = this.values.length;
|
|
103
102
|
if (entry) {
|
|
104
103
|
this.values.deleteNode(node);
|
|
105
|
-
await this.entryIndex.
|
|
106
|
-
await this.
|
|
107
|
-
this.nextsIndex.delete(node.value
|
|
108
|
-
await this.storage.rm(node.value
|
|
104
|
+
await this.headsIndex.del(this.entryIndex.getShallow(node.value));
|
|
105
|
+
await this.entryIndex.delete(node.value);
|
|
106
|
+
this.nextsIndex.delete(node.value);
|
|
107
|
+
await this.storage.rm(node.value);
|
|
109
108
|
}
|
|
110
109
|
const b = this.values.length;
|
|
111
110
|
if (a === b) {
|
|
@@ -158,6 +157,9 @@ export let Log = Log_1 = class Log {
|
|
|
158
157
|
get values() {
|
|
159
158
|
return this._values;
|
|
160
159
|
}
|
|
160
|
+
get canAppend() {
|
|
161
|
+
return this._canAppend;
|
|
162
|
+
}
|
|
161
163
|
/**
|
|
162
164
|
* Checks if a entry is part of the log
|
|
163
165
|
* @param {string} hash The hash of the entry
|
|
@@ -376,41 +378,43 @@ export let Log = Log_1 = class Log {
|
|
|
376
378
|
*/
|
|
377
379
|
async append(data, options = {}) {
|
|
378
380
|
// Update the clock (find the latest clock)
|
|
379
|
-
if (options.
|
|
380
|
-
for (const n of options.
|
|
381
|
+
if (options.meta?.next) {
|
|
382
|
+
for (const n of options.meta.next) {
|
|
381
383
|
if (!n.hash)
|
|
382
384
|
throw new Error("Expecting nexts to already be saved. missing hash for one or more entries");
|
|
383
385
|
}
|
|
384
386
|
}
|
|
385
387
|
await this.load({ reload: false });
|
|
386
|
-
const
|
|
387
|
-
const nexts = options.nexts || (await this.getHeads());
|
|
388
|
+
const nexts = options.meta?.next || (await this.getHeads());
|
|
388
389
|
// Calculate max time for log/graph
|
|
389
390
|
const clock = new Clock({
|
|
390
391
|
id: this._identity.publicKey.bytes,
|
|
391
|
-
timestamp: options
|
|
392
|
+
timestamp: options?.meta?.timestamp || this._hlc.now(),
|
|
392
393
|
});
|
|
393
394
|
const entry = await Entry.create({
|
|
394
395
|
store: this._storage,
|
|
395
396
|
identity: options.identity || this._identity,
|
|
396
397
|
signers: options.signers,
|
|
397
398
|
data,
|
|
398
|
-
|
|
399
|
-
|
|
399
|
+
meta: {
|
|
400
|
+
clock,
|
|
401
|
+
type: options.meta?.type,
|
|
402
|
+
gidSeed: options.meta?.gidSeed,
|
|
403
|
+
data: options.meta?.data,
|
|
404
|
+
next: nexts,
|
|
405
|
+
},
|
|
400
406
|
encoding: this._encoding,
|
|
401
|
-
next: nexts,
|
|
402
|
-
gidSeed: options.gidSeed,
|
|
403
407
|
encryption: options.encryption
|
|
404
408
|
? {
|
|
405
409
|
keypair: options.encryption.keypair,
|
|
406
|
-
|
|
407
|
-
...options.encryption.
|
|
410
|
+
receiver: {
|
|
411
|
+
...options.encryption.receiver,
|
|
408
412
|
},
|
|
409
413
|
}
|
|
410
414
|
: undefined,
|
|
411
415
|
canAppend: this._canAppend,
|
|
412
416
|
});
|
|
413
|
-
if (!
|
|
417
|
+
if (!entry.hash) {
|
|
414
418
|
throw new Error("Unexpected");
|
|
415
419
|
}
|
|
416
420
|
for (const e of nexts) {
|
|
@@ -424,32 +428,10 @@ export let Log = Log_1 = class Log {
|
|
|
424
428
|
nextIndexSet.add(entry.hash);
|
|
425
429
|
}
|
|
426
430
|
}
|
|
427
|
-
const removedGids = new Set();
|
|
428
|
-
if (hasNext) {
|
|
429
|
-
for (const next of nexts) {
|
|
430
|
-
const deletion = await this._headsIndex.del(next);
|
|
431
|
-
if (deletion.lastWithGid && next.gid !== entry.gid) {
|
|
432
|
-
removedGids.add(next.gid);
|
|
433
|
-
}
|
|
434
|
-
}
|
|
435
|
-
}
|
|
436
|
-
else {
|
|
437
|
-
// next is all heads, which means we should just overwrite
|
|
438
|
-
for (const key of this.headsIndex.gids.keys()) {
|
|
439
|
-
if (key !== entry.gid) {
|
|
440
|
-
removedGids.add(key);
|
|
441
|
-
}
|
|
442
|
-
}
|
|
443
|
-
await this.headsIndex.reset([entry], { cache: { update: false } });
|
|
444
|
-
}
|
|
445
431
|
await this._entryIndex.set(entry, false); // save === false, because its already saved when Entry.create
|
|
446
432
|
await this._headsIndex.put(entry, { cache: { update: false } }); // we will update the cache a few lines later *
|
|
447
433
|
await this._values.put(entry);
|
|
448
434
|
const removed = await this.processEntry(entry);
|
|
449
|
-
// if next contails all gids
|
|
450
|
-
if (options.onGidsShadowed && removedGids.size > 0) {
|
|
451
|
-
options.onGidsShadowed([...removedGids]);
|
|
452
|
-
}
|
|
453
435
|
entry.init({ encoding: this._encoding, keychain: this._keychain });
|
|
454
436
|
// console.log('put entry', entry.hash, (await this._entryIndex._index.size));
|
|
455
437
|
const trimmed = await this.trim(options?.trim);
|
|
@@ -553,7 +535,7 @@ export let Log = Log_1 = class Log {
|
|
|
553
535
|
if (amount >= 0 && counter >= amount) {
|
|
554
536
|
return;
|
|
555
537
|
}
|
|
556
|
-
yield next.value
|
|
538
|
+
yield next.value;
|
|
557
539
|
counter++;
|
|
558
540
|
next = nextFn(next);
|
|
559
541
|
}
|
|
@@ -606,6 +588,12 @@ export let Log = Log_1 = class Log {
|
|
|
606
588
|
});
|
|
607
589
|
} */
|
|
608
590
|
async join(entriesOrLog, options) {
|
|
591
|
+
const definedOptions = {
|
|
592
|
+
...options,
|
|
593
|
+
cache: options?.cache ?? {
|
|
594
|
+
update: true,
|
|
595
|
+
},
|
|
596
|
+
};
|
|
609
597
|
await this.load({ reload: false });
|
|
610
598
|
if (entriesOrLog.length === 0) {
|
|
611
599
|
return;
|
|
@@ -654,7 +642,6 @@ export let Log = Log_1 = class Log {
|
|
|
654
642
|
}
|
|
655
643
|
}
|
|
656
644
|
}
|
|
657
|
-
// Resolve missing entries
|
|
658
645
|
const removedHeads = [];
|
|
659
646
|
for (const hash of stack) {
|
|
660
647
|
if (visited.has(hash) || this.has(hash)) {
|
|
@@ -668,7 +655,7 @@ export let Log = Log_1 = class Log {
|
|
|
668
655
|
entry.init(this);
|
|
669
656
|
resolvedEntries.set(entry.hash, entry);
|
|
670
657
|
let nexts;
|
|
671
|
-
if (entry.
|
|
658
|
+
if (entry.meta.type !== EntryType.CUT &&
|
|
672
659
|
(nexts = await entry.getNext())) {
|
|
673
660
|
let isRoot = true;
|
|
674
661
|
for (const next of nexts) {
|
|
@@ -706,7 +693,7 @@ export let Log = Log_1 = class Log {
|
|
|
706
693
|
while (entriesBottomUp.length > 0) {
|
|
707
694
|
const e = entriesBottomUp.shift();
|
|
708
695
|
await this._joining.get(e.hash);
|
|
709
|
-
const p = this.joinEntry(e, nextRefs, entriesBottomUp,
|
|
696
|
+
const p = this.joinEntry(e, nextRefs, entriesBottomUp, definedOptions).then(() => this._joining.delete(e.hash) // TODO, if head we run into problems with concurrency here!, we add heads at line 929 but resolve here
|
|
710
697
|
);
|
|
711
698
|
this._joining.set(e.hash, p);
|
|
712
699
|
await p;
|
|
@@ -716,7 +703,7 @@ export let Log = Log_1 = class Log {
|
|
|
716
703
|
if (this.length > (options?.length ?? Number.MAX_SAFE_INTEGER)) {
|
|
717
704
|
return;
|
|
718
705
|
}
|
|
719
|
-
if (!
|
|
706
|
+
if (!e.hash) {
|
|
720
707
|
throw new Error("Unexpected");
|
|
721
708
|
}
|
|
722
709
|
if (!this.has(e.hash)) {
|
|
@@ -731,7 +718,7 @@ export let Log = Log_1 = class Log {
|
|
|
731
718
|
// Update the internal entry index
|
|
732
719
|
await this._entryIndex.set(e);
|
|
733
720
|
await this._values.put(e);
|
|
734
|
-
if (e.
|
|
721
|
+
if (e.meta.type !== EntryType.CUT) {
|
|
735
722
|
for (const a of e.next) {
|
|
736
723
|
if (!this.has(a)) {
|
|
737
724
|
await this.join([a]);
|
|
@@ -770,7 +757,7 @@ export let Log = Log_1 = class Log {
|
|
|
770
757
|
}
|
|
771
758
|
}
|
|
772
759
|
async processEntry(entry) {
|
|
773
|
-
if (entry.
|
|
760
|
+
if (entry.meta.type === EntryType.CUT) {
|
|
774
761
|
return this.deleteRecursively(entry, true);
|
|
775
762
|
}
|
|
776
763
|
return [];
|
|
@@ -781,6 +768,7 @@ export let Log = Log_1 = class Log {
|
|
|
781
768
|
const promises = [];
|
|
782
769
|
let counter = 0;
|
|
783
770
|
const deleted = [];
|
|
771
|
+
const deletedGids = new Set();
|
|
784
772
|
while (stack.length > 0) {
|
|
785
773
|
const entry = stack.pop();
|
|
786
774
|
if ((counter > 0 || !skipFirst) && this.has(entry.hash)) {
|