rxdb
Version:
A local-first realtime NoSQL Database for JavaScript applications - https://rxdb.info/
93 lines (85 loc) • 3.09 kB
text/typescript
import type { RxCleanupPolicy, RxState } from '../../types/index.d.ts';
import { PROMISE_RESOLVE_TRUE } from '../../plugins/utils/index.ts';
import { REPLICATION_STATE_BY_COLLECTION } from '../replication/index.ts';
import { DEFAULT_CLEANUP_POLICY } from './cleanup-helper.ts';
import { initialCleanupWait } from './cleanup.ts';
import { firstValueFrom } from 'rxjs';
let RXSTATE_CLEANUP_QUEUE: Promise<any> = PROMISE_RESOLVE_TRUE;
export async function startCleanupForRxState(state: RxState<unknown, unknown>) {
const rxCollection = state.collection;
const rxDatabase = rxCollection.database;
const cleanupPolicy = Object.assign(
{},
DEFAULT_CLEANUP_POLICY,
rxDatabase.cleanupPolicy ? rxDatabase.cleanupPolicy : {}
);
await initialCleanupWait(rxCollection, cleanupPolicy);
if (rxCollection.closed) {
return;
}
// initially cleanup the state
await cleanupRxState(state, cleanupPolicy);
/**
* Afterwards we listen to writes
* and only re-run the cleanup if there was a write
* to the state.
*/
await runCleanupAfterWrite(state, cleanupPolicy);
}
/**
* Runs the cleanup for a single RxState
*/
export async function cleanupRxState(
state: RxState<unknown, unknown>,
cleanupPolicy: RxCleanupPolicy
) {
const rxCollection = state.collection;
const rxDatabase = rxCollection.database;
// run cleanup() until it returns true
let isDone = false;
while (!isDone && !rxCollection.closed) {
if (cleanupPolicy.awaitReplicationsInSync) {
const replicationStates = REPLICATION_STATE_BY_COLLECTION.get(rxCollection);
if (replicationStates) {
await Promise.all(
replicationStates.map(replicationState => {
if (!replicationState.isStopped()) {
return replicationState.awaitInSync();
}
})
);
}
}
if (rxCollection.closed) {
return;
}
RXSTATE_CLEANUP_QUEUE = RXSTATE_CLEANUP_QUEUE
.then(async () => {
if (rxCollection.closed) {
return true;
}
await rxDatabase.requestIdlePromise();
return state._cleanup();
});
isDone = await RXSTATE_CLEANUP_QUEUE;
}
}
export async function runCleanupAfterWrite(
state: RxState<unknown, unknown>,
cleanupPolicy: RxCleanupPolicy
) {
const rxCollection = state.collection;
while (!rxCollection.closed) {
/**
* We only start the timer if there was actually a write
* to the collection. Otherwise the cleanup would
* just run on intervals even if nothing has changed.
*/
await firstValueFrom(rxCollection.eventBulks$).catch(() => { });
await rxCollection.promiseWait(cleanupPolicy.runEach);
if (rxCollection.closed) {
return;
}
await cleanupRxState(state, cleanupPolicy);
}
}