@powersync/common 1.45.0 → 1.46.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/dist/bundle.cjs +412 -2067
- package/dist/bundle.cjs.map +1 -1
- package/dist/bundle.mjs +410 -2068
- package/dist/bundle.mjs.map +1 -1
- package/dist/bundle.node.cjs +237 -63
- package/dist/bundle.node.cjs.map +1 -1
- package/dist/bundle.node.mjs +235 -64
- package/dist/bundle.node.mjs.map +1 -1
- package/dist/index.d.cts +94 -15
- package/lib/client/AbstractPowerSyncDatabase.d.ts +9 -2
- package/lib/client/AbstractPowerSyncDatabase.js +18 -5
- package/lib/client/AbstractPowerSyncDatabase.js.map +1 -1
- package/lib/client/sync/stream/AbstractRemote.js +41 -32
- package/lib/client/sync/stream/AbstractRemote.js.map +1 -1
- package/lib/client/sync/stream/AbstractStreamingSyncImplementation.d.ts +7 -12
- package/lib/client/sync/stream/AbstractStreamingSyncImplementation.js +10 -12
- package/lib/client/sync/stream/AbstractStreamingSyncImplementation.js.map +1 -1
- package/lib/client/triggers/MemoryTriggerClaimManager.d.ts +6 -0
- package/lib/client/triggers/MemoryTriggerClaimManager.js +21 -0
- package/lib/client/triggers/MemoryTriggerClaimManager.js.map +1 -0
- package/lib/client/triggers/TriggerManager.d.ts +37 -0
- package/lib/client/triggers/TriggerManagerImpl.d.ts +24 -3
- package/lib/client/triggers/TriggerManagerImpl.js +133 -11
- package/lib/client/triggers/TriggerManagerImpl.js.map +1 -1
- package/lib/index.d.ts +3 -0
- package/lib/index.js +3 -0
- package/lib/index.js.map +1 -1
- package/lib/utils/DataStream.js +11 -2
- package/lib/utils/DataStream.js.map +1 -1
- package/package.json +4 -3
- package/src/client/AbstractPowerSyncDatabase.ts +21 -6
- package/src/client/sync/stream/AbstractRemote.ts +47 -35
- package/src/client/sync/stream/AbstractStreamingSyncImplementation.ts +11 -14
- package/src/client/triggers/MemoryTriggerClaimManager.ts +25 -0
- package/src/client/triggers/TriggerManager.ts +50 -6
- package/src/client/triggers/TriggerManagerImpl.ts +177 -13
- package/src/index.ts +3 -0
- package/src/utils/DataStream.ts +13 -2
package/lib/utils/DataStream.js
CHANGED
|
@@ -67,6 +67,16 @@ export class DataStream extends BaseObserver {
|
|
|
67
67
|
* @returns a Data payload or Null if the stream closed.
|
|
68
68
|
*/
|
|
69
69
|
async read() {
|
|
70
|
+
if (this.closed) {
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
// Wait for any pending processing to complete first.
|
|
74
|
+
// This ensures we register our listener before calling processQueue(),
|
|
75
|
+
// avoiding a race where processQueue() sees no reader and returns early.
|
|
76
|
+
if (this.processingPromise) {
|
|
77
|
+
await this.processingPromise;
|
|
78
|
+
}
|
|
79
|
+
// Re-check after await - stream may have closed while we were waiting
|
|
70
80
|
if (this.closed) {
|
|
71
81
|
return null;
|
|
72
82
|
}
|
|
@@ -106,7 +116,7 @@ export class DataStream extends BaseObserver {
|
|
|
106
116
|
}
|
|
107
117
|
const promise = (this.processingPromise = this._processQueue());
|
|
108
118
|
promise.finally(() => {
|
|
109
|
-
|
|
119
|
+
this.processingPromise = null;
|
|
110
120
|
});
|
|
111
121
|
return promise;
|
|
112
122
|
}
|
|
@@ -138,7 +148,6 @@ export class DataStream extends BaseObserver {
|
|
|
138
148
|
this.notifyDataAdded = null;
|
|
139
149
|
}
|
|
140
150
|
if (this.dataQueue.length > 0) {
|
|
141
|
-
// Next tick
|
|
142
151
|
setTimeout(() => this.processQueue());
|
|
143
152
|
}
|
|
144
153
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DataStream.js","sourceRoot":"","sources":["../../src/utils/DataStream.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"DataStream.js","sourceRoot":"","sources":["../../src/utils/DataStream.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@powersync/common",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.46.0",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"registry": "https://registry.npmjs.org/",
|
|
6
6
|
"access": "public"
|
|
@@ -56,10 +56,11 @@
|
|
|
56
56
|
"@rollup/plugin-inject": "^5.0.5",
|
|
57
57
|
"@rollup/plugin-json": "^6.1.0",
|
|
58
58
|
"@rollup/plugin-node-resolve": "^16.0.3",
|
|
59
|
-
"@types/node": "^
|
|
60
|
-
"@types/uuid": "^9.0.
|
|
59
|
+
"@types/node": "^24.0.0",
|
|
60
|
+
"@types/uuid": "^9.0.6",
|
|
61
61
|
"buffer": "^6.0.3",
|
|
62
62
|
"rollup": "^4.52.5",
|
|
63
|
+
"rollup-plugin-dts": "^6.2.1",
|
|
63
64
|
"cross-fetch": "^4.1.0",
|
|
64
65
|
"js-logger": "^1.6.1",
|
|
65
66
|
"rsocket-core": "1.0.0-alpha.3",
|
|
@@ -40,7 +40,8 @@ import {
|
|
|
40
40
|
} from './sync/stream/AbstractStreamingSyncImplementation.js';
|
|
41
41
|
import { CoreSyncStatus, coreStatusToJs } from './sync/stream/core-instruction.js';
|
|
42
42
|
import { SyncStream } from './sync/sync-streams.js';
|
|
43
|
-
import {
|
|
43
|
+
import { MEMORY_TRIGGER_CLAIM_MANAGER } from './triggers/MemoryTriggerClaimManager.js';
|
|
44
|
+
import { TriggerManager, TriggerManagerConfig } from './triggers/TriggerManager.js';
|
|
44
45
|
import { TriggerManagerImpl } from './triggers/TriggerManagerImpl.js';
|
|
45
46
|
import { DEFAULT_WATCH_THROTTLE_MS, WatchCompatibleQuery } from './watched/WatchedQuery.js';
|
|
46
47
|
import { OnChangeQueryProcessor } from './watched/processors/OnChangeQueryProcessor.js';
|
|
@@ -222,6 +223,7 @@ export abstract class AbstractPowerSyncDatabase extends BaseObserver<PowerSyncDB
|
|
|
222
223
|
* Allows creating SQLite triggers which can be used to track various operations on SQLite tables.
|
|
223
224
|
*/
|
|
224
225
|
readonly triggers: TriggerManager;
|
|
226
|
+
protected triggersImpl: TriggerManagerImpl;
|
|
225
227
|
|
|
226
228
|
logger: ILogger;
|
|
227
229
|
|
|
@@ -296,9 +298,10 @@ export abstract class AbstractPowerSyncDatabase extends BaseObserver<PowerSyncDB
|
|
|
296
298
|
|
|
297
299
|
this._isReadyPromise = this.initialize();
|
|
298
300
|
|
|
299
|
-
this.triggers = new TriggerManagerImpl({
|
|
301
|
+
this.triggers = this.triggersImpl = new TriggerManagerImpl({
|
|
300
302
|
db: this,
|
|
301
|
-
schema: this.schema
|
|
303
|
+
schema: this.schema,
|
|
304
|
+
...this.generateTriggerManagerConfig()
|
|
302
305
|
});
|
|
303
306
|
}
|
|
304
307
|
|
|
@@ -334,6 +337,16 @@ export abstract class AbstractPowerSyncDatabase extends BaseObserver<PowerSyncDB
|
|
|
334
337
|
*/
|
|
335
338
|
protected abstract openDBAdapter(options: PowerSyncDatabaseOptionsWithSettings): DBAdapter;
|
|
336
339
|
|
|
340
|
+
/**
|
|
341
|
+
* Generates a base configuration for {@link TriggerManagerImpl}.
|
|
342
|
+
* Implementations should override this if necessary.
|
|
343
|
+
*/
|
|
344
|
+
protected generateTriggerManagerConfig(): TriggerManagerConfig {
|
|
345
|
+
return {
|
|
346
|
+
claimManager: MEMORY_TRIGGER_CLAIM_MANAGER
|
|
347
|
+
};
|
|
348
|
+
}
|
|
349
|
+
|
|
337
350
|
protected abstract generateSyncStreamImplementation(
|
|
338
351
|
connector: PowerSyncBackendConnector,
|
|
339
352
|
options: CreateSyncImplementationOptions & RequiredAdditionalConnectionOptions
|
|
@@ -416,15 +429,16 @@ export abstract class AbstractPowerSyncDatabase extends BaseObserver<PowerSyncDB
|
|
|
416
429
|
protected async initialize() {
|
|
417
430
|
await this._initialize();
|
|
418
431
|
await this.bucketStorageAdapter.init();
|
|
419
|
-
await this.
|
|
432
|
+
await this.loadVersion();
|
|
420
433
|
await this.updateSchema(this.options.schema);
|
|
421
434
|
await this.resolveOfflineSyncStatus();
|
|
422
435
|
await this.database.execute('PRAGMA RECURSIVE_TRIGGERS=TRUE');
|
|
436
|
+
await this.triggersImpl.cleanupResources();
|
|
423
437
|
this.ready = true;
|
|
424
438
|
this.iterateListeners((cb) => cb.initialized?.());
|
|
425
439
|
}
|
|
426
440
|
|
|
427
|
-
|
|
441
|
+
protected async loadVersion() {
|
|
428
442
|
try {
|
|
429
443
|
const { version } = await this.database.get<{ version: string }>('SELECT powersync_rs_version() as version');
|
|
430
444
|
this.sdkVersion = version;
|
|
@@ -560,7 +574,6 @@ export abstract class AbstractPowerSyncDatabase extends BaseObserver<PowerSyncDB
|
|
|
560
574
|
|
|
561
575
|
const { clearLocal } = options;
|
|
562
576
|
|
|
563
|
-
// TODO DB name, verify this is necessary with extension
|
|
564
577
|
await this.database.writeTransaction(async (tx) => {
|
|
565
578
|
await tx.execute('SELECT powersync_clear(?)', [clearLocal ? 1 : 0]);
|
|
566
579
|
});
|
|
@@ -597,6 +610,8 @@ export abstract class AbstractPowerSyncDatabase extends BaseObserver<PowerSyncDB
|
|
|
597
610
|
return;
|
|
598
611
|
}
|
|
599
612
|
|
|
613
|
+
this.triggersImpl.dispose();
|
|
614
|
+
|
|
600
615
|
await this.iterateAsyncListeners(async (cb) => cb.closing?.());
|
|
601
616
|
|
|
602
617
|
const { disconnect } = options;
|
|
@@ -573,7 +573,11 @@ export abstract class AbstractRemote {
|
|
|
573
573
|
|
|
574
574
|
const stream = new DataStream<T, string>({
|
|
575
575
|
logger: this.logger,
|
|
576
|
-
mapLine: mapLine
|
|
576
|
+
mapLine: mapLine,
|
|
577
|
+
pressure: {
|
|
578
|
+
highWaterMark: 20,
|
|
579
|
+
lowWaterMark: 10
|
|
580
|
+
}
|
|
577
581
|
});
|
|
578
582
|
|
|
579
583
|
abortSignal?.addEventListener('abort', () => {
|
|
@@ -585,46 +589,54 @@ export abstract class AbstractRemote {
|
|
|
585
589
|
let buffer = '';
|
|
586
590
|
|
|
587
591
|
|
|
592
|
+
const consumeStream = async () => {
|
|
593
|
+
while (!stream.closed && !abortSignal?.aborted && !readerReleased) {
|
|
594
|
+
const { done, value } = await reader.read();
|
|
595
|
+
if (done) {
|
|
596
|
+
const remaining = buffer.trim();
|
|
597
|
+
if (remaining.length != 0) {
|
|
598
|
+
stream.enqueueData(remaining);
|
|
599
|
+
}
|
|
588
600
|
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
}
|
|
594
|
-
try {
|
|
595
|
-
let didCompleteLine = false;
|
|
596
|
-
while (!didCompleteLine) {
|
|
597
|
-
const { done, value } = await reader.read();
|
|
598
|
-
if (done) {
|
|
599
|
-
const remaining = buffer.trim();
|
|
600
|
-
if (remaining.length != 0) {
|
|
601
|
-
stream.enqueueData(remaining);
|
|
602
|
-
}
|
|
601
|
+
stream.close();
|
|
602
|
+
await closeReader();
|
|
603
|
+
return;
|
|
604
|
+
}
|
|
603
605
|
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
return;
|
|
607
|
-
}
|
|
606
|
+
const data = decoder.decode(value, { stream: true });
|
|
607
|
+
buffer += data;
|
|
608
608
|
|
|
609
|
-
|
|
610
|
-
|
|
609
|
+
const lines = buffer.split('\n');
|
|
610
|
+
for (var i = 0; i < lines.length - 1; i++) {
|
|
611
|
+
var l = lines[i].trim();
|
|
612
|
+
if (l.length > 0) {
|
|
613
|
+
stream.enqueueData(l);
|
|
614
|
+
}
|
|
615
|
+
}
|
|
611
616
|
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
617
|
+
buffer = lines[lines.length - 1];
|
|
618
|
+
|
|
619
|
+
// Implement backpressure by waiting for the low water mark to be reached
|
|
620
|
+
if (stream.dataQueue.length > stream.highWatermark) {
|
|
621
|
+
await new Promise<void>((resolve) => {
|
|
622
|
+
const dispose = stream.registerListener({
|
|
623
|
+
lowWater: async () => {
|
|
624
|
+
resolve();
|
|
625
|
+
dispose();
|
|
626
|
+
},
|
|
627
|
+
closed: () => {
|
|
628
|
+
resolve();
|
|
629
|
+
dispose();
|
|
618
630
|
}
|
|
619
|
-
}
|
|
620
|
-
|
|
621
|
-
buffer = lines[lines.length - 1];
|
|
622
|
-
}
|
|
623
|
-
} catch (ex) {
|
|
624
|
-
stream.close();
|
|
625
|
-
throw ex;
|
|
631
|
+
})
|
|
632
|
+
})
|
|
626
633
|
}
|
|
627
|
-
}
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
consumeStream().catch(ex => this.logger.error('Error consuming stream', ex));
|
|
638
|
+
|
|
639
|
+
const l = stream.registerListener({
|
|
628
640
|
closed: () => {
|
|
629
641
|
closeReader();
|
|
630
642
|
l?.();
|
|
@@ -47,18 +47,17 @@ export enum SyncClientImplementation {
|
|
|
47
47
|
*
|
|
48
48
|
* This is the default option.
|
|
49
49
|
*
|
|
50
|
-
* @deprecated
|
|
51
|
-
*
|
|
52
|
-
*
|
|
50
|
+
* @deprecated We recommend the {@link RUST} client implementation for all apps. If you have issues with
|
|
51
|
+
* the Rust client, please file an issue or reach out to us. The JavaScript client will be removed in a future
|
|
52
|
+
* version of the PowerSync SDK.
|
|
53
53
|
*/
|
|
54
54
|
JAVASCRIPT = 'js',
|
|
55
55
|
/**
|
|
56
56
|
* This implementation offloads the sync line decoding and handling into the PowerSync
|
|
57
57
|
* core extension.
|
|
58
58
|
*
|
|
59
|
-
* @
|
|
60
|
-
*
|
|
61
|
-
* it has seen less real-world testing and is marked as __experimental__ at the moment.
|
|
59
|
+
* This option is more performant than the {@link JAVASCRIPT} client, enabled by default and the
|
|
60
|
+
* recommended client implementation for all apps.
|
|
62
61
|
*
|
|
63
62
|
* ## Compatibility warning
|
|
64
63
|
*
|
|
@@ -77,13 +76,9 @@ export enum SyncClientImplementation {
|
|
|
77
76
|
}
|
|
78
77
|
|
|
79
78
|
/**
|
|
80
|
-
* The default {@link SyncClientImplementation} to use.
|
|
81
|
-
*
|
|
82
|
-
* Please use this field instead of {@link SyncClientImplementation.JAVASCRIPT} directly. A future version
|
|
83
|
-
* of the PowerSync SDK will enable {@link SyncClientImplementation.RUST} by default and remove the JavaScript
|
|
84
|
-
* option.
|
|
79
|
+
* The default {@link SyncClientImplementation} to use, {@link SyncClientImplementation.RUST}.
|
|
85
80
|
*/
|
|
86
|
-
export const DEFAULT_SYNC_CLIENT_IMPLEMENTATION = SyncClientImplementation.
|
|
81
|
+
export const DEFAULT_SYNC_CLIENT_IMPLEMENTATION = SyncClientImplementation.RUST;
|
|
87
82
|
|
|
88
83
|
/**
|
|
89
84
|
* Abstract Lock to be implemented by various JS environments
|
|
@@ -194,8 +189,7 @@ export interface RequiredAdditionalConnectionOptions extends Required<Additional
|
|
|
194
189
|
}
|
|
195
190
|
|
|
196
191
|
export interface StreamingSyncImplementation
|
|
197
|
-
extends BaseObserverInterface<StreamingSyncImplementationListener>,
|
|
198
|
-
Disposable {
|
|
192
|
+
extends BaseObserverInterface<StreamingSyncImplementationListener>, Disposable {
|
|
199
193
|
/**
|
|
200
194
|
* Connects to the sync service
|
|
201
195
|
*/
|
|
@@ -693,6 +687,9 @@ The next upload iteration will be delayed.`);
|
|
|
693
687
|
if (rawTables != null && rawTables.length) {
|
|
694
688
|
this.logger.warn('Raw tables require the Rust-based sync client. The JS client will ignore them.');
|
|
695
689
|
}
|
|
690
|
+
if (this.activeStreams.length) {
|
|
691
|
+
this.logger.error('Sync streams require `clientImplementation: SyncClientImplementation.RUST` when connecting.');
|
|
692
|
+
}
|
|
696
693
|
|
|
697
694
|
this.logger.debug('Streaming sync iteration started');
|
|
698
695
|
this.options.adapter.startSession();
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { TriggerClaimManager } from './TriggerManager.js';
|
|
2
|
+
|
|
3
|
+
const CLAIM_STORE = new Map<string, () => Promise<void>>();
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @internal
|
|
7
|
+
* @experimental
|
|
8
|
+
*/
|
|
9
|
+
export const MEMORY_TRIGGER_CLAIM_MANAGER: TriggerClaimManager = {
|
|
10
|
+
async obtainClaim(identifier: string): Promise<() => Promise<void>> {
|
|
11
|
+
if (CLAIM_STORE.has(identifier)) {
|
|
12
|
+
throw new Error(`A claim is already present for ${identifier}`);
|
|
13
|
+
}
|
|
14
|
+
const release = async () => {
|
|
15
|
+
CLAIM_STORE.delete(identifier);
|
|
16
|
+
};
|
|
17
|
+
CLAIM_STORE.set(identifier, release);
|
|
18
|
+
|
|
19
|
+
return release;
|
|
20
|
+
},
|
|
21
|
+
|
|
22
|
+
async checkClaim(identifier: string): Promise<boolean> {
|
|
23
|
+
return CLAIM_STORE.has(identifier);
|
|
24
|
+
}
|
|
25
|
+
};
|
|
@@ -47,8 +47,9 @@ export interface BaseTriggerDiffRecord<TOperationId extends string | number = nu
|
|
|
47
47
|
* This record contains the new value and optionally the previous value.
|
|
48
48
|
* Values are stored as JSON strings.
|
|
49
49
|
*/
|
|
50
|
-
export interface TriggerDiffUpdateRecord<
|
|
51
|
-
extends
|
|
50
|
+
export interface TriggerDiffUpdateRecord<
|
|
51
|
+
TOperationId extends string | number = number
|
|
52
|
+
> extends BaseTriggerDiffRecord<TOperationId> {
|
|
52
53
|
operation: DiffTriggerOperation.UPDATE;
|
|
53
54
|
/**
|
|
54
55
|
* The updated state of the row in JSON string format.
|
|
@@ -65,8 +66,9 @@ export interface TriggerDiffUpdateRecord<TOperationId extends string | number =
|
|
|
65
66
|
* Represents a diff record for a SQLite INSERT operation.
|
|
66
67
|
* This record contains the new value represented as a JSON string.
|
|
67
68
|
*/
|
|
68
|
-
export interface TriggerDiffInsertRecord<
|
|
69
|
-
extends
|
|
69
|
+
export interface TriggerDiffInsertRecord<
|
|
70
|
+
TOperationId extends string | number = number
|
|
71
|
+
> extends BaseTriggerDiffRecord<TOperationId> {
|
|
70
72
|
operation: DiffTriggerOperation.INSERT;
|
|
71
73
|
/**
|
|
72
74
|
* The value of the row, at the time of INSERT, in JSON string format.
|
|
@@ -79,8 +81,9 @@ export interface TriggerDiffInsertRecord<TOperationId extends string | number =
|
|
|
79
81
|
* Represents a diff record for a SQLite DELETE operation.
|
|
80
82
|
* This record contains the new value represented as a JSON string.
|
|
81
83
|
*/
|
|
82
|
-
export interface TriggerDiffDeleteRecord<
|
|
83
|
-
extends
|
|
84
|
+
export interface TriggerDiffDeleteRecord<
|
|
85
|
+
TOperationId extends string | number = number
|
|
86
|
+
> extends BaseTriggerDiffRecord<TOperationId> {
|
|
84
87
|
operation: DiffTriggerOperation.DELETE;
|
|
85
88
|
/**
|
|
86
89
|
* The value of the row, before the DELETE operation, in JSON string format.
|
|
@@ -201,6 +204,12 @@ interface BaseCreateDiffTriggerOptions {
|
|
|
201
204
|
* Hooks which allow execution during the trigger creation process.
|
|
202
205
|
*/
|
|
203
206
|
hooks?: TriggerCreationHooks;
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Use storage-backed (non-TEMP) tables and triggers that persist across sessions.
|
|
210
|
+
* These resources are still automatically disposed when no longer claimed.
|
|
211
|
+
*/
|
|
212
|
+
useStorage?: boolean;
|
|
204
213
|
}
|
|
205
214
|
|
|
206
215
|
/**
|
|
@@ -449,3 +458,38 @@ export interface TriggerManager {
|
|
|
449
458
|
*/
|
|
450
459
|
trackTableDiff(options: TrackDiffOptions): Promise<TriggerRemoveCallback>;
|
|
451
460
|
}
|
|
461
|
+
|
|
462
|
+
/**
|
|
463
|
+
* @experimental
|
|
464
|
+
* @internal
|
|
465
|
+
* Manages claims on persisted SQLite triggers and destination tables to enable proper cleanup
|
|
466
|
+
* when they are no longer actively in use.
|
|
467
|
+
*
|
|
468
|
+
* When using persisted triggers (especially for OPFS multi-tab scenarios), we need a reliable way to determine which resources are still actively in use across different connections/tabs so stale resources can be safely cleaned up without interfering with active triggers.
|
|
469
|
+
*
|
|
470
|
+
* A cleanup process runs
|
|
471
|
+
* on database creation (and every 2 minutes) that:
|
|
472
|
+
* 1. Queries for existing managed persisted resources
|
|
473
|
+
* 2. Checks with the claim manager if any consumer is actively using those resources
|
|
474
|
+
* 3. Deletes unused resources
|
|
475
|
+
*/
|
|
476
|
+
|
|
477
|
+
export interface TriggerClaimManager {
|
|
478
|
+
/**
|
|
479
|
+
* Obtains or marks a claim on a certain identifier.
|
|
480
|
+
* @returns a callback to release the claim.
|
|
481
|
+
*/
|
|
482
|
+
obtainClaim: (identifier: string) => Promise<() => Promise<void>>;
|
|
483
|
+
/**
|
|
484
|
+
* Checks if a claim is present for an identifier.
|
|
485
|
+
*/
|
|
486
|
+
checkClaim: (identifier: string) => Promise<boolean>;
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
/**
|
|
490
|
+
* @experimental
|
|
491
|
+
* @internal
|
|
492
|
+
*/
|
|
493
|
+
export interface TriggerManagerConfig {
|
|
494
|
+
claimManager: TriggerClaimManager;
|
|
495
|
+
}
|