@peerbit/log 2.1.9 → 3.0.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/src/hrtime.ts CHANGED
@@ -28,7 +28,7 @@ SOFTWARE.
28
28
  const _perfomancePolyfill = () => {
29
29
  // based on https://gist.github.com/paulirish/5438650 copyright Paul Irish 2015.
30
30
  if ("performance" in window === false) {
31
- (window.performance as any) = {};
31
+ ((window as any).performance as any) = {};
32
32
  }
33
33
 
34
34
  Date.now =
@@ -45,7 +45,7 @@ const _perfomancePolyfill = () => {
45
45
  nowOffset = performance.timing.navigationStart;
46
46
  }
47
47
 
48
- window.performance.now = () => Date.now() - nowOffset;
48
+ (window.performance as any)["now"] = () => Date.now() - nowOffset;
49
49
  }
50
50
  };
51
51
 
package/src/log.ts CHANGED
@@ -3,11 +3,10 @@ import {
3
3
  randomBytes,
4
4
  sha256Base64Sync,
5
5
  Identity,
6
- Keychain,
7
6
  X25519Keypair
8
7
  } from "@peerbit/crypto";
9
8
  import { Cache } from "@peerbit/cache";
10
- import { SimpleLevel } from "@peerbit/lazy-level";
9
+ import { AnyStore } from "@peerbit/any-store";
11
10
 
12
11
  import { EntryIndex } from "./entry-index.js";
13
12
  import * as LogError from "./log-errors.js";
@@ -37,6 +36,7 @@ import { Change } from "./change.js";
37
36
  import { EntryWithRefs } from "./entry-with-refs.js";
38
37
  import { Blocks } from "@peerbit/blocks-interface";
39
38
  import { cidifyString } from "@peerbit/blocks";
39
+ import { Keychain } from "@peerbit/keychain";
40
40
 
41
41
  const { LastWriteWins, NoZeroes } = Sorting;
42
42
 
@@ -46,7 +46,7 @@ export type LogEvents<T> = {
46
46
  };
47
47
 
48
48
  export type MemoryProperties = {
49
- cache?: SimpleLevel;
49
+ cache?: AnyStore;
50
50
  };
51
51
 
52
52
  export type LogProperties<T> = {
@@ -110,7 +110,7 @@ export class Log<T> {
110
110
  private _canAppend?: CanAppend<T>;
111
111
  private _onChange?: (change: Change<T>) => void;
112
112
  private _closed = true;
113
- private _memory?: SimpleLevel;
113
+ private _memory?: AnyStore;
114
114
  private _joining: Map<string, Promise<any>>; // entry hashes that are currently joining into this log
115
115
 
116
116
  constructor(properties?: { id?: Uint8Array }) {
@@ -173,6 +173,7 @@ export class Log<T> {
173
173
  this._values = new Values(this._entryIndex, this._sortFn);
174
174
  this._trim = new Trim(
175
175
  {
176
+ headsIndex: this._headsIndex,
176
177
  deleteNode: async (node: EntryNode) => {
177
178
  // TODO check if we have before delete?
178
179
  const entry = await this.get(node.value);
@@ -180,19 +181,20 @@ export class Log<T> {
180
181
  const a = this.values.length;
181
182
  if (entry) {
182
183
  this.values.deleteNode(node);
183
- await this.headsIndex.del(this.entryIndex.getShallow(node.value)!);
184
- await this.entryIndex.delete(node.value);
184
+ await Promise.all([
185
+ this.headsIndex.del(this.entryIndex.getShallow(node.value)!),
186
+ this.entryIndex.delete(node.value)
187
+ ]);
185
188
  this.nextsIndex.delete(node.value);
186
- await this.storage.rm(node.value);
189
+ await this.blocks.rm(node.value);
187
190
  }
188
191
  const b = this.values.length;
189
192
  if (a === b) {
190
- throw new Error(
191
- "UNexpected: " +
192
- this.values.length +
193
- "_-- " +
194
- this.entryIndex._index.size
195
- );
193
+ /* throw new Error(
194
+ "Unexpected miss match between log size and entry index size: " +
195
+ this.values.length +
196
+ this.entryIndex._index.size
197
+ ); */
196
198
  }
197
199
  return entry;
198
200
  },
@@ -276,7 +278,7 @@ export class Log<T> {
276
278
  return this._headsIndex;
277
279
  }
278
280
 
279
- get memory(): SimpleLevel | undefined {
281
+ get memory(): AnyStore | undefined {
280
282
  return this._memory;
281
283
  }
282
284
 
@@ -328,7 +330,7 @@ export class Log<T> {
328
330
  return this._identity;
329
331
  }
330
332
 
331
- get storage(): Blocks {
333
+ get blocks(): Blocks {
332
334
  return this._storage;
333
335
  }
334
336
 
@@ -554,7 +556,7 @@ export class Log<T> {
554
556
  receiver: {
555
557
  ...options.encryption.receiver
556
558
  }
557
- }
559
+ }
558
560
  : undefined,
559
561
  canAppend: this._canAppend
560
562
  });
@@ -581,7 +583,6 @@ export class Log<T> {
581
583
  const removed = await this.processEntry(entry);
582
584
 
583
585
  entry.init({ encoding: this._encoding, keychain: this._keychain });
584
- // console.log('put entry', entry.hash, (await this._entryIndex._index.size));
585
586
 
586
587
  const trimmed = await this.trim(options?.trim);
587
588
 
@@ -939,16 +940,15 @@ export class Log<T> {
939
940
  const promises: Promise<void>[] = [];
940
941
  let counter = 0;
941
942
  const deleted: Entry<T>[] = [];
942
- const deletedGids = new Set();
943
943
 
944
944
  while (stack.length > 0) {
945
945
  const entry = stack.pop()!;
946
946
  if ((counter > 0 || !skipFirst) && this.has(entry.hash)) {
947
947
  // TODO test last argument: It is for when multiple heads point to the same entry, hence we might visit it multiple times? or a concurrent delete process is doing it before us.
948
948
  this._trim.deleteFromCache(entry);
949
+ await this._headsIndex.del(entry);
949
950
  await this._values.delete(entry);
950
951
  await this._entryIndex.delete(entry.hash);
951
- await this._headsIndex.del(entry);
952
952
 
953
953
  this._nextsIndex.delete(entry.hash);
954
954
  deleted.push(entry);
@@ -976,9 +976,9 @@ export class Log<T> {
976
976
 
977
977
  async delete(entry: Entry<any>) {
978
978
  this._trim.deleteFromCache(entry);
979
+ await this._headsIndex.del(entry);
979
980
  await this._values.delete(entry);
980
981
  await this._entryIndex.delete(entry.hash);
981
- await this._headsIndex.del(entry);
982
982
  this._nextsIndex.delete(entry.hash);
983
983
  const newHeads: string[] = [];
984
984
  for (const next of entry.next) {
@@ -1049,6 +1049,10 @@ export class Log<T> {
1049
1049
  async drop() {
1050
1050
  // Don't return early here if closed = true, because "load" might create processes that needs to be closed
1051
1051
  this._closed = true; // closed = true before doing below, else we might try to open the headsIndex cache because it is closed as we assume log is still open
1052
+
1053
+ await Promise.all(
1054
+ [...this.entryIndex._index.values()].map((x) => this.blocks.rm(x.hash))
1055
+ );
1052
1056
  await this._headsIndex?.drop();
1053
1057
  await this._entryCache?.clear();
1054
1058
  await this._memory?.clear();
@@ -1107,7 +1111,7 @@ export class Log<T> {
1107
1111
  timeout: opts.fetchEntryTimeout,
1108
1112
  reload: opts.reload,
1109
1113
  cache: { update: true, reset: true }
1110
- });
1114
+ });
1111
1115
 
1112
1116
  if (heads) {
1113
1117
  // Load the log
package/src/snapshot.ts CHANGED
@@ -10,8 +10,8 @@ import {
10
10
  variant,
11
11
  vec
12
12
  } from "@dao-xyz/borsh";
13
- import { waitForAsync } from "@peerbit/time";
14
- import LocalStore from "@peerbit/lazy-level";
13
+ import { waitFor } from "@peerbit/time";
14
+ import { AnyStore } from "@peerbit/any-store";
15
15
  import { logger } from "./logger.js";
16
16
 
17
17
  @variant(0)
@@ -46,7 +46,7 @@ export class Snapshot {
46
46
  export const save = async <T>(
47
47
  snapshotPath: string,
48
48
  blockstore: Blocks,
49
- cache: LocalStore,
49
+ cache: AnyStore,
50
50
  log: {
51
51
  id: Uint8Array;
52
52
  getHeads: () => Promise<string[]>;
@@ -68,7 +68,7 @@ export const save = async <T>(
68
68
  writer.string(snapshot);
69
69
  await cache.put(snapshotPath, writer.finalize());
70
70
 
71
- await waitForAsync(() => cache.get(snapshotPath).then((bytes) => !!bytes), {
71
+ await waitFor(async () => (await cache.get(snapshotPath)) != null, {
72
72
  delayInterval: 200,
73
73
  timeout: 10 * 1000
74
74
  });
@@ -91,7 +91,7 @@ export const load = async (
91
91
  export const loadFromCache = async (
92
92
  path: string,
93
93
  blockstore: Blocks,
94
- cache: LocalStore
94
+ cache: AnyStore
95
95
  ) => {
96
96
  const snapshotOrCID = await cache.get(path);
97
97
  if (!snapshotOrCID) {
package/src/trim.ts CHANGED
@@ -2,6 +2,7 @@ import { Cache } from "@peerbit/cache";
2
2
  import PQueue from "p-queue";
3
3
  import { Entry, ShallowEntry } from "./entry.js";
4
4
  import { EntryNode, Values } from "./values.js";
5
+ import { HeadsIndex } from "./heads.js";
5
6
 
6
7
  const trimOptionsEqual = (a: TrimOptions, b: TrimOptions) => {
7
8
  if (a.type === b.type) {
@@ -78,6 +79,7 @@ export type TrimCanAppendOption = {
78
79
  export type TrimOptions = TrimCanAppendOption & TrimCondition;
79
80
 
80
81
  interface Log<T> {
82
+ headsIndex: HeadsIndex<T>;
81
83
  values: () => Values<T>;
82
84
  deleteNode: (node: EntryNode) => Promise<Entry<T> | undefined>;
83
85
  }
@@ -86,6 +88,8 @@ export class Trim<T> {
86
88
  private _canTrimCacheLastNode: EntryNode | undefined | null;
87
89
  private _trimLastHead: EntryNode | undefined | null;
88
90
  private _trimLastTail: EntryNode | undefined | null;
91
+ private _trimLastLength = 0;
92
+
89
93
  private _trimLastOptions: TrimOptions;
90
94
  private _trimLastSeed: string | number | undefined;
91
95
  private _canTrimCacheHashBreakpoint: Cache<boolean>;
@@ -177,9 +181,10 @@ export class Trim<T> {
177
181
  !this._trimLastOptions ||
178
182
  !trimOptionsEqual(this._trimLastOptions, option);
179
183
 
180
- const changed =
184
+ changed =
181
185
  this._trimLastHead !== values.head ||
182
186
  this._trimLastTail !== values.tail ||
187
+ this._trimLastLength !== this._log.headsIndex.size ||
183
188
  trimOptionsChanged;
184
189
  if (!changed) {
185
190
  return [];
@@ -250,6 +255,7 @@ export class Trim<T> {
250
255
  this._canTrimCacheLastNode = node || lastNode;
251
256
  this._trimLastHead = values.head;
252
257
  this._trimLastTail = values.tail;
258
+ this._trimLastLength = this._log.headsIndex.size;
253
259
  this._trimLastOptions = option;
254
260
  this._trimLastSeed = seed;
255
261
 
package/src/values.ts CHANGED
@@ -61,29 +61,18 @@ export class Values<T> {
61
61
  return this._values.length;
62
62
  }
63
63
 
64
- private _putPromise: Map<string, Promise<any>> = new Map();
65
-
66
64
  get entryIndex(): EntryIndex<T> {
67
65
  return this._entryIndex;
68
66
  }
69
- async put(value: Entry<T>) {
70
- let promise = this._putPromise.get(value.hash);
71
- if (promise) {
72
- return promise;
73
- }
74
- promise = this._put(value).then((v) => {
75
- this._putPromise.delete(value.hash);
76
- return v;
77
- });
78
- this._putPromise.set(value.hash, promise);
79
- return promise;
67
+ put(value: Entry<T>) {
68
+ return this._put(value);
80
69
  }
81
- async _put(value: Entry<T>) {
70
+ _put(value: Entry<T>) {
82
71
  // assume we want to insert at head (or somehere close)
83
72
  let walker = this._values.head;
84
73
  let last: EntryNode | undefined = undefined;
85
74
  while (walker) {
86
- const walkerValue = await this._entryIndex.getShallow(walker.value);
75
+ const walkerValue = this._entryIndex.getShallow(walker.value);
87
76
  if (!walkerValue) {
88
77
  throw new Error("Missing walker value");
89
78
  }
@@ -167,7 +156,7 @@ function _insertAfter(
167
156
  null as any,
168
157
  self.head as EntryNode | undefined,
169
158
  self
170
- )
159
+ )
171
160
  : new yallist.Node(value, node, node.next as EntryNode | undefined, self);
172
161
 
173
162
  // is tail