@powersync/web 1.38.7 → 1.39.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.umd.js +344 -83
- package/dist/index.umd.js.map +1 -1
- package/dist/worker/SharedSyncImplementation.umd.js +18 -9
- package/dist/worker/SharedSyncImplementation.umd.js.map +1 -1
- package/dist/worker/WASQLiteDB.umd.js +94 -60
- package/dist/worker/WASQLiteDB.umd.js.map +1 -1
- package/dist/worker/node_modules_pnpm_journeyapps_wa-sqlite_1_7_0_node_modules_journeyapps_wa-sqlite_src_examples-833585.umd.js +1400 -0
- package/dist/worker/node_modules_pnpm_journeyapps_wa-sqlite_1_7_0_node_modules_journeyapps_wa-sqlite_src_examples-833585.umd.js.map +1 -0
- package/lib/package.json +2 -2
- package/lib/src/db/adapters/AsyncWebAdapter.js +1 -1
- package/lib/src/db/adapters/AsyncWebAdapter.js.map +1 -1
- package/lib/src/db/adapters/wa-sqlite/RawSqliteConnection.d.ts +8 -1
- package/lib/src/db/adapters/wa-sqlite/RawSqliteConnection.js +13 -9
- package/lib/src/db/adapters/wa-sqlite/RawSqliteConnection.js.map +1 -1
- package/lib/src/db/adapters/wa-sqlite/WASQLiteOpenFactory.js +8 -2
- package/lib/src/db/adapters/wa-sqlite/WASQLiteOpenFactory.js.map +1 -1
- package/lib/src/db/adapters/wa-sqlite/vfs.d.ts +20 -30
- package/lib/src/db/adapters/wa-sqlite/vfs.js +57 -39
- package/lib/src/db/adapters/wa-sqlite/vfs.js.map +1 -1
- package/lib/src/db/sync/SharedWebStreamingSyncImplementation.d.ts +1 -0
- package/lib/src/db/sync/SharedWebStreamingSyncImplementation.js +10 -5
- package/lib/src/db/sync/SharedWebStreamingSyncImplementation.js.map +1 -1
- package/lib/src/worker/db/MultiDatabaseServer.js +5 -3
- package/lib/src/worker/db/MultiDatabaseServer.js.map +1 -1
- package/lib/src/worker/db/open-worker-database.d.ts +3 -2
- package/lib/src/worker/db/open-worker-database.js +30 -22
- package/lib/src/worker/db/open-worker-database.js.map +1 -1
- package/lib/src/worker/errors.d.ts +2 -0
- package/lib/src/worker/errors.js +7 -0
- package/lib/src/worker/errors.js.map +1 -0
- package/lib/src/worker/sync/SharedSyncImplementation.d.ts +1 -0
- package/lib/src/worker/sync/SharedSyncImplementation.js +2 -1
- package/lib/src/worker/sync/SharedSyncImplementation.js.map +1 -1
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +3 -3
- package/src/db/adapters/AsyncWebAdapter.ts +1 -1
- package/src/db/adapters/wa-sqlite/RawSqliteConnection.ts +15 -11
- package/src/db/adapters/wa-sqlite/WASQLiteOpenFactory.ts +24 -9
- package/src/db/adapters/wa-sqlite/vfs.ts +67 -54
- package/src/db/sync/SharedWebStreamingSyncImplementation.ts +17 -11
- package/src/worker/db/MultiDatabaseServer.ts +5 -3
- package/src/worker/db/open-worker-database.ts +34 -22
- package/src/worker/errors.ts +9 -0
- package/src/worker/sync/SharedSyncImplementation.ts +3 -1
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type * as SQLite from '@journeyapps/wa-sqlite';
|
|
2
|
+
import { ResolvedWASQLiteOpenFactoryOptions } from './WASQLiteOpenFactory.js';
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* List of currently tested virtual filesystems
|
|
@@ -7,31 +8,36 @@ export enum WASQLiteVFS {
|
|
|
7
8
|
IDBBatchAtomicVFS = 'IDBBatchAtomicVFS',
|
|
8
9
|
OPFSCoopSyncVFS = 'OPFSCoopSyncVFS',
|
|
9
10
|
AccessHandlePoolVFS = 'AccessHandlePoolVFS',
|
|
10
|
-
OPFSWriteAheadVFS = 'OPFSWriteAheadVFS'
|
|
11
|
+
OPFSWriteAheadVFS = 'OPFSWriteAheadVFS',
|
|
12
|
+
/**
|
|
13
|
+
* A virtual file system storing data in-memory only, without persistence.
|
|
14
|
+
*
|
|
15
|
+
* This file system can be used in three configurations:
|
|
16
|
+
*
|
|
17
|
+
* 1. In shared workers (the default when available): All tabs share the same in-memory database, which is cleared
|
|
18
|
+
* once the last tab is closed.
|
|
19
|
+
* 2. In dedicated workers (used when `enableMultiTabs` is disabled). Each tab has its own in-memory database cleared
|
|
20
|
+
* when the tab is closed. Queries are offloaded to a dedicated worker.
|
|
21
|
+
* 3. In the context of the tab itself (used when both `enableMultiTabs` and `useWebWorker` are disabled). The per-tab
|
|
22
|
+
* database is hosted in the tab itself, and queries run synchronously. This is _a lot_ faster than any other
|
|
23
|
+
* single-threadedVFS, but can block JavaScript for computationally-intensive queries.
|
|
24
|
+
*
|
|
25
|
+
* This VFS primarily intended for development, but it also useful for online-first deployments not syncing large
|
|
26
|
+
* amounts of data, as it is quicker to start up.
|
|
27
|
+
*/
|
|
28
|
+
InMemoryVfs = 'InMemoryVFS'
|
|
11
29
|
}
|
|
12
30
|
|
|
13
31
|
export function vfsRequiresDedicatedWorkers(vfs: WASQLiteVFS) {
|
|
14
|
-
return vfs != WASQLiteVFS.IDBBatchAtomicVFS;
|
|
32
|
+
return vfs != WASQLiteVFS.IDBBatchAtomicVFS && vfs != WASQLiteVFS.InMemoryVfs;
|
|
15
33
|
}
|
|
16
34
|
|
|
17
|
-
/**
|
|
18
|
-
* @internal
|
|
19
|
-
*/
|
|
20
|
-
export type WASQLiteModuleFactoryOptions = { dbFileName: string; encryptionKey?: string };
|
|
21
|
-
|
|
22
35
|
/**
|
|
23
36
|
* @internal
|
|
24
37
|
*/
|
|
25
38
|
export type SQLiteModule = Parameters<typeof SQLite.Factory>[0];
|
|
26
39
|
|
|
27
|
-
|
|
28
|
-
* @internal
|
|
29
|
-
*/
|
|
30
|
-
export type WASQLiteModuleFactory = (
|
|
31
|
-
options: WASQLiteModuleFactoryOptions
|
|
32
|
-
) => Promise<{ module: SQLiteModule; vfs: SQLiteVFS }>;
|
|
33
|
-
|
|
34
|
-
async function asyncModuleFactory(encryptionKey: unknown) {
|
|
40
|
+
async function asyncModuleFactory(encryptionKey: string | undefined): Promise<SQLiteModule> {
|
|
35
41
|
if (encryptionKey) {
|
|
36
42
|
const { default: factory } = await import('@journeyapps/wa-sqlite/dist/mc-wa-sqlite-async.mjs');
|
|
37
43
|
return factory();
|
|
@@ -41,7 +47,7 @@ async function asyncModuleFactory(encryptionKey: unknown) {
|
|
|
41
47
|
}
|
|
42
48
|
}
|
|
43
49
|
|
|
44
|
-
async function syncModuleFactory(encryptionKey:
|
|
50
|
+
async function syncModuleFactory(encryptionKey: string | undefined): Promise<SQLiteModule> {
|
|
45
51
|
if (encryptionKey) {
|
|
46
52
|
const { default: factory } = await import('@journeyapps/wa-sqlite/dist/mc-wa-sqlite.mjs');
|
|
47
53
|
return factory();
|
|
@@ -54,43 +60,50 @@ async function syncModuleFactory(encryptionKey: unknown) {
|
|
|
54
60
|
/**
|
|
55
61
|
* @internal
|
|
56
62
|
*/
|
|
57
|
-
export
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
+
export async function loadModuleAndVfs({
|
|
64
|
+
vfs,
|
|
65
|
+
dbFilename,
|
|
66
|
+
encryptionKey
|
|
67
|
+
}: ResolvedWASQLiteOpenFactoryOptions): Promise<{ module: SQLiteModule; vfs: SQLiteVFS }> {
|
|
68
|
+
let moduleFactory = syncModuleFactory;
|
|
69
|
+
let resolveVfs: (module: any) => Promise<SQLiteVFS>;
|
|
70
|
+
|
|
71
|
+
switch (vfs) {
|
|
72
|
+
case WASQLiteVFS.IDBBatchAtomicVFS: {
|
|
73
|
+
moduleFactory = asyncModuleFactory;
|
|
74
|
+
const { IDBBatchAtomicVFS } = await import('@journeyapps/wa-sqlite/src/examples/IDBBatchAtomicVFS.js');
|
|
75
|
+
resolveVfs = (module) => {
|
|
76
|
+
// @ts-expect-error The types for this static method are missing upstream
|
|
77
|
+
return IDBBatchAtomicVFS.create(dbFilename, module, { lockPolicy: 'exclusive' });
|
|
78
|
+
};
|
|
79
|
+
break;
|
|
80
|
+
}
|
|
81
|
+
case WASQLiteVFS.AccessHandlePoolVFS: {
|
|
82
|
+
// @ts-expect-error The types for this import are missing upstream
|
|
83
|
+
const { AccessHandlePoolVFS } = await import('@journeyapps/wa-sqlite/src/examples/AccessHandlePoolVFS.js');
|
|
84
|
+
resolveVfs = (module) => AccessHandlePoolVFS.create(dbFilename, module);
|
|
85
|
+
break;
|
|
86
|
+
}
|
|
87
|
+
case WASQLiteVFS.OPFSCoopSyncVFS: {
|
|
88
|
+
// @ts-expect-error The types for this import are missing upstream
|
|
89
|
+
const { OPFSCoopSyncVFS } = await import('@journeyapps/wa-sqlite/src/examples/OPFSCoopSyncVFS.js');
|
|
90
|
+
resolveVfs = (module) => OPFSCoopSyncVFS.create(dbFilename, module);
|
|
91
|
+
break;
|
|
92
|
+
}
|
|
93
|
+
case WASQLiteVFS.OPFSWriteAheadVFS: {
|
|
94
|
+
// @ts-expect-error The types for this import are missing upstream
|
|
95
|
+
const { OPFSWriteAheadVFS } = await import('@journeyapps/wa-sqlite/src/examples/OPFSWriteAheadVFS.js');
|
|
96
|
+
resolveVfs = (module) => OPFSWriteAheadVFS.create(dbFilename, module, {});
|
|
97
|
+
break;
|
|
98
|
+
}
|
|
99
|
+
case WASQLiteVFS.InMemoryVfs: {
|
|
100
|
+
const { MemoryVFS } = await import('@journeyapps/wa-sqlite/src/examples/MemoryVFS.js');
|
|
63
101
|
// @ts-expect-error The types for this static method are missing upstream
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
[WASQLiteVFS.AccessHandlePoolVFS]: async (options: WASQLiteModuleFactoryOptions) => {
|
|
68
|
-
const module = await syncModuleFactory(options.encryptionKey);
|
|
69
|
-
// @ts-expect-error The types for this static method are missing upstream
|
|
70
|
-
const { AccessHandlePoolVFS } = await import('@journeyapps/wa-sqlite/src/examples/AccessHandlePoolVFS.js');
|
|
71
|
-
return {
|
|
72
|
-
module,
|
|
73
|
-
vfs: await AccessHandlePoolVFS.create(options.dbFileName, module)
|
|
74
|
-
};
|
|
75
|
-
},
|
|
76
|
-
[WASQLiteVFS.OPFSCoopSyncVFS]: async (options: WASQLiteModuleFactoryOptions) => {
|
|
77
|
-
const module = await syncModuleFactory(options.encryptionKey);
|
|
78
|
-
// @ts-expect-error The types for this static method are missing upstream
|
|
79
|
-
const { OPFSCoopSyncVFS } = await import('@journeyapps/wa-sqlite/src/examples/OPFSCoopSyncVFS.js');
|
|
80
|
-
const vfs = await OPFSCoopSyncVFS.create(options.dbFileName, module);
|
|
81
|
-
return {
|
|
82
|
-
module,
|
|
83
|
-
vfs
|
|
84
|
-
};
|
|
85
|
-
},
|
|
86
|
-
[WASQLiteVFS.OPFSWriteAheadVFS]: async (options: WASQLiteModuleFactoryOptions) => {
|
|
87
|
-
const module = await syncModuleFactory(options.encryptionKey);
|
|
88
|
-
// @ts-expect-error The types for this static method are missing upstream
|
|
89
|
-
const { OPFSWriteAheadVFS } = await import('@journeyapps/wa-sqlite/src/examples/OPFSWriteAheadVFS.js');
|
|
90
|
-
const vfs = await OPFSWriteAheadVFS.create(options.dbFileName, module, {});
|
|
91
|
-
return {
|
|
92
|
-
module,
|
|
93
|
-
vfs
|
|
94
|
-
};
|
|
102
|
+
resolveVfs = (module) => MemoryVFS.create(dbFilename, module);
|
|
103
|
+
break;
|
|
104
|
+
}
|
|
95
105
|
}
|
|
96
|
-
|
|
106
|
+
|
|
107
|
+
const module = await moduleFactory(encryptionKey);
|
|
108
|
+
return { module, vfs: await resolveVfs(module) };
|
|
109
|
+
}
|
|
@@ -5,7 +5,6 @@ import {
|
|
|
5
5
|
SyncStatusOptions
|
|
6
6
|
} from '@powersync/common';
|
|
7
7
|
import * as Comlink from 'comlink';
|
|
8
|
-
import { getNavigatorLocks } from '../../shared/navigator.js';
|
|
9
8
|
import { AbstractSharedSyncClientProvider } from '../../worker/sync/AbstractSharedSyncClientProvider.js';
|
|
10
9
|
import { ManualSharedSyncPayload, SharedSyncClientEvent } from '../../worker/sync/SharedSyncImplementation.js';
|
|
11
10
|
import { WorkerClient } from '../../worker/sync/WorkerClient.js';
|
|
@@ -16,6 +15,7 @@ import {
|
|
|
16
15
|
WebStreamingSyncImplementationOptions
|
|
17
16
|
} from './WebStreamingSyncImplementation.js';
|
|
18
17
|
import { generateTabCloseSignal } from '../../shared/tab_close_signal.js';
|
|
18
|
+
import { logWorkerErrors } from '../../worker/errors.js';
|
|
19
19
|
|
|
20
20
|
/**
|
|
21
21
|
* The shared worker will trigger methods on this side of the message port
|
|
@@ -128,22 +128,23 @@ export class SharedWebStreamingSyncImplementation extends WebStreamingSyncImplem
|
|
|
128
128
|
const syncWorker = options.sync?.worker;
|
|
129
129
|
if (syncWorker) {
|
|
130
130
|
if (typeof syncWorker === 'function') {
|
|
131
|
-
this.messagePort = syncWorker(resolvedWorkerOptions)
|
|
131
|
+
this.messagePort = this.workerPort(syncWorker(resolvedWorkerOptions));
|
|
132
132
|
} else {
|
|
133
|
-
this.messagePort =
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
133
|
+
this.messagePort = this.workerPort(
|
|
134
|
+
new SharedWorker(`${syncWorker}`, {
|
|
135
|
+
/* @vite-ignore */
|
|
136
|
+
name: `shared-sync-${this.webOptions.identifier}`
|
|
137
|
+
})
|
|
138
|
+
);
|
|
137
139
|
}
|
|
138
140
|
} else {
|
|
139
|
-
this.messagePort =
|
|
140
|
-
new URL('../../worker/sync/SharedSyncImplementation.worker.js', import.meta.url),
|
|
141
|
-
{
|
|
141
|
+
this.messagePort = this.workerPort(
|
|
142
|
+
new SharedWorker(new URL('../../worker/sync/SharedSyncImplementation.worker.js', import.meta.url), {
|
|
142
143
|
/* @vite-ignore */
|
|
143
144
|
name: `shared-sync-${this.webOptions.identifier}`,
|
|
144
145
|
type: 'module'
|
|
145
|
-
}
|
|
146
|
-
)
|
|
146
|
+
})
|
|
147
|
+
);
|
|
147
148
|
}
|
|
148
149
|
|
|
149
150
|
/**
|
|
@@ -179,6 +180,11 @@ export class SharedWebStreamingSyncImplementation extends WebStreamingSyncImplem
|
|
|
179
180
|
this.isInitialized = this._init();
|
|
180
181
|
}
|
|
181
182
|
|
|
183
|
+
private workerPort(worker: SharedWorker): MessagePort {
|
|
184
|
+
logWorkerErrors(worker, this.logger);
|
|
185
|
+
return worker.port;
|
|
186
|
+
}
|
|
187
|
+
|
|
182
188
|
protected async _init() {
|
|
183
189
|
/**
|
|
184
190
|
* The general flow of initialization is:
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
import { getNavigatorLocks } from '../../shared/navigator.js';
|
|
9
9
|
import { RawSqliteConnection } from '../../db/adapters/wa-sqlite/RawSqliteConnection.js';
|
|
10
10
|
import { ConcurrentSqliteConnection } from '../../db/adapters/wa-sqlite/ConcurrentConnection.js';
|
|
11
|
+
import { WASQLiteVFS } from '../../db/adapters/wa-sqlite/vfs.js';
|
|
11
12
|
|
|
12
13
|
const OPEN_DB_LOCK = 'open-wasqlite-db';
|
|
13
14
|
|
|
@@ -57,14 +58,15 @@ export class MultiDatabaseServer {
|
|
|
57
58
|
|
|
58
59
|
private async databaseOpenAttempt(options: ResolvedWASQLiteOpenFactoryOptions): Promise<DatabaseServer> {
|
|
59
60
|
return getNavigatorLocks().request(OPEN_DB_LOCK, async () => {
|
|
60
|
-
const { dbFilename } = options;
|
|
61
|
+
const { dbFilename, isReadOnly, vfs } = options;
|
|
61
62
|
|
|
62
63
|
let server: DatabaseServer | undefined = this.activeDatabases.get(dbFilename);
|
|
63
64
|
if (server == null) {
|
|
64
65
|
// We don't need navigator locks for shared workers because all queries run in this shared worker exclusively.
|
|
65
66
|
// For read-only connections, we use a VFS that supports concurrent reads (so a single lock on the connection is
|
|
66
|
-
// fine).
|
|
67
|
-
|
|
67
|
+
// fine). In-memory databases either run in a shared worker or aren't shared across tabs at all, so the internal
|
|
68
|
+
// lock is enough.
|
|
69
|
+
const needsNavigatorLocks = !(isSharedWorker || isReadOnly || vfs == WASQLiteVFS.InMemoryVfs);
|
|
68
70
|
const connection = new RawSqliteConnection(options);
|
|
69
71
|
const withSafeConcurrency = new ConcurrentSqliteConnection(connection, needsNavigatorLocks);
|
|
70
72
|
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import * as Comlink from 'comlink';
|
|
2
2
|
import { vfsRequiresDedicatedWorkers, WASQLiteVFS } from '../../db/adapters/wa-sqlite/vfs.js';
|
|
3
3
|
import { OpenWorkerConnection } from '../../db/adapters/wa-sqlite/DatabaseClient.js';
|
|
4
|
+
import type { ILogger } from '@powersync/common';
|
|
5
|
+
import { logWorkerErrors } from '../errors.js';
|
|
4
6
|
|
|
5
7
|
/**
|
|
6
8
|
* Opens a shared or dedicated worker which exposes opening of database connections
|
|
@@ -9,20 +11,23 @@ export function openWorkerDatabasePort(
|
|
|
9
11
|
workerIdentifier: string,
|
|
10
12
|
multipleTabs = true,
|
|
11
13
|
worker: string | URL = '',
|
|
12
|
-
vfs?: WASQLiteVFS
|
|
14
|
+
vfs?: WASQLiteVFS,
|
|
15
|
+
logger?: ILogger
|
|
13
16
|
) {
|
|
14
17
|
const needsDedicated = vfs && vfsRequiresDedicatedWorkers(vfs);
|
|
18
|
+
let resolvedWorker: Worker | SharedWorker;
|
|
15
19
|
|
|
16
20
|
if (worker) {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
21
|
+
resolvedWorker =
|
|
22
|
+
!needsDedicated && multipleTabs
|
|
23
|
+
? new SharedWorker(`${worker}`, {
|
|
24
|
+
/* @vite-ignore */
|
|
25
|
+
name: `shared-DB-worker-${workerIdentifier}`
|
|
26
|
+
})
|
|
27
|
+
: new Worker(`${worker}`, {
|
|
28
|
+
/* @vite-ignore */
|
|
29
|
+
name: `DB-worker-${workerIdentifier}`
|
|
30
|
+
});
|
|
26
31
|
} else {
|
|
27
32
|
/**
|
|
28
33
|
* Webpack V5 can bundle the worker automatically if the full Worker constructor syntax is used
|
|
@@ -30,18 +35,21 @@ export function openWorkerDatabasePort(
|
|
|
30
35
|
* This enables multi tab support by default, but falls back if SharedWorker is not available
|
|
31
36
|
* (in the case of Android)
|
|
32
37
|
*/
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
38
|
+
resolvedWorker =
|
|
39
|
+
!needsDedicated && multipleTabs
|
|
40
|
+
? new SharedWorker(new URL('./WASQLiteDB.worker.js', import.meta.url), {
|
|
41
|
+
/* @vite-ignore */
|
|
42
|
+
name: `shared-DB-worker-${workerIdentifier}`,
|
|
43
|
+
type: 'module'
|
|
44
|
+
})
|
|
45
|
+
: new Worker(new URL('./WASQLiteDB.worker.js', import.meta.url), {
|
|
46
|
+
/* @vite-ignore */
|
|
47
|
+
name: `DB-worker-${workerIdentifier}`,
|
|
48
|
+
type: 'module'
|
|
49
|
+
});
|
|
44
50
|
}
|
|
51
|
+
|
|
52
|
+
return resolveWorkerDatabasePortFactory(() => resolvedWorker, logger);
|
|
45
53
|
}
|
|
46
54
|
|
|
47
55
|
/**
|
|
@@ -52,8 +60,12 @@ export function getWorkerDatabaseOpener(workerIdentifier: string, multipleTabs =
|
|
|
52
60
|
return Comlink.wrap<OpenWorkerConnection>(openWorkerDatabasePort(workerIdentifier, multipleTabs, worker));
|
|
53
61
|
}
|
|
54
62
|
|
|
55
|
-
export function resolveWorkerDatabasePortFactory(worker: () => Worker | SharedWorker) {
|
|
63
|
+
export function resolveWorkerDatabasePortFactory(worker: () => Worker | SharedWorker, logger?: ILogger) {
|
|
56
64
|
const workerInstance = worker();
|
|
65
|
+
if (logger) {
|
|
66
|
+
logWorkerErrors(workerInstance, logger);
|
|
67
|
+
}
|
|
68
|
+
|
|
57
69
|
return isSharedWorker(workerInstance) ? workerInstance.port : workerInstance;
|
|
58
70
|
}
|
|
59
71
|
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { ILogger } from '@powersync/common';
|
|
2
|
+
|
|
3
|
+
export function logWorkerErrors(worker: AbstractWorker, logger: ILogger) {
|
|
4
|
+
function logError(event: ErrorEvent) {
|
|
5
|
+
logger.error('Error in database or sync worker, this likely disrupts PowerSync.', event.error);
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
worker.addEventListener('error', logError);
|
|
9
|
+
}
|
|
@@ -122,6 +122,8 @@ export class SharedSyncImplementation extends BaseObserver<SharedSyncImplementat
|
|
|
122
122
|
broadCastLogger: ILogger;
|
|
123
123
|
protected readonly database = this.generateReconnectableDatabase();
|
|
124
124
|
|
|
125
|
+
private sharedCloseSignal = generateTabCloseSignal();
|
|
126
|
+
|
|
125
127
|
constructor() {
|
|
126
128
|
super();
|
|
127
129
|
this.ports = [];
|
|
@@ -508,7 +510,7 @@ export class SharedSyncImplementation extends BaseObserver<SharedSyncImplementat
|
|
|
508
510
|
const remote = Comlink.wrap<OpenWorkerConnection>(workerPort);
|
|
509
511
|
const identifier = this.syncParams!.dbParams.dbFilename;
|
|
510
512
|
|
|
511
|
-
const clientLockName = await
|
|
513
|
+
const clientLockName = await this.sharedCloseSignal;
|
|
512
514
|
|
|
513
515
|
/**
|
|
514
516
|
* The open could fail if the tab is closed while we're busy opening the database.
|