Upgrading to the PouchDb indexedDb adapter while testing signals in web workers...
This commit is contained in:
1 parent
e73497265f
commit
4a4ebdff50
11 files changed
+362
-5
No files matched your search
@@ -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();
|
||||
};
|
||||
+1
-1
@@ -4,7 +4,7 @@ import getUri from '../lib/ids';
|
||||
export const initialAccount = {
|
||||
id: 'initial',
|
||||
name: '???',
|
||||
localDb: 'dyomedea',
|
||||
localDb: '_dyomedea_',
|
||||
};
|
||||
|
||||
export const getAccounts = async () => {
|
||||
|
||||
+22
-2
@@ -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
-2
@@ -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 });
|
||||
});
|
||||
};
|
||||
Reference in new issue
Block a user