@loro-dev/flock-sqlite 0.5.0 → 0.6.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@loro-dev/flock-sqlite",
3
- "version": "0.5.0",
3
+ "version": "0.6.0",
4
4
  "description": "SQLite-backed Flock CRDT replica for Node, browsers, and Cloudflare Workers.",
5
5
  "type": "module",
6
6
  "exports": {
@@ -62,7 +62,7 @@
62
62
  "tsdown": "^0.15.4",
63
63
  "typescript": "^5.9.2",
64
64
  "vitest": "^3.2.4",
65
- "@loro-dev/flock": "4.3.0"
65
+ "@loro-dev/flock": "4.4.0"
66
66
  },
67
67
  "scripts": {
68
68
  "build": "tsdown",
package/src/index.ts CHANGED
@@ -635,7 +635,9 @@ export class FlockSQLite {
635
635
  private debounceState:
636
636
  | {
637
637
  timeout: number;
638
+ maxDebounceTime: number;
638
639
  timerId: ReturnType<typeof setTimeout> | undefined;
640
+ maxTimerId: ReturnType<typeof setTimeout> | undefined;
639
641
  pendingEvents: Array<{
640
642
  key: KeyPart[];
641
643
  payload: ExportPayload;
@@ -969,6 +971,17 @@ export class FlockSQLite {
969
971
  this.debounceState.timerId = setTimeout(() => {
970
972
  this.commit();
971
973
  }, this.debounceState.timeout);
974
+
975
+ // Start max debounce timer on first pending event
976
+ // Note: this is called after the event is pushed, so length === 1 means first event
977
+ if (
978
+ this.debounceState.maxTimerId === undefined &&
979
+ this.debounceState.pendingEvents.length === 1
980
+ ) {
981
+ this.debounceState.maxTimerId = setTimeout(() => {
982
+ this.commit();
983
+ }, this.debounceState.maxDebounceTime);
984
+ }
972
985
  }
973
986
 
974
987
  private emitEvents(
@@ -1740,6 +1753,7 @@ export class FlockSQLite {
1740
1753
  * Import operations will automatically call `commit()` before proceeding.
1741
1754
  *
1742
1755
  * @param timeout - Debounce timeout in milliseconds
1756
+ * @param options - Optional configuration object with maxDebounceTime (default: 10000ms)
1743
1757
  * @throws Error if called while a transaction is active
1744
1758
  * @throws Error if autoDebounceCommit is already active
1745
1759
  *
@@ -1750,9 +1764,13 @@ export class FlockSQLite {
1750
1764
  * await flock.put(["b"], 2);
1751
1765
  * // No events emitted yet...
1752
1766
  * // After 100ms of inactivity, subscribers receive single EventBatch
1767
+ * // If operations keep coming, commit happens after maxDebounceTime (10s default)
1753
1768
  * ```
1754
1769
  */
1755
- autoDebounceCommit(timeout: number): void {
1770
+ autoDebounceCommit(
1771
+ timeout: number,
1772
+ options?: { maxDebounceTime?: number },
1773
+ ): void {
1756
1774
  if (this.txnEventSink !== undefined) {
1757
1775
  throw new Error(
1758
1776
  "Cannot enable autoDebounceCommit while transaction is active",
@@ -1762,9 +1780,13 @@ export class FlockSQLite {
1762
1780
  throw new Error("autoDebounceCommit is already active");
1763
1781
  }
1764
1782
 
1783
+ const maxDebounceTime = options?.maxDebounceTime ?? 10000;
1784
+
1765
1785
  this.debounceState = {
1766
1786
  timeout,
1787
+ maxDebounceTime,
1767
1788
  timerId: undefined,
1789
+ maxTimerId: undefined,
1768
1790
  pendingEvents: [],
1769
1791
  };
1770
1792
  }
@@ -1778,10 +1800,13 @@ export class FlockSQLite {
1778
1800
  return;
1779
1801
  }
1780
1802
 
1781
- const { timerId, pendingEvents } = this.debounceState;
1803
+ const { timerId, maxTimerId, pendingEvents } = this.debounceState;
1782
1804
  if (timerId !== undefined) {
1783
1805
  clearTimeout(timerId);
1784
1806
  }
1807
+ if (maxTimerId !== undefined) {
1808
+ clearTimeout(maxTimerId);
1809
+ }
1785
1810
  this.debounceState = undefined;
1786
1811
 
1787
1812
  if (pendingEvents.length > 0) {
@@ -1799,11 +1824,15 @@ export class FlockSQLite {
1799
1824
  return;
1800
1825
  }
1801
1826
 
1802
- const { timerId, pendingEvents } = this.debounceState;
1827
+ const { timerId, maxTimerId, pendingEvents } = this.debounceState;
1803
1828
  if (timerId !== undefined) {
1804
1829
  clearTimeout(timerId);
1805
1830
  this.debounceState.timerId = undefined;
1806
1831
  }
1832
+ if (maxTimerId !== undefined) {
1833
+ clearTimeout(maxTimerId);
1834
+ this.debounceState.maxTimerId = undefined;
1835
+ }
1807
1836
 
1808
1837
  if (pendingEvents.length > 0) {
1809
1838
  this.emitEvents("local", pendingEvents);