@graffiti-garden/implementation-local 0.6.2 → 0.6.4
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/browser/index.js +2 -2
- package/dist/browser/index.js.map +3 -3
- package/dist/cjs/database.js +18 -4
- package/dist/cjs/database.js.map +2 -2
- package/dist/database.d.ts +6 -0
- package/dist/database.d.ts.map +1 -1
- package/dist/esm/database.js +18 -4
- package/dist/esm/database.js.map +2 -2
- package/package.json +2 -2
- package/src/database.ts +36 -5
package/src/database.ts
CHANGED
|
@@ -63,9 +63,17 @@ export interface GraffitiLocalOptions {
|
|
|
63
63
|
* If not provided, an internal instance will be created.
|
|
64
64
|
*/
|
|
65
65
|
ajv?: Ajv;
|
|
66
|
+
/**
|
|
67
|
+
* Wait at least this long (in milliseconds) before continuing a stream.
|
|
68
|
+
* A basic form of rate limiting. Defaults to 1 seconds.
|
|
69
|
+
*/
|
|
70
|
+
continueBuffer?: number;
|
|
66
71
|
}
|
|
67
72
|
|
|
68
73
|
const DEFAULT_ORIGIN = "graffiti:local:";
|
|
74
|
+
|
|
75
|
+
// During stream continuations, return objects
|
|
76
|
+
// that have possibly already been seen over this window
|
|
69
77
|
const LAST_MODIFIED_BUFFER = 60000;
|
|
70
78
|
|
|
71
79
|
type GraffitiObjectWithTombstone = GraffitiObjectBase & { tombstone: boolean };
|
|
@@ -240,6 +248,9 @@ export class GraffitiLocalDatabase
|
|
|
240
248
|
get: Graffiti["get"] = async (...args) => {
|
|
241
249
|
const [urlObject, schema, session] = args;
|
|
242
250
|
|
|
251
|
+
// TODO: Rate limit getting the same object
|
|
252
|
+
// over and over
|
|
253
|
+
|
|
243
254
|
const docsAll = await this.allDocsAtLocation(urlObject);
|
|
244
255
|
|
|
245
256
|
// Filter out ones not allowed
|
|
@@ -596,7 +607,10 @@ export class GraffitiLocalDatabase
|
|
|
596
607
|
channels?: string[],
|
|
597
608
|
processedIds?: Set<string>,
|
|
598
609
|
): AsyncGenerator<GraffitiObjectStreamContinueEntry<Schema>> {
|
|
599
|
-
|
|
610
|
+
if (ifModifiedSince !== undefined) {
|
|
611
|
+
// Subtract a minute to make sure we don't miss any objects
|
|
612
|
+
ifModifiedSince -= LAST_MODIFIED_BUFFER;
|
|
613
|
+
}
|
|
600
614
|
|
|
601
615
|
const result = await (
|
|
602
616
|
await this.db
|
|
@@ -613,7 +627,8 @@ export class GraffitiLocalDatabase
|
|
|
613
627
|
if (processedIds?.has(doc._id)) continue;
|
|
614
628
|
processedIds?.add(doc._id);
|
|
615
629
|
|
|
616
|
-
|
|
630
|
+
// If this is not a continuation, skip tombstones
|
|
631
|
+
if (ifModifiedSince === undefined && doc.tombstone) continue;
|
|
617
632
|
|
|
618
633
|
const object = this.extractGraffitiObject(doc);
|
|
619
634
|
|
|
@@ -636,6 +651,19 @@ export class GraffitiLocalDatabase
|
|
|
636
651
|
}
|
|
637
652
|
}
|
|
638
653
|
|
|
654
|
+
protected async waitToContinue(ifModifiedSince: number | undefined) {
|
|
655
|
+
if (ifModifiedSince === undefined) return;
|
|
656
|
+
const continueBuffer = this.options.continueBuffer ?? 1000;
|
|
657
|
+
const timeElapsedSinceContinue = Date.now() - ifModifiedSince;
|
|
658
|
+
if (timeElapsedSinceContinue < continueBuffer) {
|
|
659
|
+
// Continue was called too soon,
|
|
660
|
+
// wait a bit before continuing
|
|
661
|
+
await new Promise((resolve) =>
|
|
662
|
+
setTimeout(resolve, continueBuffer - timeElapsedSinceContinue),
|
|
663
|
+
);
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
|
|
639
667
|
protected async *discoverMeta<Schema extends JSONSchema>(
|
|
640
668
|
args: Parameters<typeof Graffiti.prototype.discover<Schema>>,
|
|
641
669
|
ifModifiedSince?: number,
|
|
@@ -643,6 +671,8 @@ export class GraffitiLocalDatabase
|
|
|
643
671
|
GraffitiObjectStreamContinueEntry<Schema>,
|
|
644
672
|
number | undefined
|
|
645
673
|
> {
|
|
674
|
+
await this.waitToContinue(ifModifiedSince);
|
|
675
|
+
|
|
646
676
|
const [channels, schema, session] = args;
|
|
647
677
|
const validate = compileGraffitiObjectSchema(await this.ajv, schema);
|
|
648
678
|
const { startKeySuffix, endKeySuffix } = this.queryLastModifiedSuffixes(
|
|
@@ -673,8 +703,7 @@ export class GraffitiLocalDatabase
|
|
|
673
703
|
for await (const result of iterator) yield result;
|
|
674
704
|
}
|
|
675
705
|
|
|
676
|
-
|
|
677
|
-
return startTime - LAST_MODIFIED_BUFFER;
|
|
706
|
+
return startTime;
|
|
678
707
|
}
|
|
679
708
|
|
|
680
709
|
protected async *recoverOrphansMeta<Schema extends JSONSchema>(
|
|
@@ -684,6 +713,8 @@ export class GraffitiLocalDatabase
|
|
|
684
713
|
GraffitiObjectStreamContinueEntry<Schema>,
|
|
685
714
|
number | undefined
|
|
686
715
|
> {
|
|
716
|
+
await this.waitToContinue(ifModifiedSince);
|
|
717
|
+
|
|
687
718
|
const [schema, session] = args;
|
|
688
719
|
const { startKeySuffix, endKeySuffix } = this.queryLastModifiedSuffixes(
|
|
689
720
|
schema,
|
|
@@ -708,7 +739,7 @@ export class GraffitiLocalDatabase
|
|
|
708
739
|
|
|
709
740
|
for await (const result of iterator) yield result;
|
|
710
741
|
|
|
711
|
-
return startTime
|
|
742
|
+
return startTime;
|
|
712
743
|
}
|
|
713
744
|
|
|
714
745
|
protected discoverCursor(
|