@serfab/quereus-plugin-sereus 1.18.0 → 1.19.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/README.md +5 -0
- package/dist/app-schema.d.ts +45 -0
- package/dist/app-schema.js +147 -0
- package/dist/app-schema.js.map +1 -0
- package/dist/compose-strand.d.ts +15 -19
- package/dist/compose-strand.js +75 -51
- package/dist/compose-strand.js.map +1 -1
- package/dist/connect-browser.d.ts +2 -0
- package/dist/connect-browser.js +10 -3
- package/dist/connect-browser.js.map +1 -1
- package/dist/index.d.ts +5 -2
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/plugin-browser.js +40 -40
- package/dist/plugin-browser.js.map +4 -4
- package/dist/strand-schema.d.ts +1 -1
- package/dist/strand-schema.js +8 -8
- package/dist/types.d.ts +49 -1
- package/package.json +8 -8
- package/src/app-schema.ts +172 -0
- package/src/compose-strand.ts +93 -56
- package/src/connect-browser.ts +10 -3
- package/src/index.ts +30 -18
- package/src/strand-schema.ts +8 -8
- package/src/types.ts +49 -1
package/README.md
CHANGED
|
@@ -274,6 +274,10 @@ on shutdown.
|
|
|
274
274
|
|
|
275
275
|
The result's `onCommitDurability(listener)` is called after every commit that wrote something, before the commit returns, with who holds what it wrote; `onCommitFullyHeld(listener)` is called once when a commit reported `followed` below full replication becomes held by its whole cohort. Both pass through from `@optimystic/quereus-plugin-optimystic`, whose README explains the report ([A commit's durability](https://github.com/gotchoices/optimystic/blob/main/packages/quereus-plugin-optimystic/README.md#a-commits-durability--pluginoncommitdurabilitylistener)); the `SqlCommitDurability` and `CommitFullyHeld` types are re-exported here. A cadre app reads the same reports through `@serfab/cadre-core` ([strands.md → A commit's durability](../../docs/strands.md#a-commits-durability)).
|
|
276
276
|
|
|
277
|
+
### Offline mode
|
|
278
|
+
|
|
279
|
+
With `offline` given, the result's `offline` is the queue's controller (`enter()`, `exit()`, `whenDrained()`, `onStatus(listener)`, `entries()`, …), passed through from `@optimystic/quereus-plugin-optimystic` ([Offline mode](https://github.com/gotchoices/optimystic/blob/main/packages/quereus-plugin-optimystic/README.md#offline-mode--pluginoffline)); `offlineControllerOf(db)` finds it from the `Database`, and the status, state and error types are re-exported here. The `Strand` tables are always acknowledged by the network, and an `App` schema apply that queued transactions refuse is retried once they drain rather than failing the connect: the result's `appSchema` settles with how it ended, and `appSchemaDeferredBy` names the transactions that refused it. Both, and where the queue is saved, are in [strands.md → Offline mode](../../docs/strands.md#offline-mode).
|
|
280
|
+
|
|
277
281
|
### Founding a strand: `createEmptyCollections()`
|
|
278
282
|
|
|
279
283
|
A table nobody has written has no collection, so no single machine can show it empty: every read of it asks the other members, and fails while they are offline. The result's `createEmptyCollections(except?)` commits an empty collection for every table the `Strand` and `App` schemas declare that has none yet, and resolves to how many it committed. `except` lists qualified tables (`'Strand.Header'`) the caller is about to write: their inserts create their collections, so every tree of those tables is left out, and a name matching no declared table throws. The founder calls it once, before its founding write, while no other machine can have written to the strand; cadre-core's founder bootstrap does this, leaving out the tables its founding transaction writes ([strands.md → Joining](../../docs/strands.md#joining-no-writes-before-the-first-sync)). Call it only while nothing else writes through the `Database`: it commits whatever is staged in those collections outside any SQL transaction.
|
|
@@ -301,6 +305,7 @@ The same step is exported on its own as `createEmptyCollections(db, bridge, sche
|
|
|
301
305
|
| `coordinatedRepo` | IRepo | — | Required when `libp2pNode` is provided |
|
|
302
306
|
| `transactor` | `'local' \| 'network' \| 'test'` | `'network'` | Storage engine transactions go through. `'network'`: the strand's libp2p cohort, which a lone node coordinates for itself — the only value an application should use. `'local'`: this process's raw storage directly, no peers consulted (in-process tests and tooling). `'test'`: Optimystic's in-memory fake; no libp2p node is created unless one is injected (unit tests) |
|
|
303
307
|
| `storage` | IRawStorage | — | Persistent raw storage. Borrowed — not closed on `shutdown()` |
|
|
308
|
+
| `offline` | `StrandOfflineOptions` | — | Turn on Optimystic's offline queue: the plugin's `offline` block less `journalLabel`, which is derived from the strand id. Programmatic only; no plugin setting carries it. See [Offline mode](#offline-mode) |
|
|
304
309
|
|
|
305
310
|
### Plugin settings (plugin-loader / Quoomb)
|
|
306
311
|
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { type Database } from '@quereus/quereus';
|
|
2
|
+
import type { StrandOfflineController, AppSchemaOutcome } from './types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Step 7 of `composeStrand`: declare the sApp's schema as `App` and apply it — a
|
|
5
|
+
* declarative diff against the catalog, so re-applying a schema that is already in place
|
|
6
|
+
* emits nothing. The one site that applies an `App` schema: `composeStrand` calls it at
|
|
7
|
+
* bring-up (through {@link applyAppSchemaAfterQueue}, whose deferred retry shares its
|
|
8
|
+
* declaration), and cadre-core's `StrandDatabase.attachAppSchema` calls it on a live storage
|
|
9
|
+
* replica when an app claims the strand. The database must already be composed (optimystic
|
|
10
|
+
* set as the default vtab), or the tables land in memory instead of the strand.
|
|
11
|
+
*
|
|
12
|
+
* Refuses a schema holding an item the Quereus parser skipped: it keeps any item whose leading
|
|
13
|
+
* keyword it does not model (`create unique index …`, a misspelled `tabel`, `domain`) as an
|
|
14
|
+
* opaque placeholder that apply ignores, so the app would otherwise run without that item.
|
|
15
|
+
*
|
|
16
|
+
* Refuses a schema holding a `seed` item: the apply runs on every node of the strand at every
|
|
17
|
+
* connect, so seed inserts would put a network write on each bring-up and two nodes inserting
|
|
18
|
+
* the same key at once would collide. Rows an app needs at birth are the founding app's to write.
|
|
19
|
+
*/
|
|
20
|
+
export declare function applyAppSchema(db: Database, schema: string): Promise<void>;
|
|
21
|
+
/** What {@link applyAppSchemaAfterQueue} reports, in the shape `SereusPluginResult` carries it. */
|
|
22
|
+
export interface AppSchemaApply {
|
|
23
|
+
appSchema: Promise<AppSchemaOutcome>;
|
|
24
|
+
appSchemaDeferredBy?: readonly string[];
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Step 7 of `composeStrand`: {@link applyAppSchema}, except that an apply refused by queued
|
|
28
|
+
* offline transactions (`QueuedEntriesBlockSchemaChangeError` on the error's `cause` chain) does not
|
|
29
|
+
* throw. Quereus unwinds the refused apply, so `db` keeps the `App` schema it had; the apply is
|
|
30
|
+
* retried in the background each time `queue` drains, for as long as the queue is what refuses it,
|
|
31
|
+
* and `appSchema` settles with how that ended. Any other error from the first apply is thrown.
|
|
32
|
+
*
|
|
33
|
+
* Waiting for the queue before returning was rejected: offline, that withholds the strand from the
|
|
34
|
+
* app right after an app update, which is when offline mode matters. So was refusing the connect:
|
|
35
|
+
* the queue can drain only while the composition is alive.
|
|
36
|
+
*
|
|
37
|
+
* `released` is aborted when the composition shuts down; a retry not yet landed then settles
|
|
38
|
+
* `cancelled`.
|
|
39
|
+
*
|
|
40
|
+
* A retry runs while the app is using `db`, so it is one atomic batch that refuses to run inside a
|
|
41
|
+
* transaction another caller holds open, and waits for that transaction to end: run inside it, the
|
|
42
|
+
* apply would be committed or rolled back with the app's rows, and a rollback leaves the index it
|
|
43
|
+
* built holding entries for rows that are gone.
|
|
44
|
+
*/
|
|
45
|
+
export declare function applyAppSchemaAfterQueue(db: Database, schema: string, queue: Pick<StrandOfflineController, 'whenDrained'>, released: AbortSignal): Promise<AppSchemaApply>;
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import debug from 'debug';
|
|
2
|
+
import { TransactionActiveError } from '@quereus/quereus';
|
|
3
|
+
import { QueuedEntriesBlockSchemaChangeError, QueueDisposedError } from '@optimystic/quereus-plugin-optimystic/plugin';
|
|
4
|
+
const log = debug('sereus:plugin:strand');
|
|
5
|
+
/**
|
|
6
|
+
* Step 7 of `composeStrand`: declare the sApp's schema as `App` and apply it — a
|
|
7
|
+
* declarative diff against the catalog, so re-applying a schema that is already in place
|
|
8
|
+
* emits nothing. The one site that applies an `App` schema: `composeStrand` calls it at
|
|
9
|
+
* bring-up (through {@link applyAppSchemaAfterQueue}, whose deferred retry shares its
|
|
10
|
+
* declaration), and cadre-core's `StrandDatabase.attachAppSchema` calls it on a live storage
|
|
11
|
+
* replica when an app claims the strand. The database must already be composed (optimystic
|
|
12
|
+
* set as the default vtab), or the tables land in memory instead of the strand.
|
|
13
|
+
*
|
|
14
|
+
* Refuses a schema holding an item the Quereus parser skipped: it keeps any item whose leading
|
|
15
|
+
* keyword it does not model (`create unique index …`, a misspelled `tabel`, `domain`) as an
|
|
16
|
+
* opaque placeholder that apply ignores, so the app would otherwise run without that item.
|
|
17
|
+
*
|
|
18
|
+
* Refuses a schema holding a `seed` item: the apply runs on every node of the strand at every
|
|
19
|
+
* connect, so seed inserts would put a network write on each bring-up and two nodes inserting
|
|
20
|
+
* the same key at once would collide. Rows an app needs at birth are the founding app's to write.
|
|
21
|
+
*/
|
|
22
|
+
export async function applyAppSchema(db, schema) {
|
|
23
|
+
await declareAppSchema(db, schema);
|
|
24
|
+
await db.exec('apply schema App;');
|
|
25
|
+
}
|
|
26
|
+
/** Declare `schema` as `App`, refusing the items {@link applyAppSchema} refuses. Writes nothing to the strand. */
|
|
27
|
+
async function declareAppSchema(db, schema) {
|
|
28
|
+
await db.exec(`
|
|
29
|
+
declare schema App {
|
|
30
|
+
${schema}
|
|
31
|
+
}
|
|
32
|
+
`);
|
|
33
|
+
assertNoIgnoredItems(db);
|
|
34
|
+
assertNoSeedItems(db);
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Step 7 of `composeStrand`: {@link applyAppSchema}, except that an apply refused by queued
|
|
38
|
+
* offline transactions (`QueuedEntriesBlockSchemaChangeError` on the error's `cause` chain) does not
|
|
39
|
+
* throw. Quereus unwinds the refused apply, so `db` keeps the `App` schema it had; the apply is
|
|
40
|
+
* retried in the background each time `queue` drains, for as long as the queue is what refuses it,
|
|
41
|
+
* and `appSchema` settles with how that ended. Any other error from the first apply is thrown.
|
|
42
|
+
*
|
|
43
|
+
* Waiting for the queue before returning was rejected: offline, that withholds the strand from the
|
|
44
|
+
* app right after an app update, which is when offline mode matters. So was refusing the connect:
|
|
45
|
+
* the queue can drain only while the composition is alive.
|
|
46
|
+
*
|
|
47
|
+
* `released` is aborted when the composition shuts down; a retry not yet landed then settles
|
|
48
|
+
* `cancelled`.
|
|
49
|
+
*
|
|
50
|
+
* A retry runs while the app is using `db`, so it is one atomic batch that refuses to run inside a
|
|
51
|
+
* transaction another caller holds open, and waits for that transaction to end: run inside it, the
|
|
52
|
+
* apply would be committed or rolled back with the app's rows, and a rollback leaves the index it
|
|
53
|
+
* built holding entries for rows that are gone.
|
|
54
|
+
*/
|
|
55
|
+
export async function applyAppSchemaAfterQueue(db, schema, queue, released) {
|
|
56
|
+
try {
|
|
57
|
+
await applyAppSchema(db, schema);
|
|
58
|
+
log('sApp schema applied');
|
|
59
|
+
return { appSchema: Promise.resolve({ state: 'applied' }) };
|
|
60
|
+
}
|
|
61
|
+
catch (err) {
|
|
62
|
+
const refusal = queueRefusalIn(err);
|
|
63
|
+
if (!refusal) {
|
|
64
|
+
throw err;
|
|
65
|
+
}
|
|
66
|
+
log('sApp schema apply refused by queued transactions %o; retrying once they settle', refusal.transactionIds);
|
|
67
|
+
return {
|
|
68
|
+
appSchema: retryAppSchemaAfterDrain(db, schema, queue, released),
|
|
69
|
+
appSchemaDeferredBy: refusal.transactionIds,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
async function retryAppSchemaAfterDrain(db, schema, queue, released) {
|
|
74
|
+
// NOTE: this loops without a pause when `whenDrained` resolves at once while the refusal stands
|
|
75
|
+
// (a segment left sealed with nothing queued, say). Upstream counts a removal still in progress
|
|
76
|
+
// as undrained, so no such state is known; if one shows up as a busy loop, back off between tries.
|
|
77
|
+
for (;;) {
|
|
78
|
+
try {
|
|
79
|
+
await queue.whenDrained();
|
|
80
|
+
if (released.aborted) {
|
|
81
|
+
return { state: 'cancelled' };
|
|
82
|
+
}
|
|
83
|
+
await declareAppSchema(db, schema);
|
|
84
|
+
await db.exec('apply schema App;', undefined, { transaction: true });
|
|
85
|
+
log('Deferred sApp schema applied');
|
|
86
|
+
return { state: 'applied', deferred: true };
|
|
87
|
+
}
|
|
88
|
+
catch (err) {
|
|
89
|
+
if (released.aborted || err instanceof QueueDisposedError) {
|
|
90
|
+
log('Deferred sApp schema apply cancelled by shutdown');
|
|
91
|
+
return { state: 'cancelled' };
|
|
92
|
+
}
|
|
93
|
+
if (err instanceof TransactionActiveError) {
|
|
94
|
+
log('Deferred sApp schema apply waiting for an open transaction to end');
|
|
95
|
+
await abortableDelay(OPEN_TRANSACTION_RETRY_MS, released);
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
const refusal = queueRefusalIn(err);
|
|
99
|
+
if (!refusal) {
|
|
100
|
+
log('Deferred sApp schema apply failed: %O', err);
|
|
101
|
+
return { state: 'failed', error: err };
|
|
102
|
+
}
|
|
103
|
+
log('sApp schema apply refused again by queued transactions %o', refusal.transactionIds);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
/** The offline queue's refusal `err` is or wraps: Quereus rewraps it out of `apply schema`, keeping it as `cause`. */
|
|
108
|
+
function queueRefusalIn(err) {
|
|
109
|
+
for (let at = err; at instanceof Error; at = at.cause) {
|
|
110
|
+
if (at instanceof QueuedEntriesBlockSchemaChangeError) {
|
|
111
|
+
return at;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return undefined;
|
|
115
|
+
}
|
|
116
|
+
/** How long a deferred sApp schema apply waits before trying again while another caller's transaction is open. */
|
|
117
|
+
const OPEN_TRANSACTION_RETRY_MS = 250;
|
|
118
|
+
/** Resolves after `ms`, or as soon as `signal` aborts. */
|
|
119
|
+
function abortableDelay(ms, signal) {
|
|
120
|
+
return new Promise(resolve => {
|
|
121
|
+
const done = () => {
|
|
122
|
+
clearTimeout(timer);
|
|
123
|
+
signal.removeEventListener('abort', done);
|
|
124
|
+
resolve();
|
|
125
|
+
};
|
|
126
|
+
const timer = setTimeout(done, ms);
|
|
127
|
+
signal.addEventListener('abort', done, { once: true });
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
function declaredAppItems(db) {
|
|
131
|
+
return db.declaredSchemaManager.getDeclaredSchema('App')?.items ?? [];
|
|
132
|
+
}
|
|
133
|
+
function assertNoIgnoredItems(db) {
|
|
134
|
+
const ignored = declaredAppItems(db).filter(item => item.type === 'declareIgnored').length;
|
|
135
|
+
if (ignored > 0) {
|
|
136
|
+
// Only a count: Quereus leaves an ignored item's source text empty.
|
|
137
|
+
throw new Error(`sApp schema has ${ignored} item(s) the parser does not recognize (a \`create …\` prefix or a misspelled item keyword such as \`tabel\`); items are \`table\`, \`index\`, \`unique index\`, \`view\`, \`materialized view\` and \`assertion\``);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
function assertNoSeedItems(db) {
|
|
141
|
+
// Quereus refuses a second seed for one table at declare, so these names are distinct.
|
|
142
|
+
const tables = declaredAppItems(db).flatMap(item => item.type === 'declaredSeed' ? [item.tableName] : []);
|
|
143
|
+
if (tables.length > 0) {
|
|
144
|
+
throw new Error(`sApp schema has seed item(s) for table(s) ${tables.join(', ')}; Sereus does not apply seed rows to a strand — insert the rows an app needs at birth from the app when it founds the strand`);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
//# sourceMappingURL=app-schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app-schema.js","sourceRoot":"","sources":["../src/app-schema.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,sBAAsB,EAAiB,MAAM,kBAAkB,CAAC;AACzE,OAAO,EAAE,mCAAmC,EAAE,kBAAkB,EAAE,MAAM,8CAA8C,CAAC;AAGvH,MAAM,GAAG,GAAG,KAAK,CAAC,sBAAsB,CAAC,CAAC;AAE1C;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,EAAY,EAAE,MAAc;IAChE,MAAM,gBAAgB,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;IACnC,MAAM,EAAE,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;AACpC,CAAC;AAED,kHAAkH;AAClH,KAAK,UAAU,gBAAgB,CAAC,EAAY,EAAE,MAAc;IAC3D,MAAM,EAAE,CAAC,IAAI,CAAC;;KAEV,MAAM;;EAET,CAAC,CAAC;IACH,oBAAoB,CAAC,EAAE,CAAC,CAAC;IACzB,iBAAiB,CAAC,EAAE,CAAC,CAAC;AACvB,CAAC;AAQD;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAC7C,EAAY,EACZ,MAAc,EACd,KAAmD,EACnD,QAAqB;IAErB,IAAI,CAAC;QACJ,MAAM,cAAc,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;QACjC,GAAG,CAAC,qBAAqB,CAAC,CAAC;QAC3B,OAAO,EAAE,SAAS,EAAE,OAAO,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,EAAE,CAAC;IAC7D,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACd,MAAM,OAAO,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC;QACpC,IAAI,CAAC,OAAO,EAAE,CAAC;YACd,MAAM,GAAG,CAAC;QACX,CAAC;QACD,GAAG,CAAC,gFAAgF,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC;QAC9G,OAAO;YACN,SAAS,EAAE,wBAAwB,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,CAAC;YAChE,mBAAmB,EAAE,OAAO,CAAC,cAAc;SAC3C,CAAC;IACH,CAAC;AACF,CAAC;AAED,KAAK,UAAU,wBAAwB,CACtC,EAAY,EACZ,MAAc,EACd,KAAmD,EACnD,QAAqB;IAErB,gGAAgG;IAChG,gGAAgG;IAChG,mGAAmG;IACnG,SAAS,CAAC;QACT,IAAI,CAAC;YACJ,MAAM,KAAK,CAAC,WAAW,EAAE,CAAC;YAC1B,IAAI,QAAQ,CAAC,OAAO,EAAE,CAAC;gBACtB,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC;YAC/B,CAAC;YACD,MAAM,gBAAgB,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;YACnC,MAAM,EAAE,CAAC,IAAI,CAAC,mBAAmB,EAAE,SAAS,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,CAAC;YACrE,GAAG,CAAC,8BAA8B,CAAC,CAAC;YACpC,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;QAC7C,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACd,IAAI,QAAQ,CAAC,OAAO,IAAI,GAAG,YAAY,kBAAkB,EAAE,CAAC;gBAC3D,GAAG,CAAC,kDAAkD,CAAC,CAAC;gBACxD,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC;YAC/B,CAAC;YACD,IAAI,GAAG,YAAY,sBAAsB,EAAE,CAAC;gBAC3C,GAAG,CAAC,mEAAmE,CAAC,CAAC;gBACzE,MAAM,cAAc,CAAC,yBAAyB,EAAE,QAAQ,CAAC,CAAC;gBAC1D,SAAS;YACV,CAAC;YACD,MAAM,OAAO,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC;YACpC,IAAI,CAAC,OAAO,EAAE,CAAC;gBACd,GAAG,CAAC,uCAAuC,EAAE,GAAG,CAAC,CAAC;gBAClD,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC;YACxC,CAAC;YACD,GAAG,CAAC,2DAA2D,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC;QAC1F,CAAC;IACF,CAAC;AACF,CAAC;AAED,sHAAsH;AACtH,SAAS,cAAc,CAAC,GAAY;IACnC,KAAK,IAAI,EAAE,GAAG,GAAG,EAAE,EAAE,YAAY,KAAK,EAAE,EAAE,GAAG,EAAE,CAAC,KAAK,EAAE,CAAC;QACvD,IAAI,EAAE,YAAY,mCAAmC,EAAE,CAAC;YACvD,OAAO,EAAE,CAAC;QACX,CAAC;IACF,CAAC;IACD,OAAO,SAAS,CAAC;AAClB,CAAC;AAED,kHAAkH;AAClH,MAAM,yBAAyB,GAAG,GAAG,CAAC;AAEtC,0DAA0D;AAC1D,SAAS,cAAc,CAAC,EAAU,EAAE,MAAmB;IACtD,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE;QAC5B,MAAM,IAAI,GAAG,GAAS,EAAE;YACvB,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,MAAM,CAAC,mBAAmB,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;YAC1C,OAAO,EAAE,CAAC;QACX,CAAC,CAAC;QACF,MAAM,KAAK,GAAG,UAAU,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QACnC,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;IACxD,CAAC,CAAC,CAAC;AACJ,CAAC;AAED,SAAS,gBAAgB,CAAC,EAAY;IACrC,OAAO,EAAE,CAAC,qBAAqB,CAAC,iBAAiB,CAAC,KAAK,CAAC,EAAE,KAAK,IAAI,EAAE,CAAC;AACvE,CAAC;AAED,SAAS,oBAAoB,CAAC,EAAY;IACzC,MAAM,OAAO,GAAG,gBAAgB,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,gBAAgB,CAAC,CAAC,MAAM,CAAC;IAC3F,IAAI,OAAO,GAAG,CAAC,EAAE,CAAC;QACjB,oEAAoE;QACpE,MAAM,IAAI,KAAK,CAAC,mBAAmB,OAAO,oNAAoN,CAAC,CAAC;IACjQ,CAAC;AACF,CAAC;AAED,SAAS,iBAAiB,CAAC,EAAY;IACtC,uFAAuF;IACvF,MAAM,MAAM,GAAG,gBAAgB,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,cAAc,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IAC1G,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CAAC,6CAA6C,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,8HAA8H,CAAC,CAAC;IAC/M,CAAC;AACF,CAAC"}
|
package/dist/compose-strand.d.ts
CHANGED
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
import type { Database, VTablePluginInfo, FunctionPluginInfo, CollationPluginInfo } from '@quereus/quereus';
|
|
2
2
|
import type { Libp2p } from '@libp2p/interface';
|
|
3
|
-
import type { IRawStorage, NodeOptions } from '@optimystic/db-p2p';
|
|
4
|
-
import type { StrandConnectionOptions, SereusPluginResult, StrandTransactor } from './types.js';
|
|
3
|
+
import type { IKVStore, IRawStorage, NodeOptions } from '@optimystic/db-p2p';
|
|
4
|
+
import type { StrandConnectionOptions, SereusPluginResult, StrandTransactor, StrandOfflineController } from './types.js';
|
|
5
|
+
/**
|
|
6
|
+
* The offline controller of the live strand composition over `db`, or `undefined` when it was
|
|
7
|
+
* composed without `offline`, has shut down, or `db` is no strand composition. For Sereus's own
|
|
8
|
+
* writers, which are handed a bare `Database` and must see whether its queue holds transactions.
|
|
9
|
+
*/
|
|
10
|
+
export declare function offlineControllerOf(db: Database): StrandOfflineController | undefined;
|
|
5
11
|
/** Registration shape shared by the crypto and optimystic plugin results. */
|
|
6
12
|
interface PluginRegistrations {
|
|
7
13
|
vtables?: VTablePluginInfo[];
|
|
@@ -71,6 +77,13 @@ export interface StrandPlatform {
|
|
|
71
77
|
* default to IndexedDB so a reload survives.
|
|
72
78
|
*/
|
|
73
79
|
resolveStorage?(ctx: ResolveStorageContext): Promise<IRawStorage | undefined> | IRawStorage | undefined;
|
|
80
|
+
/**
|
|
81
|
+
* The store to journal offline transactions in when `options.offline` names no `journal`.
|
|
82
|
+
* Called after {@link resolveStorage}, only when `options.offline` is given. Optional — when
|
|
83
|
+
* omitted, or when it answers `undefined`, the queue lives in memory (Node). The browser answers
|
|
84
|
+
* a store over the IndexedDB database it defaulted the strand's storage to.
|
|
85
|
+
*/
|
|
86
|
+
defaultOfflineJournal?(): IKVStore | undefined;
|
|
74
87
|
/**
|
|
75
88
|
* Create a libp2p node. Called only when no node is injected and the
|
|
76
89
|
* transactor needs one. Node creates a TCP node via `@optimystic/db-p2p`;
|
|
@@ -90,21 +103,4 @@ export interface StrandPlatform {
|
|
|
90
103
|
* vtab, hydrate the catalog, then apply the sApp schema.
|
|
91
104
|
*/
|
|
92
105
|
export declare function composeStrand(db: Database, options: StrandConnectionOptions, platform: StrandPlatform): Promise<SereusPluginResult>;
|
|
93
|
-
/**
|
|
94
|
-
* Step 7 of {@link composeStrand}: declare the sApp's schema as `App` and apply it — a
|
|
95
|
-
* declarative diff against the catalog, so re-applying a schema that is already in place
|
|
96
|
-
* emits nothing. The one site that applies an `App` schema: `composeStrand` calls it at
|
|
97
|
-
* bring-up, and cadre-core's `StrandDatabase.attachAppSchema` calls it on a live storage
|
|
98
|
-
* replica when an app claims the strand. The database must already be composed (optimystic
|
|
99
|
-
* set as the default vtab), or the tables land in memory instead of the strand.
|
|
100
|
-
*
|
|
101
|
-
* Refuses a schema holding an item the Quereus parser skipped: it keeps any item whose leading
|
|
102
|
-
* keyword it does not model (`create unique index …`, a misspelled `tabel`, `domain`) as an
|
|
103
|
-
* opaque placeholder that apply ignores, so the app would otherwise run without that item.
|
|
104
|
-
*
|
|
105
|
-
* Refuses a schema holding a `seed` item: the apply runs on every node of the strand at every
|
|
106
|
-
* connect, so seed inserts would put a network write on each bring-up and two nodes inserting
|
|
107
|
-
* the same key at once would collide. Rows an app needs at birth are the founding app's to write.
|
|
108
|
-
*/
|
|
109
|
-
export declare function applyAppSchema(db: Database, schema: string): Promise<void>;
|
|
110
106
|
export {};
|
package/dist/compose-strand.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import debug from 'debug';
|
|
2
2
|
import optimysticPlugin from '@optimystic/quereus-plugin-optimystic/plugin';
|
|
3
|
+
import { applyAppSchemaAfterQueue } from './app-schema.js';
|
|
3
4
|
import { STRAND_SCHEMA } from './strand-schema.js';
|
|
4
5
|
import { resolveStrandClusterSize, STRAND_CLUSTER_POLICY } from './cluster-size.js';
|
|
5
6
|
import { wrapStorageWithCache, disposeStorageCache } from './cached-storage.js';
|
|
@@ -8,18 +9,33 @@ const log = debug('sereus:plugin:strand');
|
|
|
8
9
|
const timing = debug('sereus:plugin:strand:timing');
|
|
9
10
|
/** The schemas whose tables a strand founder gives a collection: strand membership, then the sApp's. */
|
|
10
11
|
const FOUNDED_SCHEMAS = ['Strand', 'App'];
|
|
12
|
+
/** The offline controller of each live strand composition composed with `offline`, by its `Database`. */
|
|
13
|
+
const offlineControllers = new WeakMap();
|
|
11
14
|
/**
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
* The offline controller of the live strand composition over `db`, or `undefined` when it was
|
|
16
|
+
* composed without `offline`, has shut down, or `db` is no strand composition. For Sereus's own
|
|
17
|
+
* writers, which are handed a bare `Database` and must see whether its queue holds transactions.
|
|
18
|
+
*/
|
|
19
|
+
export function offlineControllerOf(db) {
|
|
20
|
+
return offlineControllers.get(db);
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Release a composition's hold on the optimystic plugin. The offline queue goes first: its drain
|
|
24
|
+
* keeps timers and may have a submission in flight, which reports its commit through the bridge's
|
|
25
|
+
* follower, so the bridge must outlive it (the plugin's own `dispose()` orders them the same way).
|
|
26
|
+
* A queue `hydrate` restored before a failed composition is stopped here too. Then the transaction
|
|
27
|
+
* bridge: its durability follower subscribes to the node's `StorageRepo`, and cadre-core keeps a
|
|
28
|
+
* strand's node across a database rebuild, so a bridge never disposed stays subscribed once per
|
|
29
|
+
* rebuild. Then the collection factory: a node the composition created is stopped with it; an
|
|
30
|
+
* injected node is left running, because it belongs to the caller — cadre-core keeps a strand's
|
|
31
|
+
* node up across a failed database build and retries the build on it.
|
|
18
32
|
*
|
|
19
|
-
* Disposes the bridge itself rather than calling the plugin's `dispose()`, which would
|
|
20
|
-
* factory a second time on the created-node path (`shutdown()` ends with the same
|
|
33
|
+
* Disposes the queue and bridge itself rather than calling the plugin's `dispose()`, which would
|
|
34
|
+
* release the factory a second time on the created-node path (`shutdown()` ends with the same
|
|
35
|
+
* `dispose()`).
|
|
21
36
|
*/
|
|
22
37
|
async function releaseOptimysticPlugin(plugin, createdNode) {
|
|
38
|
+
await plugin.offline.dispose();
|
|
23
39
|
// NOTE: the bridge's follower re-subscribes at the start of any transaction, so a write begun on
|
|
24
40
|
// this `Database` after release (before its owner closes it) subscribes again and nothing
|
|
25
41
|
// releases it. cadre-core stops its own writers before releasing; if an app write in flight at
|
|
@@ -119,6 +135,7 @@ export async function composeStrand(db, options, platform) {
|
|
|
119
135
|
networkName,
|
|
120
136
|
enableCache,
|
|
121
137
|
storage,
|
|
138
|
+
offline: options.offline && strandOfflineConfig(strandId, options.offline, platform),
|
|
122
139
|
});
|
|
123
140
|
}
|
|
124
141
|
catch (err) {
|
|
@@ -126,6 +143,13 @@ export async function composeStrand(db, options, platform) {
|
|
|
126
143
|
throw err;
|
|
127
144
|
}
|
|
128
145
|
const { collectionFactory } = pluginResult;
|
|
146
|
+
const offline = options.offline && pluginResult.offline;
|
|
147
|
+
if (offline) {
|
|
148
|
+
offlineControllers.set(db, offline);
|
|
149
|
+
}
|
|
150
|
+
// Aborted by `shutdown`, so a deferred sApp schema apply still waiting settles `cancelled`.
|
|
151
|
+
const released = new AbortController();
|
|
152
|
+
let appSchemaApply;
|
|
129
153
|
let createdNode = null;
|
|
130
154
|
let hydrated;
|
|
131
155
|
try {
|
|
@@ -194,6 +218,13 @@ export async function composeStrand(db, options, platform) {
|
|
|
194
218
|
// nothing here writes membership rows. Founder bootstrap (Header, founding
|
|
195
219
|
// Manager/Member, invite/peer flows) is owned by the lifecycle ticket
|
|
196
220
|
// `strand-membership-lifecycle-population`.
|
|
221
|
+
//
|
|
222
|
+
// NOTE: unlike step 7, this apply is not deferred behind the offline queue. Every `Strand`
|
|
223
|
+
// table is tagged `"optimystic.offline" = 'network'`, so the only queued transactions that
|
|
224
|
+
// write one are network-acknowledged commits waiting behind app transactions, and the only
|
|
225
|
+
// change this schema has made since is a tag, which the queue does not refuse. If a
|
|
226
|
+
// later strand schema changes how a table's rows are stored (an index, a column), this apply
|
|
227
|
+
// can be refused by `QueuedEntriesBlockSchemaChangeError` the same way and needs step 7's path.
|
|
197
228
|
log('Applying Strand membership schema for strand %s', strandId);
|
|
198
229
|
await db.exec(`
|
|
199
230
|
declare schema Strand {
|
|
@@ -218,14 +249,18 @@ export async function composeStrand(db, options, platform) {
|
|
|
218
249
|
// differ: once one has run, any later step that fails leaves the schema partially
|
|
219
250
|
// migrated instead of restored. No schema in this repo evolves that way, so this
|
|
220
251
|
// is a note for whoever first ships a migration that does.
|
|
252
|
+
//
|
|
253
|
+
// The one exception: an apply refused by queued offline transactions does not fail the
|
|
254
|
+
// connect. The strand comes up on the `App` schema it had, and the apply is retried as the
|
|
255
|
+
// queue drains (see `applyAppSchemaAfterQueue`).
|
|
221
256
|
if (schema) {
|
|
222
257
|
log('Applying sApp schema for strand %s', strandId);
|
|
223
|
-
await
|
|
224
|
-
log('sApp schema applied');
|
|
258
|
+
appSchemaApply = await applyAppSchemaAfterQueue(db, schema, pluginResult.offline, released.signal);
|
|
225
259
|
}
|
|
226
260
|
}
|
|
227
261
|
catch (err) {
|
|
228
262
|
// Clean up resources if setup fails after partial initialization.
|
|
263
|
+
offlineControllers.delete(db);
|
|
229
264
|
await releaseOptimysticPlugin(pluginResult, createdNode);
|
|
230
265
|
await releaseStorageCache();
|
|
231
266
|
throw err;
|
|
@@ -242,8 +277,15 @@ export async function composeStrand(db, options, platform) {
|
|
|
242
277
|
onCommitDurability: listener => pluginResult.onCommitDurability(listener),
|
|
243
278
|
onCommitFullyHeld: listener => pluginResult.onCommitFullyHeld(listener),
|
|
244
279
|
createEmptyCollections: except => createEmptyCollections(db, pluginResult.txnBridge, FOUNDED_SCHEMAS, except),
|
|
280
|
+
...(offline && { offline }),
|
|
281
|
+
...appSchemaApply,
|
|
245
282
|
async shutdown() {
|
|
246
283
|
log('Shutting down strand connection %s', strandId);
|
|
284
|
+
// NOTE: a deferred sApp schema apply already running is not awaited: it runs on against the
|
|
285
|
+
// released plugin, Quereus unwinds it when it fails, and `appSchema` settles `cancelled`. If
|
|
286
|
+
// that ever leaves a catalog write landing after close, await `appSchema` here first.
|
|
287
|
+
released.abort();
|
|
288
|
+
offlineControllers.delete(db);
|
|
247
289
|
await releaseOptimysticPlugin(pluginResult, createdNode);
|
|
248
290
|
await releaseStorageCache();
|
|
249
291
|
log('Strand connection %s shut down', strandId);
|
|
@@ -251,47 +293,22 @@ export async function composeStrand(db, options, platform) {
|
|
|
251
293
|
};
|
|
252
294
|
}
|
|
253
295
|
/**
|
|
254
|
-
*
|
|
255
|
-
*
|
|
256
|
-
* emits nothing. The one site that applies an `App` schema: `composeStrand` calls it at
|
|
257
|
-
* bring-up, and cadre-core's `StrandDatabase.attachAppSchema` calls it on a live storage
|
|
258
|
-
* replica when an app claims the strand. The database must already be composed (optimystic
|
|
259
|
-
* set as the default vtab), or the tables land in memory instead of the strand.
|
|
260
|
-
*
|
|
261
|
-
* Refuses a schema holding an item the Quereus parser skipped: it keeps any item whose leading
|
|
262
|
-
* keyword it does not model (`create unique index …`, a misspelled `tabel`, `domain`) as an
|
|
263
|
-
* opaque placeholder that apply ignores, so the app would otherwise run without that item.
|
|
264
|
-
*
|
|
265
|
-
* Refuses a schema holding a `seed` item: the apply runs on every node of the strand at every
|
|
266
|
-
* connect, so seed inserts would put a network write on each bring-up and two nodes inserting
|
|
267
|
-
* the same key at once would collide. Rows an app needs at birth are the founding app's to write.
|
|
296
|
+
* The Optimystic plugin's `offline` block for this strand: the caller's options, the platform's
|
|
297
|
+
* journal when the caller named none, and the journal label, which the plugin refuses without one.
|
|
268
298
|
*/
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
`);
|
|
275
|
-
assertNoIgnoredItems(db);
|
|
276
|
-
assertNoSeedItems(db);
|
|
277
|
-
await db.exec('apply schema App;');
|
|
299
|
+
function strandOfflineConfig(strandId, offline, platform) {
|
|
300
|
+
const journal = offline.journal ?? platform.defaultOfflineJournal?.();
|
|
301
|
+
return journal === undefined
|
|
302
|
+
? { ...offline }
|
|
303
|
+
: { ...offline, journal, journalLabel: strandJournalLabel(strandId) };
|
|
278
304
|
}
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
throw new Error(`sApp schema has ${ignored} item(s) the parser does not recognize (a \`create …\` prefix or a misspelled item keyword such as \`tabel\`); items are \`table\`, \`index\`, \`unique index\`, \`view\`, \`materialized view\` and \`assertion\``);
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
function assertNoSeedItems(db) {
|
|
290
|
-
// Quereus refuses a second seed for one table at declare, so these names are distinct.
|
|
291
|
-
const tables = declaredAppItems(db).flatMap(item => item.type === 'declaredSeed' ? [item.tableName] : []);
|
|
292
|
-
if (tables.length > 0) {
|
|
293
|
-
throw new Error(`sApp schema has seed item(s) for table(s) ${tables.join(', ')}; Sereus does not apply seed rows to a strand — insert the rows an app needs at birth from the app when it founds the strand`);
|
|
294
|
-
}
|
|
305
|
+
/**
|
|
306
|
+
* The offline journal label for a strand. A label is `[a-z0-9_-]` and a strand id `[a-z0-9._-]`, so
|
|
307
|
+
* `_` becomes `__` and `.` becomes `_d`: no two strand ids share a label, and two strands journaling
|
|
308
|
+
* into one store keep their records apart.
|
|
309
|
+
*/
|
|
310
|
+
function strandJournalLabel(strandId) {
|
|
311
|
+
return `strand-${strandId.replaceAll('_', '__').replaceAll('.', '_d')}`;
|
|
295
312
|
}
|
|
296
313
|
/**
|
|
297
314
|
* Steps 1-2 of {@link composeStrand}: register the crypto plugin, then the optimystic
|
|
@@ -313,9 +330,16 @@ async function registerStrandPlugins(db, platform, strand) {
|
|
|
313
330
|
const storage = strand.storage;
|
|
314
331
|
pluginConfig.rawStorageFactory = () => storage;
|
|
315
332
|
}
|
|
333
|
+
// NOTE: `networkCommitTimeoutMs` is left at upstream's default (five minutes); nothing was
|
|
334
|
+
// measured to choose another. A network-acknowledged commit made while transactions are queued
|
|
335
|
+
// (any `Strand` write, all of them tagged 'network') waits that long behind them holding
|
|
336
|
+
// Quereus's execution lock. If that ever shows up as a frozen app, lower it for strands here.
|
|
337
|
+
if (strand.offline) {
|
|
338
|
+
pluginConfig.offline = strand.offline;
|
|
339
|
+
}
|
|
316
340
|
// The plugin's published signature is `Record<string, SqlValue>` but it also reads
|
|
317
|
-
// `rawStorageFactory` (a function reference)
|
|
318
|
-
// rather than widen the public type.
|
|
341
|
+
// `rawStorageFactory` (a function reference) and `offline` (an object) from the same
|
|
342
|
+
// map. Cast through unknown rather than widen the public type.
|
|
319
343
|
const pluginResult = optimysticPlugin(db, pluginConfig);
|
|
320
344
|
applyRegistrations(db, pluginResult);
|
|
321
345
|
log('Registered optimystic vtables and functions');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compose-strand.js","sourceRoot":"","sources":["../src/compose-strand.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,gBAAgB,MAAM,8CAA8C,CAAC;
|
|
1
|
+
{"version":3,"file":"compose-strand.js","sourceRoot":"","sources":["../src/compose-strand.ts"],"names":[],"mappings":"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"}
|
|
@@ -8,6 +8,8 @@ import type { StrandConnectionOptions, SereusPluginResult } from './types.js';
|
|
|
8
8
|
* - crypto registered inline (no runtime `@quereus/quereus` import, so the
|
|
9
9
|
* bundle does not duplicate the host's instance),
|
|
10
10
|
* - storage defaulting to `IndexedDBRawStorage` keyed by `sereus-strand-<id>`,
|
|
11
|
+
* - with `offline` given and no `journal`, the offline queue journaled into that same
|
|
12
|
+
* IndexedDB database (its `kv` object store) when the storage was defaulted,
|
|
11
13
|
* - a node created via the TCP-free `@optimystic/db-p2p/rn` entry with explicit
|
|
12
14
|
* `webSockets()` + `circuitRelayTransport()` transports.
|
|
13
15
|
*/
|
package/dist/connect-browser.js
CHANGED
|
@@ -2,7 +2,7 @@ import cryptoPlugin from '@optimystic/quereus-plugin-crypto/plugin';
|
|
|
2
2
|
import { createLibp2pNode } from '@optimystic/db-p2p/rn';
|
|
3
3
|
import { webSockets } from '@libp2p/websockets';
|
|
4
4
|
import { circuitRelayTransport } from '@libp2p/circuit-relay-v2';
|
|
5
|
-
import { IndexedDBRawStorage, openOptimysticWebDb } from '@optimystic/db-p2p-storage-web';
|
|
5
|
+
import { IndexedDBKVStore, IndexedDBRawStorage, openOptimysticWebDb } from '@optimystic/db-p2p-storage-web';
|
|
6
6
|
import { composeStrand, applyRegistrations } from './compose-strand.js';
|
|
7
7
|
/**
|
|
8
8
|
* Connect a Quereus Database to a Sereus strand from a browser/worker.
|
|
@@ -12,10 +12,14 @@ import { composeStrand, applyRegistrations } from './compose-strand.js';
|
|
|
12
12
|
* - crypto registered inline (no runtime `@quereus/quereus` import, so the
|
|
13
13
|
* bundle does not duplicate the host's instance),
|
|
14
14
|
* - storage defaulting to `IndexedDBRawStorage` keyed by `sereus-strand-<id>`,
|
|
15
|
+
* - with `offline` given and no `journal`, the offline queue journaled into that same
|
|
16
|
+
* IndexedDB database (its `kv` object store) when the storage was defaulted,
|
|
15
17
|
* - a node created via the TCP-free `@optimystic/db-p2p/rn` entry with explicit
|
|
16
18
|
* `webSockets()` + `circuitRelayTransport()` transports.
|
|
17
19
|
*/
|
|
18
20
|
export async function connectToStrandBrowser(db, options) {
|
|
21
|
+
// The IndexedDB database the storage was defaulted to, if it was; the offline journal shares it.
|
|
22
|
+
let defaultedDb;
|
|
19
23
|
return composeStrand(db, options, {
|
|
20
24
|
registerCrypto(database) {
|
|
21
25
|
applyRegistrations(database, cryptoPlugin(database, {}));
|
|
@@ -27,8 +31,11 @@ export async function connectToStrandBrowser(db, options) {
|
|
|
27
31
|
// unit-test fake transactor needs no storage.
|
|
28
32
|
if (resolvedTransactor === 'test')
|
|
29
33
|
return undefined;
|
|
30
|
-
|
|
31
|
-
return new IndexedDBRawStorage(
|
|
34
|
+
defaultedDb = await openOptimysticWebDb(`sereus-strand-${strandId}`);
|
|
35
|
+
return new IndexedDBRawStorage(defaultedDb);
|
|
36
|
+
},
|
|
37
|
+
defaultOfflineJournal() {
|
|
38
|
+
return defaultedDb && new IndexedDBKVStore(defaultedDb);
|
|
32
39
|
},
|
|
33
40
|
async createNode({ networkName, bootstrapNodes, fretProfile, clusterSize, clusterPolicy, storage }) {
|
|
34
41
|
return createLibp2pNode({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connect-browser.js","sourceRoot":"","sources":["../src/connect-browser.ts"],"names":[],"mappings":"AACA,OAAO,YAAY,MAAM,0CAA0C,CAAC;AACpE,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"connect-browser.js","sourceRoot":"","sources":["../src/connect-browser.ts"],"names":[],"mappings":"AACA,OAAO,YAAY,MAAM,0CAA0C,CAAC;AACpE,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,mBAAmB,EAA8B,MAAM,gCAAgC,CAAC;AAGxI,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AASxE;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC3C,EAAY,EACZ,OAAgC;IAEhC,iGAAiG;IACjG,IAAI,WAA8C,CAAC;IACnD,OAAO,aAAa,CAAC,EAAE,EAAE,OAAO,EAAE;QACjC,cAAc,CAAC,QAAQ;YACtB,kBAAkB,CAAC,QAAQ,EAAE,YAAY,CAAC,QAAQ,EAAE,EAAE,CAAkC,CAAC,CAAC;QAC3F,CAAC;QACD,KAAK,CAAC,cAAc,CAAC,EAAE,QAAQ,EAAE,kBAAkB,EAAE,gBAAgB,EAAE;YACtE,IAAI,gBAAgB;gBAAE,OAAO,gBAAgB,CAAC;YAC9C,iEAAiE;YACjE,8CAA8C;YAC9C,IAAI,kBAAkB,KAAK,MAAM;gBAAE,OAAO,SAAS,CAAC;YACpD,WAAW,GAAG,MAAM,mBAAmB,CAAC,iBAAiB,QAAQ,EAAE,CAAC,CAAC;YACrE,OAAO,IAAI,mBAAmB,CAAC,WAAW,CAAC,CAAC;QAC7C,CAAC;QACD,qBAAqB;YACpB,OAAO,WAAW,IAAI,IAAI,gBAAgB,CAAC,WAAW,CAAC,CAAC;QACzD,CAAC;QACD,KAAK,CAAC,UAAU,CAAC,EAAE,WAAW,EAAE,cAAc,EAAE,WAAW,EAAE,WAAW,EAAE,aAAa,EAAE,OAAO,EAAE;YACjG,OAAO,gBAAgB,CAAC;gBACvB,UAAU,EAAE,CAAC,UAAU,EAAE,EAAE,qBAAqB,EAAE,CAAC;gBACnD,WAAW,EAAE,EAAE;gBACf,cAAc;gBACd,WAAW;gBACX,WAAW;gBACX,WAAW;gBACX,aAAa;gBACb,GAAG,CAAC,OAAO,IAAI,EAAE,OAAO,EAAE,CAAC;aAC3B,CAAoB,CAAC;QACvB,CAAC;KACD,CAAC,CAAC;AACJ,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
export { connectToStrand } from './connect.js';
|
|
2
|
-
export {
|
|
2
|
+
export { offlineControllerOf } from './compose-strand.js';
|
|
3
|
+
export { applyAppSchema } from './app-schema.js';
|
|
3
4
|
export { createEmptyCollections, type CollectionRegistrySource } from './empty-collections.js';
|
|
4
5
|
export { MIN_CLUSTER_SIZE, COHORT_READ_DEADLINE_MS, CONTROL_REPLICATION_BREADTH, CONTROL_CLUSTER_POLICY, DEFAULT_STRAND_CLUSTER_SIZE, STRAND_CLUSTER_POLICY, resolveStrandClusterSize, resolveRepairYardstick, controlClusterPolicy, strandClusterPolicy } from './cluster-size.js';
|
|
5
6
|
export { wrapStorageWithCache, disposeStorageCache } from './cached-storage.js';
|
|
6
|
-
export type { StrandConnectionOptions, SereusPluginResult, StrandTransactor } from './types.js';
|
|
7
|
+
export type { StrandConnectionOptions, SereusPluginResult, StrandTransactor, StrandOfflineOptions, StrandOfflineController, AppSchemaOutcome, } from './types.js';
|
|
7
8
|
export type { SqlCommitDurability, CommitFullyHeld } from '@optimystic/quereus-plugin-optimystic/plugin';
|
|
9
|
+
export { OfflineCommitTimeoutError, QueuedEntriesBlockSchemaChangeError, EntryNotDiscardableError, UnknownEntryError, QueueDisposedError, OfflineJournalError, } from '@optimystic/quereus-plugin-optimystic/plugin';
|
|
10
|
+
export type { QueuedTransactionStatus, OfflineModeState, CommitOutlook } from '@optimystic/quereus-plugin-optimystic/plugin';
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
export { connectToStrand } from './connect.js';
|
|
2
|
-
export {
|
|
2
|
+
export { offlineControllerOf } from './compose-strand.js';
|
|
3
|
+
export { applyAppSchema } from './app-schema.js';
|
|
3
4
|
export { createEmptyCollections } from './empty-collections.js';
|
|
4
5
|
export { MIN_CLUSTER_SIZE, COHORT_READ_DEADLINE_MS, CONTROL_REPLICATION_BREADTH, CONTROL_CLUSTER_POLICY, DEFAULT_STRAND_CLUSTER_SIZE, STRAND_CLUSTER_POLICY, resolveStrandClusterSize, resolveRepairYardstick, controlClusterPolicy, strandClusterPolicy } from './cluster-size.js';
|
|
5
6
|
export { wrapStorageWithCache, disposeStorageCache } from './cached-storage.js';
|
|
7
|
+
export { OfflineCommitTimeoutError, QueuedEntriesBlockSchemaChangeError, EntryNotDiscardableError, UnknownEntryError, QueueDisposedError, OfflineJournalError, } from '@optimystic/quereus-plugin-optimystic/plugin';
|
|
6
8
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,EAAE,sBAAsB,EAAiC,MAAM,wBAAwB,CAAC;AAC/F,OAAO,EACN,gBAAgB,EAChB,uBAAuB,EACvB,2BAA2B,EAC3B,sBAAsB,EACtB,2BAA2B,EAC3B,qBAAqB,EACrB,wBAAwB,EACxB,sBAAsB,EACtB,oBAAoB,EACpB,mBAAmB,EACnB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAKhF,OAAO,EACN,yBAAyB,EACzB,mCAAmC,EACnC,wBAAwB,EACxB,iBAAiB,EACjB,kBAAkB,EAClB,mBAAmB,GACnB,MAAM,8CAA8C,CAAC"}
|