Porting db health to single worker mode.

This commit is contained in:
Eric van der Vlist 2023-02-12 10:46:26 +01:00
parent 0d86b789c1
commit 89689c5ed6
2 changed files with 218 additions and 36 deletions

View File

@ -0,0 +1,189 @@
import { createEffect, createRoot, createSignal, Signal } from 'solid-js';
import PouchDB from 'pouchdb';
import indexeddb from 'pouchdb-adapter-indexeddb';
import { sleep } from '../lib/async-wait';
import { openDatabases } from './open';
import { toHex } from '../lib/to-hex';
import { isEqual } from 'lodash';
PouchDB.plugin(indexeddb);
declare global {
var localDb: any;
var db: any;
var remoteDb: any;
var currentAccount: any;
var sync: any;
}
const [state, setState] = createSignal({});
export { state };
export const watchDbLegacy = async () => {
createRoot((dispose) => {
console.log({ caller: 'watchDbLegacy' });
db = globalThis.db;
localDb = globalThis.localDb;
const [status, setStatus] = createSignal<any>({});
const [syncState, setSyncState] = createSignal<any>({});
const updateStatus = async () => {
const dbInfo = await db.info();
const localDbInfo = await localDb.info();
const remoteDbInfo = globalThis.remoteDb
? await remoteDb.info()
: undefined;
const tasks = PouchDB.activeTasks.list();
const newStatus = {
...status(),
tasks,
dbInfo,
localDbInfo,
remoteDbInfo,
// date: new Date(),
};
if (!isEqual(status(), newStatus)) {
setStatus(newStatus);
}
};
createEffect(() => {
console.log({
caller: 'watchDbLegacy',
state: state(),
status: status(),
syncState: syncState(),
sync,
});
});
createEffect(() => {
const newState = { ...state(), sync: syncState() };
if (!isEqual(newState, state())) {
setState({
...state(),
localUpdateSeq: status()?.dbInfo?.update_seq,
remoteUrl: status()?.remoteDbInfo?.host,
sync: syncState(),
});
}
});
updateStatus();
if (globalThis.sync) {
globalThis.sync
.on('change', function (info) {
// handle change
console.log({ caller: 'Sync / change', info });
if (info.direction === 'push') {
setSyncState({ ...syncState(), lastSeq: info.change.last_seq });
}
})
.on('paused', function (err) {
// replication paused (e.g. replication up to date, user went offline)
setSyncState({ ...syncState(), paused: true });
console.log({ caller: 'Sync / paused', err });
})
.on('active', function () {
// replicate resumed (e.g. new changes replicating, user went back online)
setSyncState({ ...syncState(), paused: false });
console.log({ caller: 'Sync / active' });
})
.on('denied', function (err) {
// a document failed to replicate (e.g. due to permissions)
console.error({ caller: 'Sync / denied', err });
})
.on('complete', function (info) {
// handle complete
console.log({ caller: 'Sync / complete', info });
})
.on('error', function (err) {
// handle error
console.error({ caller: 'Sync / error', err });
});
}
const timerId = setInterval(updateStatus, 10000);
// db.compact();
// await sleep(10000);
const openIDb = (name: string) =>
new Promise((resolve, reject) => {
const iDb = indexedDB.open(name);
iDb.onerror = (event: any) => {
console.error({
caller: 'watchDb',
message: 'open db error',
target: event.target,
});
reject(event.target.errorCode);
};
iDb.onsuccess = (event: any) => {
console.log({
caller: 'watchDb',
message: 'open db',
target: event.target,
});
resolve(event.target.result);
};
});
const getAll = (store: any) =>
new Promise((resolve, reject) => {
const request = store.getAll();
request.onerror = (event: any) => {
console.error({
caller: 'watchDb',
message: 'getAll error',
target: event.target,
});
reject(event.target.errorCode);
};
request.onsuccess = (event: any) => {
console.log({
caller: 'watchDb',
message: 'getAll',
target: event.target,
});
resolve(event.target.result as any[]);
};
});
// const iDb = (await openIDb('_pouch__dyomedea_')) as IDBDatabase;
// const bySequence = iDb.transaction('docs', 'readonly');
// const store = bySequence.objectStore('docs');
// console.log({
// caller: 'watchDb',
// message: 'transaction opened',
// bySequence,
// store,
// });
// const docs = (await getAll(store)) as any[];
// docs.forEach(async (doc) => {
// const { id, rev, deleted } = doc;
// if (deleted !== 0) {
// // const purge = await db.purge(id, rev);
// console.log({
// caller: 'watchDb',
// message: 'purging',
// id,
// rev,
// doc,
// // purge,
// });
// await sleep(1000);
// }
// });
});
};

View File

@ -1,17 +1,9 @@
import _ from 'lodash'; import _ from 'lodash';
import PouchDB from 'pouchdb'; import PouchDB from 'pouchdb';
import indexeddb from 'pouchdb-adapter-indexeddb'; import { watchDbLegacy } from '../db-admin/health-legacy';
import { openDatabases } from '../db-admin/open'; import { openDatabases } from '../db-admin/open';
import uri from '../lib/ids';
import { toHex } from '../lib/to-hex'; import { toHex } from '../lib/to-hex';
import {
getAccountById,
getAccounts,
initialAccount,
putAccount,
} from './account';
import changeHandler from './change-handler'; import changeHandler from './change-handler';
import { getSettings, putSettings } from './settings';
declare global { declare global {
var localDb: any; var localDb: any;
@ -51,33 +43,33 @@ export const initDb = async () => {
}); });
} }
if (globalThis.sync) { // if (globalThis.sync) {
globalThis.sync // globalThis.sync
.on('change', function (info) { // .on('change', function (info) {
// handle change // // handle change
console.log({ caller: 'Sync / change', info }); // console.log({ caller: 'Sync / change', info });
}) // })
.on('paused', function (err) { // .on('paused', function (err) {
// replication paused (e.g. replication up to date, user went offline) // // replication paused (e.g. replication up to date, user went offline)
console.log({ caller: 'Sync / paused', err }); // console.log({ caller: 'Sync / paused', err });
}) // })
.on('active', function () { // .on('active', function () {
// replicate resumed (e.g. new changes replicating, user went back online) // // replicate resumed (e.g. new changes replicating, user went back online)
console.log({ caller: 'Sync / active' }); // console.log({ caller: 'Sync / active' });
}) // })
.on('denied', function (err) { // .on('denied', function (err) {
// a document failed to replicate (e.g. due to permissions) // // a document failed to replicate (e.g. due to permissions)
console.error({ caller: 'Sync / denied', err }); // console.error({ caller: 'Sync / denied', err });
}) // })
.on('complete', function (info) { // .on('complete', function (info) {
// handle complete // // handle complete
console.log({ caller: 'Sync / complete', info }); // console.log({ caller: 'Sync / complete', info });
}) // })
.on('error', function (err) { // .on('error', function (err) {
// handle error // // handle error
console.error({ caller: 'Sync / error', err }); // console.error({ caller: 'Sync / error', err });
}); // });
} // }
// console.log({ caller: 'initDb / before db.changes' }); // console.log({ caller: 'initDb / before db.changes' });
@ -106,5 +98,6 @@ export const initDb = async () => {
// changes.cancel(); // changes.cancel();
globalThis.dbReady = true; globalThis.dbReady = true;
watchDbLegacy();
} }
}; };