@peerbit/log 6.1.0 → 6.2.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.
Files changed (47) hide show
  1. package/dist/benchmark/native-graph.js +447 -5
  2. package/dist/benchmark/native-graph.js.map +1 -1
  3. package/dist/src/clock.d.ts +1 -0
  4. package/dist/src/clock.d.ts.map +1 -1
  5. package/dist/src/clock.js +32 -0
  6. package/dist/src/clock.js.map +1 -1
  7. package/dist/src/entry-create.d.ts +1 -0
  8. package/dist/src/entry-create.d.ts.map +1 -1
  9. package/dist/src/entry-create.js.map +1 -1
  10. package/dist/src/entry-index.d.ts +288 -12
  11. package/dist/src/entry-index.d.ts.map +1 -1
  12. package/dist/src/entry-index.js +1478 -33
  13. package/dist/src/entry-index.js.map +1 -1
  14. package/dist/src/entry-v0.d.ts +184 -1
  15. package/dist/src/entry-v0.d.ts.map +1 -1
  16. package/dist/src/entry-v0.js +1021 -12
  17. package/dist/src/entry-v0.js.map +1 -1
  18. package/dist/src/entry.d.ts +73 -1
  19. package/dist/src/entry.d.ts.map +1 -1
  20. package/dist/src/entry.js +124 -1
  21. package/dist/src/entry.js.map +1 -1
  22. package/dist/src/index.d.ts +1 -1
  23. package/dist/src/index.d.ts.map +1 -1
  24. package/dist/src/index.js +1 -1
  25. package/dist/src/index.js.map +1 -1
  26. package/dist/src/log.d.ts +62 -13
  27. package/dist/src/log.d.ts.map +1 -1
  28. package/dist/src/log.js +2282 -100
  29. package/dist/src/log.js.map +1 -1
  30. package/dist/src/runtime.d.ts +2 -0
  31. package/dist/src/runtime.d.ts.map +1 -0
  32. package/dist/src/runtime.js +10 -0
  33. package/dist/src/runtime.js.map +1 -0
  34. package/dist/src/trim.d.ts +14 -2
  35. package/dist/src/trim.d.ts.map +1 -1
  36. package/dist/src/trim.js +92 -4
  37. package/dist/src/trim.js.map +1 -1
  38. package/package.json +18 -15
  39. package/src/clock.ts +34 -0
  40. package/src/entry-create.ts +1 -0
  41. package/src/entry-index.ts +2232 -68
  42. package/src/entry-v0.ts +1488 -13
  43. package/src/entry.ts +235 -1
  44. package/src/index.ts +7 -1
  45. package/src/log.ts +3246 -206
  46. package/src/runtime.ts +16 -0
  47. package/src/trim.ts +133 -7
package/src/runtime.ts ADDED
@@ -0,0 +1,16 @@
1
+ export const canUseOptionalNativeModuleImports = (): boolean => {
2
+ const scope = globalThis as {
3
+ ServiceWorkerGlobalScope?: unknown;
4
+ clients?: unknown;
5
+ registration?: unknown;
6
+ skipWaiting?: unknown;
7
+ };
8
+ const serviceWorkerGlobalScope = scope.ServiceWorkerGlobalScope;
9
+ return !(
10
+ (typeof serviceWorkerGlobalScope === "function" &&
11
+ globalThis instanceof serviceWorkerGlobalScope) ||
12
+ (!!scope.clients &&
13
+ !!scope.registration &&
14
+ typeof scope.skipWaiting === "function")
15
+ );
16
+ };
package/src/trim.ts CHANGED
@@ -5,6 +5,16 @@ import type { ShallowEntry } from "./entry-shallow.js";
5
5
  import type { Entry } from "./entry.js";
6
6
  import type { SortFn } from "./log-sorting.js";
7
7
 
8
+ type MaybePromise<T> = T | Promise<T>;
9
+
10
+ const isPromiseLike = <T>(value: MaybePromise<T>): value is Promise<T> =>
11
+ !!value && typeof (value as { then?: unknown }).then === "function";
12
+
13
+ const mapMaybePromise = <T, R>(
14
+ value: MaybePromise<T>,
15
+ fn: (value: T) => MaybePromise<R>,
16
+ ): MaybePromise<R> => (isPromiseLike(value) ? value.then(fn) : fn(value));
17
+
8
18
  const trimOptionsEqual = (a: TrimOptions, b: TrimOptions) => {
9
19
  if (a.type === b.type) {
10
20
  if (a.type === "length" && b.type === "length") {
@@ -82,7 +92,14 @@ export type TrimOptions = TrimCanAppendOption & TrimCondition;
82
92
  interface Log<T> {
83
93
  index: EntryIndex<T>;
84
94
  sortFn: SortFn;
85
- deleteNode: (node: ShallowEntry) => Promise<Entry<T> | undefined>;
95
+ deleteNode: (
96
+ node: ShallowEntry,
97
+ options?: { resolveDeletedEntry?: boolean },
98
+ ) => MaybePromise<Entry<T> | ShallowEntry | undefined>;
99
+ deleteNodes?: (
100
+ nodes: ShallowEntry[],
101
+ options?: { resolveDeletedEntry?: boolean; skipNextHeadUpdates?: boolean },
102
+ ) => MaybePromise<(Entry<T> | ShallowEntry)[]>;
86
103
  getLength(): number;
87
104
  }
88
105
  export class Trim<T> {
@@ -118,14 +135,25 @@ export class Trim<T> {
118
135
  return this._trim;
119
136
  }
120
137
 
121
- private async trimTask(
138
+ private trimTask(
122
139
  option: TrimOptions | undefined = this._trim,
123
- ): Promise<Entry<T>[]> {
140
+ options?: { resolveDeletedEntries?: boolean },
141
+ ): MaybePromise<(Entry<T> | ShallowEntry)[]> {
124
142
  if (!option) {
125
143
  return [];
126
144
  }
145
+ if (option.type === "length" && !option.filter?.canTrim) {
146
+ return this.trimUnfilteredLength(option, options);
147
+ }
148
+ return this.trimTaskWithFilter(option, options);
149
+ }
150
+
151
+ private async trimTaskWithFilter(
152
+ option: TrimOptions,
153
+ options?: { resolveDeletedEntries?: boolean },
154
+ ): Promise<(Entry<T> | ShallowEntry)[]> {
127
155
  /// TODO Make this method less ugly
128
- const deleted: Entry<T>[] = [];
156
+ const deleted: (Entry<T> | ShallowEntry)[] = [];
129
157
 
130
158
  let done: () => Promise<boolean> | boolean;
131
159
  /* const valueIterator = this._log.index.query([], this._log.sortFn.sort, false); */
@@ -252,7 +280,9 @@ export class Trim<T> {
252
280
  false,
253
281
  );
254
282
 
255
- const entry = await this._log.deleteNode(node);
283
+ const entry = await this._log.deleteNode(node, {
284
+ resolveDeletedEntry: options?.resolveDeletedEntries,
285
+ });
256
286
  if (entry) {
257
287
  deleted.push(entry);
258
288
  }
@@ -286,17 +316,113 @@ export class Trim<T> {
286
316
 
287
317
  return deleted;
288
318
  }
319
+
320
+ private trimUnfilteredLength(
321
+ option: TrimToLengthOption,
322
+ options?: { resolveDeletedEntries?: boolean },
323
+ ): MaybePromise<(Entry<T> | ShallowEntry)[]> {
324
+ const to = option.to;
325
+ const from = option.from ?? to;
326
+ if (this._log.getLength() < from) {
327
+ return [];
328
+ }
329
+
330
+ const deleted: (Entry<T> | ShallowEntry)[] = [];
331
+ this._canTrimCacheHashBreakpoint.clear();
332
+ this._canTrimCacheLastNode = undefined;
333
+ this._trimLastHead = undefined;
334
+ this._trimLastTail = undefined;
335
+ this._trimLastSeed = undefined;
336
+
337
+ if (this._log.deleteNodes) {
338
+ const overage = this._log.getLength() - to;
339
+ const finish = () => {
340
+ this._trimLastLength = this._log.getLength();
341
+ this._trimLastOptions = option;
342
+ return deleted;
343
+ };
344
+ const deleteBatch = (
345
+ limit: number,
346
+ ): MaybePromise<(Entry<T> | ShallowEntry)[] | undefined> => {
347
+ const nodesResult = this._log.index.getOldestManyMaybe(limit, false);
348
+ return mapMaybePromise(nodesResult, (nodes) => {
349
+ if (nodes.length === 0) {
350
+ return undefined;
351
+ }
352
+ return this._log.deleteNodes!(nodes, {
353
+ resolveDeletedEntry: options?.resolveDeletedEntries,
354
+ // Oldest-first trim only removes entries whose next links point
355
+ // further back into the same deleted prefix.
356
+ skipNextHeadUpdates: true,
357
+ });
358
+ });
359
+ };
360
+ const pushDeleted = (items: (Entry<T> | ShallowEntry)[] | undefined) => {
361
+ if (items) {
362
+ deleted.push(...items);
363
+ }
364
+ };
365
+ const deleteRemaining = async () => {
366
+ while (this._log.getLength() > to) {
367
+ const items = await deleteBatch(
368
+ Math.min(this._log.getLength() - to, 512),
369
+ );
370
+ if (!items || items.length === 0) {
371
+ break;
372
+ }
373
+ deleted.push(...items);
374
+ }
375
+ return finish();
376
+ };
377
+ if (overage > 0) {
378
+ return mapMaybePromise(deleteBatch(overage), (items) => {
379
+ pushDeleted(items);
380
+ return this._log.getLength() > to ? deleteRemaining() : finish();
381
+ });
382
+ }
383
+ return finish();
384
+ } else {
385
+ return this.trimUnfilteredLengthOneByOne(option, options, deleted);
386
+ }
387
+ }
388
+
389
+ private async trimUnfilteredLengthOneByOne(
390
+ option: TrimToLengthOption,
391
+ options: { resolveDeletedEntries?: boolean } | undefined,
392
+ deleted: (Entry<T> | ShallowEntry)[],
393
+ ): Promise<(Entry<T> | ShallowEntry)[]> {
394
+ const to = option.to;
395
+ while (this._log.getLength() > to) {
396
+ const node = await this._log.index.getOldest(false);
397
+ if (!node) {
398
+ break;
399
+ }
400
+ const entry = await this._log.deleteNode(node, {
401
+ resolveDeletedEntry: options?.resolveDeletedEntries,
402
+ });
403
+ if (entry) {
404
+ deleted.push(entry);
405
+ }
406
+ }
407
+ this._trimLastLength = this._log.getLength();
408
+ this._trimLastOptions = option;
409
+ return deleted;
410
+ }
411
+
289
412
  /**
290
413
  * @param options
291
414
  * @returns deleted entries
292
415
  */
293
416
  async trim(
294
417
  options: TrimOptions | undefined = this._trim,
295
- ): Promise<Entry<T>[] | undefined> {
418
+ properties?: { resolveDeletedEntries?: boolean },
419
+ ): Promise<(Entry<T> | ShallowEntry)[] | undefined> {
296
420
  if (!options) {
297
421
  return;
298
422
  }
299
- const result = await this._queue.add(() => this.trimTask(options));
423
+ const result = await this._queue.add(() =>
424
+ this.trimTask(options, properties),
425
+ );
300
426
  if (result instanceof Object) {
301
427
  return result;
302
428
  }