From 89689c5ed6d5277b8d8772b1326e1a1869de195a Mon Sep 17 00:00:00 2001 From: evlist Date: Sun, 12 Feb 2023 10:46:26 +0100 Subject: [PATCH] Porting db health to single worker mode. --- src/db-admin/health-legacy.ts | 189 ++++++++++++++++++++++++++++++++++ src/db/index.ts | 65 ++++++------ 2 files changed, 218 insertions(+), 36 deletions(-) create mode 100644 src/db-admin/health-legacy.ts diff --git a/src/db-admin/health-legacy.ts b/src/db-admin/health-legacy.ts new file mode 100644 index 0000000..226b8e9 --- /dev/null +++ b/src/db-admin/health-legacy.ts @@ -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({}); + const [syncState, setSyncState] = createSignal({}); + + 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); + // } + // }); + }); +}; diff --git a/src/db/index.ts b/src/db/index.ts index 434ce50..6b507cd 100644 --- a/src/db/index.ts +++ b/src/db/index.ts @@ -1,17 +1,9 @@ import _ from 'lodash'; import PouchDB from 'pouchdb'; -import indexeddb from 'pouchdb-adapter-indexeddb'; +import { watchDbLegacy } from '../db-admin/health-legacy'; import { openDatabases } from '../db-admin/open'; -import uri from '../lib/ids'; import { toHex } from '../lib/to-hex'; -import { - getAccountById, - getAccounts, - initialAccount, - putAccount, -} from './account'; import changeHandler from './change-handler'; -import { getSettings, putSettings } from './settings'; declare global { var localDb: any; @@ -51,33 +43,33 @@ export const initDb = async () => { }); } - if (globalThis.sync) { - globalThis.sync - .on('change', function (info) { - // handle change - console.log({ caller: 'Sync / change', info }); - }) - .on('paused', function (err) { - // replication paused (e.g. replication up to date, user went offline) - console.log({ caller: 'Sync / paused', err }); - }) - .on('active', function () { - // replicate resumed (e.g. new changes replicating, user went back online) - 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 }); - }); - } + // if (globalThis.sync) { + // globalThis.sync + // .on('change', function (info) { + // // handle change + // console.log({ caller: 'Sync / change', info }); + // }) + // .on('paused', function (err) { + // // replication paused (e.g. replication up to date, user went offline) + // console.log({ caller: 'Sync / paused', err }); + // }) + // .on('active', function () { + // // replicate resumed (e.g. new changes replicating, user went back online) + // 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 }); + // }); + // } // console.log({ caller: 'initDb / before db.changes' }); @@ -106,5 +98,6 @@ export const initDb = async () => { // changes.cancel(); globalThis.dbReady = true; + watchDbLegacy(); } };