Upgrading to the PouchDb indexedDb adapter while testing signals in web workers...
This commit is contained in:
parent
e73497265f
commit
4a4ebdff50
|
@ -35,6 +35,7 @@
|
|||
"osmtogeojson": "^3.0.0-beta.5",
|
||||
"patch-package": "^6.5.1",
|
||||
"pouchdb": "^8.0.1",
|
||||
"pouchdb-adapter-indexeddb": "^8.0.1",
|
||||
"pouchdb-browser": "^8.0.1",
|
||||
"proj4": "^2.8.1",
|
||||
"solid-js": "^1.6.10",
|
||||
|
@ -7095,6 +7096,40 @@
|
|||
"vuvuzela": "1.0.3"
|
||||
}
|
||||
},
|
||||
"node_modules/pouchdb-adapter-indexeddb": {
|
||||
"version": "8.0.1",
|
||||
"resolved": "https://registry.npmjs.org/pouchdb-adapter-indexeddb/-/pouchdb-adapter-indexeddb-8.0.1.tgz",
|
||||
"integrity": "sha512-pX4FdL2isG4uhYXXnBUQJnkwcu+mBUjN/TW+B6aQhU+b/ZpLzH1XU/aui3/X604vhyOwy+DE4MsZEIsohUkR4g==",
|
||||
"dependencies": {
|
||||
"pouchdb-adapter-utils": "8.0.1",
|
||||
"pouchdb-binary-utils": "8.0.1",
|
||||
"pouchdb-errors": "8.0.1",
|
||||
"pouchdb-md5": "8.0.1",
|
||||
"pouchdb-merge": "8.0.1",
|
||||
"pouchdb-utils": "8.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/pouchdb-adapter-utils": {
|
||||
"version": "8.0.1",
|
||||
"resolved": "https://registry.npmjs.org/pouchdb-adapter-utils/-/pouchdb-adapter-utils-8.0.1.tgz",
|
||||
"integrity": "sha512-2nTeYaImu958BU4e46SSdv0IdkXYS/PSy5CXyfb7jK9g0aBAp/JRi7qh9nsTjk4FewpT6OpaE/7evxMQa7UuMg==",
|
||||
"dependencies": {
|
||||
"pouchdb-binary-utils": "8.0.1",
|
||||
"pouchdb-collections": "8.0.1",
|
||||
"pouchdb-errors": "8.0.1",
|
||||
"pouchdb-md5": "8.0.1",
|
||||
"pouchdb-merge": "8.0.1",
|
||||
"pouchdb-utils": "8.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/pouchdb-binary-utils": {
|
||||
"version": "8.0.1",
|
||||
"resolved": "https://registry.npmjs.org/pouchdb-binary-utils/-/pouchdb-binary-utils-8.0.1.tgz",
|
||||
"integrity": "sha512-WsuR/S0aoUlcA0Alt99czkXsfuXWcrYXAcvGiTW02zawVXOafCnb/qHjA09TUaV0oy5HeHmYaNnDckoOUqspeA==",
|
||||
"dependencies": {
|
||||
"buffer-from": "1.1.2"
|
||||
}
|
||||
},
|
||||
"node_modules/pouchdb-browser": {
|
||||
"version": "8.0.1",
|
||||
"resolved": "https://registry.npmjs.org/pouchdb-browser/-/pouchdb-browser-8.0.1.tgz",
|
||||
|
@ -7106,6 +7141,46 @@
|
|||
"vuvuzela": "1.0.3"
|
||||
}
|
||||
},
|
||||
"node_modules/pouchdb-collections": {
|
||||
"version": "8.0.1",
|
||||
"resolved": "https://registry.npmjs.org/pouchdb-collections/-/pouchdb-collections-8.0.1.tgz",
|
||||
"integrity": "sha512-TlkQ2GGHJApJgL0b7bJMQcwX6eMfVenLeoK9mqHfC2fJssui+HWJJ5LYKHOWan11SeB90BQVFbO6rHN6CJQeDg=="
|
||||
},
|
||||
"node_modules/pouchdb-errors": {
|
||||
"version": "8.0.1",
|
||||
"resolved": "https://registry.npmjs.org/pouchdb-errors/-/pouchdb-errors-8.0.1.tgz",
|
||||
"integrity": "sha512-H+ZsQxcG/JV3Tn29gnM6c9+lRPCN91ZYOkoIICsLjVRYgOTzN1AvNUD/G5JCB+81aI/u3fxZec0LEaZh6g6NHA=="
|
||||
},
|
||||
"node_modules/pouchdb-md5": {
|
||||
"version": "8.0.1",
|
||||
"resolved": "https://registry.npmjs.org/pouchdb-md5/-/pouchdb-md5-8.0.1.tgz",
|
||||
"integrity": "sha512-shVcs/K/iilrcAhDEERpLIrGm/cnDVsXiocOzs7kycJEuBqYnLD9nj58VwWDcum26wfa8T9cznvEGE1jlYVNPQ==",
|
||||
"dependencies": {
|
||||
"pouchdb-binary-utils": "8.0.1",
|
||||
"spark-md5": "3.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/pouchdb-merge": {
|
||||
"version": "8.0.1",
|
||||
"resolved": "https://registry.npmjs.org/pouchdb-merge/-/pouchdb-merge-8.0.1.tgz",
|
||||
"integrity": "sha512-79dw6+K7js2+/kt9u4hKOkGCnz+ov0+yft2k21n6M+ylFEQyMKuWHEZRoFWr72o1vxwjhIXhUM1PB2PIdxIh0Q==",
|
||||
"dependencies": {
|
||||
"pouchdb-utils": "8.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/pouchdb-utils": {
|
||||
"version": "8.0.1",
|
||||
"resolved": "https://registry.npmjs.org/pouchdb-utils/-/pouchdb-utils-8.0.1.tgz",
|
||||
"integrity": "sha512-pWgxdk9EHVWJmjQoEvTe+ZlPXyjcuQ/vgLITN+RjGwcYhoQYUE1M0PksQd2dUP3V8lGS4+wrg9lEM/qSJPYcpw==",
|
||||
"dependencies": {
|
||||
"clone-buffer": "1.0.0",
|
||||
"immediate": "3.3.0",
|
||||
"pouchdb-collections": "8.0.1",
|
||||
"pouchdb-errors": "8.0.1",
|
||||
"pouchdb-md5": "8.0.1",
|
||||
"uuid": "8.3.2"
|
||||
}
|
||||
},
|
||||
"node_modules/pouchdb/node_modules/isarray": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
|
||||
|
|
|
@ -58,6 +58,7 @@
|
|||
"osmtogeojson": "^3.0.0-beta.5",
|
||||
"patch-package": "^6.5.1",
|
||||
"pouchdb": "^8.0.1",
|
||||
"pouchdb-adapter-indexeddb": "^8.0.1",
|
||||
"pouchdb-browser": "^8.0.1",
|
||||
"proj4": "^2.8.1",
|
||||
"solid-js": "^1.6.10",
|
||||
|
|
|
@ -0,0 +1,110 @@
|
|||
import { Signal } from 'solid-js';
|
||||
import PouchDB from 'pouchdb';
|
||||
|
||||
import { getSettings } from '../db/settings';
|
||||
import { delay } from '../lib/delay';
|
||||
|
||||
export const compactDb = async (p: { signal: Signal<any>; params: any }) => {
|
||||
const { signal, params } = p;
|
||||
const [, setStatus] = signal;
|
||||
console.log({ caller: 'compactDb', p });
|
||||
|
||||
const db = new PouchDB('dyomedea', { auto_compaction: true });
|
||||
const dbinfo = await db.info();
|
||||
const tasks = PouchDB.activeTasks.list();
|
||||
|
||||
setStatus({ status: 'starting', db: 'dyomedea', dbinfo, tasks });
|
||||
|
||||
return;
|
||||
const timerId = setInterval(async () => {
|
||||
const dbinfo = await db.info();
|
||||
const tasks = PouchDB.activeTasks.list();
|
||||
if (tasks.length > 0) {
|
||||
setStatus({ status: 'ongoing', db: 'dyomedea', dbinfo, tasks });
|
||||
} else {
|
||||
setStatus({ status: 'terminated', db: 'dyomedea', dbinfo, tasks });
|
||||
clearInterval(timerId);
|
||||
}
|
||||
}, 1000);
|
||||
|
||||
const openIDb = (name: string) =>
|
||||
new Promise((resolve, reject) => {
|
||||
const iDb = indexedDB.open(name);
|
||||
iDb.onerror = (event: any) => {
|
||||
console.error({
|
||||
caller: 'compactDb',
|
||||
message: 'open db error',
|
||||
target: event.target,
|
||||
});
|
||||
reject(event.target.errorCode);
|
||||
};
|
||||
|
||||
iDb.onsuccess = (event: any) => {
|
||||
console.log({
|
||||
caller: 'compactDb',
|
||||
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: 'compactDb',
|
||||
message: 'getAll error',
|
||||
target: event.target,
|
||||
});
|
||||
reject(event.target.errorCode);
|
||||
};
|
||||
|
||||
request.onsuccess = (event: any) => {
|
||||
console.log({
|
||||
caller: 'compactDb',
|
||||
message: 'getAll',
|
||||
target: event.target,
|
||||
});
|
||||
resolve(event.target.result as any[]);
|
||||
};
|
||||
});
|
||||
|
||||
const iDb = (await openIDb('_pouch_dyomedea')) as IDBDatabase;
|
||||
|
||||
const bySequence = iDb.transaction('by-sequence', 'readonly');
|
||||
const store = bySequence.objectStore('by-sequence');
|
||||
console.log({
|
||||
caller: 'compactDb',
|
||||
message: 'transaction opened',
|
||||
bySequence,
|
||||
store,
|
||||
});
|
||||
|
||||
const sequences = (await getAll(store)) as any[];
|
||||
setStatus({
|
||||
status: 'revisions',
|
||||
db: 'dyomedea',
|
||||
sequences,
|
||||
});
|
||||
|
||||
sequences.forEach(async (sequence) => {
|
||||
const { _deleted, _doc_id_rev } = sequence;
|
||||
if (_deleted) {
|
||||
const [id, rev] = _doc_id_rev.split('::');
|
||||
// const purge = await db.purge(id, rev);
|
||||
console.log({
|
||||
caller: 'compactDb',
|
||||
message: 'purging',
|
||||
id,
|
||||
rev,
|
||||
sequence,
|
||||
purge,
|
||||
});
|
||||
await delay(100);
|
||||
}
|
||||
});
|
||||
|
||||
// db.compact();
|
||||
};
|
|
@ -4,7 +4,7 @@ import getUri from '../lib/ids';
|
|||
export const initialAccount = {
|
||||
id: 'initial',
|
||||
name: '???',
|
||||
localDb: 'dyomedea',
|
||||
localDb: '_dyomedea_',
|
||||
};
|
||||
|
||||
export const getAccounts = async () => {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import _ from 'lodash';
|
||||
import PouchDB from 'pouchdb';
|
||||
import indexeddb from 'pouchdb-adapter-indexeddb';
|
||||
import uri from '../lib/ids';
|
||||
import { toHex } from '../lib/to-hex';
|
||||
import {
|
||||
|
@ -11,6 +12,8 @@ import {
|
|||
import changeHandler from './change-handler';
|
||||
import { getSettings, putSettings } from './settings';
|
||||
|
||||
PouchDB.plugin(indexeddb);
|
||||
|
||||
const dbDefinitionId = uri('dbdef', {});
|
||||
|
||||
const currentDbDefinition = {
|
||||
|
@ -29,7 +32,8 @@ export const initDb = async (params: any) => {
|
|||
console.log({ caller: 'initDb' });
|
||||
|
||||
if (globalThis.localDb === undefined) {
|
||||
globalThis.localDb = new PouchDB('$local_dyomedea$', {
|
||||
globalThis.localDb = new PouchDB('_local_dyomedea_', {
|
||||
adapter: 'indexeddb',
|
||||
auto_compaction: true,
|
||||
revs_limit: 10,
|
||||
});
|
||||
|
@ -55,10 +59,20 @@ export const initDb = async (params: any) => {
|
|||
|
||||
if (globalThis.db === undefined) {
|
||||
globalThis.db = new PouchDB(currentAccount.localDb, {
|
||||
auto_compaction: false,
|
||||
adapter: 'indexeddb',
|
||||
auto_compaction: true,
|
||||
});
|
||||
}
|
||||
const db = globalThis.db;
|
||||
const dbinfo = await db.info();
|
||||
// db.compact();
|
||||
console.log({
|
||||
caller: 'initDb',
|
||||
dbinfo,
|
||||
activeTasks: PouchDB.activeTasks.list(),
|
||||
storage: await navigator.storage.estimate(),
|
||||
});
|
||||
//
|
||||
var previousDbDefinition = {
|
||||
_id: dbDefinitionId,
|
||||
type: dbDefinitionId,
|
||||
|
@ -150,5 +164,11 @@ export const initDb = async (params: any) => {
|
|||
|
||||
// changes.cancel();
|
||||
|
||||
console.log({
|
||||
caller: 'initDb (end)',
|
||||
dbinfo,
|
||||
activeTasks: PouchDB.activeTasks.list(),
|
||||
storage: await navigator.storage.estimate(),
|
||||
});
|
||||
globalThis.dbReady = true;
|
||||
};
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import { cloneDeep, debounce, memoize, property, wrap } from 'lodash';
|
||||
import { delay } from '../lib/delay';
|
||||
import getUri from '../lib/ids';
|
||||
import { appendToArray, putNewGpx } from './gpx';
|
||||
import { putNewGpx } from './gpx';
|
||||
import { getFamily, put } from './lib';
|
||||
|
||||
export const emptyRte: Rte = {
|
||||
|
|
|
@ -10,6 +10,9 @@ import dict from './i18n';
|
|||
|
||||
import App from './App';
|
||||
import { Language } from '@suid/icons-material';
|
||||
import { createWorkerSignal } from './solid-workers/solid-worker-main';
|
||||
import { createEffect } from 'solid-js';
|
||||
import dispatch from './workers/dispatcher-main';
|
||||
|
||||
// See https://stackoverflow.com/questions/71538643/property-wakelock-does-not-exist-on-type-navigator
|
||||
const requestWakeLock = async () => {
|
||||
|
@ -55,6 +58,20 @@ const getLanguage = () => {
|
|||
|
||||
const i18nDict = createI18nContext(dict, getLanguage());
|
||||
|
||||
const settings: any = await dispatch({
|
||||
action: 'getSettings',
|
||||
});
|
||||
const accounts: any = await dispatch({
|
||||
action: 'getAccounts',
|
||||
});
|
||||
const [compactDbStatus] = createWorkerSignal({
|
||||
provider: 'compactDb',
|
||||
params: { settings, accounts },
|
||||
});
|
||||
createEffect(() => {
|
||||
console.log({ caller: 'createEffect', compactDbStatus: compactDbStatus() });
|
||||
});
|
||||
|
||||
render(
|
||||
() => (
|
||||
<Router>
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
export const delay = (ms: number) =>
|
||||
new Promise((resolve) => setTimeout(resolve, ms));
|
|
@ -0,0 +1 @@
|
|||
declare module 'pouchdb-adapter-indexeddb';
|
|
@ -0,0 +1,73 @@
|
|||
import { createSignal, Signal } from 'solid-js';
|
||||
|
||||
declare global {
|
||||
var exportQueue: Map<string, any>;
|
||||
}
|
||||
|
||||
let worker: Worker;
|
||||
|
||||
const init = () => {
|
||||
console.log({ caller: 'solid-worker-main / init' });
|
||||
globalThis.exportQueue = new Map<
|
||||
string,
|
||||
{ count: number; signal: Signal<any> }
|
||||
>();
|
||||
|
||||
worker = new Worker(new URL('./solid-worker', import.meta.url), {
|
||||
type: 'module',
|
||||
});
|
||||
|
||||
worker.onmessage = (event: any) => {
|
||||
const { _id, _updatedValue } = event.data;
|
||||
console.log({
|
||||
caller: 'solid-worker-main / message received',
|
||||
_id,
|
||||
_updatedValue,
|
||||
});
|
||||
if (!globalThis.exportQueue.get(_id)) {
|
||||
console.error({
|
||||
caller: 'solid-worker-main / message received',
|
||||
message: 'not found',
|
||||
_id,
|
||||
_updatedValue,
|
||||
});
|
||||
}
|
||||
const signal = globalThis.exportQueue.get(_id).signal;
|
||||
signal[1](_updatedValue);
|
||||
};
|
||||
};
|
||||
|
||||
export const createWorkerSignal = (parameters: {
|
||||
provider: string;
|
||||
params?: any;
|
||||
initialValue?: any;
|
||||
}) => {
|
||||
if (!worker) {
|
||||
init();
|
||||
}
|
||||
const { provider, params, initialValue } = parameters;
|
||||
const id = JSON.stringify({ provider, params });
|
||||
if (globalThis.exportQueue.has(id)) {
|
||||
globalThis.exportQueue.get(id).count++;
|
||||
return globalThis.exportQueue.get(id).signal;
|
||||
}
|
||||
const signal = createSignal(initialValue);
|
||||
globalThis.exportQueue.set(id, { signal, count: 1 });
|
||||
worker.postMessage({ ...parameters, _id: id });
|
||||
return signal;
|
||||
};
|
||||
|
||||
export const releaseWorkerSignal = (parameters: {
|
||||
provider: string;
|
||||
params: any;
|
||||
}) => {
|
||||
const { provider, params } = parameters;
|
||||
const id = JSON.stringify({ provider, params });
|
||||
if (globalThis.exportQueue.has(id)) {
|
||||
globalThis.exportQueue.get(id).count--;
|
||||
if (globalThis.exportQueue.get(id).count === 0) {
|
||||
globalThis.exportQueue.delete(id);
|
||||
worker.postMessage({ ...parameters, _id: id, _release: true });
|
||||
}
|
||||
}
|
||||
};
|
|
@ -0,0 +1,59 @@
|
|||
import { createEffect, createRoot, createSignal, Signal } from 'solid-js';
|
||||
import { compactDb } from '../db-admin/compact';
|
||||
|
||||
declare global {
|
||||
var importQueue: Map<string, any>;
|
||||
}
|
||||
|
||||
globalThis.importQueue = new Map<string, Signal<any>>();
|
||||
|
||||
const providers = {
|
||||
compactDb,
|
||||
};
|
||||
|
||||
onmessage = function (e) {
|
||||
createRoot((dispose) => {
|
||||
const { provider, params, initialValue, _release, _id } = e.data;
|
||||
console.log({
|
||||
caller: 'solid-worker / onmessage',
|
||||
e,
|
||||
provider,
|
||||
params,
|
||||
initialValue,
|
||||
_release,
|
||||
_id,
|
||||
});
|
||||
|
||||
if (_release) {
|
||||
dispose();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Object.hasOwn(providers, provider)) {
|
||||
console.error({
|
||||
caller: 'solid-worker',
|
||||
message: 'Unknown provider',
|
||||
provider,
|
||||
});
|
||||
}
|
||||
|
||||
const signal = createSignal(initialValue);
|
||||
// globalThis.importQueue.set(_id, signal); // Would be needed for bidirectional signals...
|
||||
|
||||
createEffect(() => {
|
||||
console.log({
|
||||
caller: 'solid_worker / effect',
|
||||
provider,
|
||||
params,
|
||||
initialValue,
|
||||
_release,
|
||||
currentValue: signal[0](),
|
||||
_id,
|
||||
});
|
||||
postMessage({ _id, _updatedValue: signal[0]() });
|
||||
});
|
||||
|
||||
const providerFunction = providers[provider as keyof typeof providers];
|
||||
providerFunction({ params, signal });
|
||||
});
|
||||
};
|
Loading…
Reference in New Issue