@agentshouse/mdruntime 0.1.0-c49444f2a8fc6 → 0.1.0-c4d7cf2ec26a6
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/acceptance.d.ts +6 -0
- package/dist/acceptance.d.ts.map +1 -0
- package/dist/acceptance.js +386 -0
- package/dist/actions.d.ts +20 -0
- package/dist/actions.d.ts.map +1 -0
- package/dist/actions.js +251 -0
- package/dist/adapter.d.ts +6 -0
- package/dist/adapter.d.ts.map +1 -1
- package/dist/bootstrap.js +1 -0
- package/dist/cell.d.ts +6 -0
- package/dist/cell.d.ts.map +1 -0
- package/dist/cell.js +9 -0
- package/dist/change.d.ts.map +1 -1
- package/dist/change.js +4 -2
- package/dist/chat-types.d.ts +5 -0
- package/dist/chat-types.d.ts.map +1 -0
- package/dist/chat-types.js +13 -0
- package/dist/client.d.ts +12 -1
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +1 -0
- package/dist/compile.d.ts +5 -0
- package/dist/compile.d.ts.map +1 -1
- package/dist/compile.js +190 -59
- package/dist/connection.d.ts +5 -143
- package/dist/connection.d.ts.map +1 -1
- package/dist/connection.js +101 -5309
- package/dist/conversation-live.d.ts +136 -0
- package/dist/conversation-live.d.ts.map +1 -0
- package/dist/conversation-live.js +248 -0
- package/dist/conversation-row.d.ts.map +1 -1
- package/dist/conversation-row.js +7 -1
- package/dist/conversation.d.ts +22 -35
- package/dist/conversation.d.ts.map +1 -1
- package/dist/conversation.js +827 -972
- package/dist/discovery.d.ts +10 -0
- package/dist/discovery.d.ts.map +1 -0
- package/dist/discovery.js +175 -0
- package/dist/durability.d.ts +9 -0
- package/dist/durability.d.ts.map +1 -1
- package/dist/figures.d.ts +49 -0
- package/dist/figures.d.ts.map +1 -0
- package/dist/figures.js +197 -0
- package/dist/holdings.d.ts +29 -0
- package/dist/holdings.d.ts.map +1 -0
- package/dist/holdings.js +95 -0
- package/dist/host.d.ts +1 -0
- package/dist/host.d.ts.map +1 -1
- package/dist/host.js +7 -4
- package/dist/index.d.ts +16 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/install.d.ts +56 -0
- package/dist/install.d.ts.map +1 -0
- package/dist/install.js +554 -0
- package/dist/lifecycle.d.ts +7 -0
- package/dist/lifecycle.d.ts.map +1 -0
- package/dist/lifecycle.js +268 -0
- package/dist/listing.d.ts +53 -0
- package/dist/listing.d.ts.map +1 -0
- package/dist/listing.js +176 -0
- package/dist/live.d.ts.map +1 -1
- package/dist/live.js +0 -2
- package/dist/locks.d.ts +9 -0
- package/dist/locks.d.ts.map +1 -0
- package/dist/locks.js +61 -0
- package/dist/log.d.ts +1 -0
- package/dist/log.d.ts.map +1 -1
- package/dist/lost.d.ts +5 -0
- package/dist/lost.d.ts.map +1 -0
- package/dist/lost.js +61 -0
- package/dist/memory.d.ts.map +1 -1
- package/dist/memory.js +1 -0
- package/dist/messages.d.ts +1 -1
- package/dist/messages.d.ts.map +1 -1
- package/dist/messages.js +3 -3
- package/dist/models.d.ts +14 -0
- package/dist/models.d.ts.map +1 -0
- package/dist/models.js +195 -0
- package/dist/observation.d.ts.map +1 -1
- package/dist/observation.js +12 -17
- package/dist/opened.js +3 -3
- package/dist/opening.d.ts +4 -0
- package/dist/opening.d.ts.map +1 -0
- package/dist/opening.js +57 -0
- package/dist/outcome.d.ts +4 -1
- package/dist/outcome.d.ts.map +1 -1
- package/dist/outcome.js +3 -0
- package/dist/parts.d.ts +1 -0
- package/dist/parts.d.ts.map +1 -1
- package/dist/parts.js +8 -0
- package/dist/paths.d.ts +1 -0
- package/dist/paths.d.ts.map +1 -1
- package/dist/paths.js +22 -0
- package/dist/preparation.d.ts +20 -0
- package/dist/preparation.d.ts.map +1 -0
- package/dist/preparation.js +226 -0
- package/dist/queries.d.ts +16 -0
- package/dist/queries.d.ts.map +1 -0
- package/dist/queries.js +272 -0
- package/dist/query.d.ts +10 -0
- package/dist/query.d.ts.map +1 -1
- package/dist/questions.d.ts +2 -0
- package/dist/questions.d.ts.map +1 -1
- package/dist/questions.js +5 -1
- package/dist/reach.d.ts +3 -1
- package/dist/reach.d.ts.map +1 -1
- package/dist/reach.js +11 -0
- package/dist/react.d.ts +7 -1
- package/dist/react.d.ts.map +1 -1
- package/dist/readiness.d.ts +0 -1
- package/dist/readiness.d.ts.map +1 -1
- package/dist/reads.d.ts +37 -0
- package/dist/reads.d.ts.map +1 -0
- package/dist/reads.js +171 -0
- package/dist/refusal.d.ts +5 -0
- package/dist/refusal.d.ts.map +1 -0
- package/dist/refusal.js +56 -0
- package/dist/replica.d.ts +1 -3
- package/dist/replica.d.ts.map +1 -1
- package/dist/replica.js +3 -2
- package/dist/room-draft.d.ts +1 -1
- package/dist/room-draft.d.ts.map +1 -1
- package/dist/room-draft.js +2 -2
- package/dist/room-drafts.d.ts +24 -0
- package/dist/room-drafts.d.ts.map +1 -0
- package/dist/room-drafts.js +217 -0
- package/dist/runtime.d.ts +43 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +1 -0
- package/dist/save.d.ts +5 -1
- package/dist/save.d.ts.map +1 -1
- package/dist/save.js +12 -14
- package/dist/saves.d.ts +70 -0
- package/dist/saves.d.ts.map +1 -0
- package/dist/saves.js +1005 -0
- package/dist/seed.d.ts +11 -2
- package/dist/seed.d.ts.map +1 -1
- package/dist/seed.js +71 -0
- package/dist/shared.d.ts +1 -6
- package/dist/shared.d.ts.map +1 -1
- package/dist/shared.js +13 -95
- package/dist/shown.d.ts +31 -0
- package/dist/shown.d.ts.map +1 -0
- package/dist/shown.js +292 -0
- package/dist/socket/admission.d.ts +7 -0
- package/dist/socket/admission.d.ts.map +1 -0
- package/dist/socket/admission.js +39 -0
- package/dist/socket/answers.d.ts +6 -0
- package/dist/socket/answers.d.ts.map +1 -0
- package/dist/socket/answers.js +20 -0
- package/dist/socket/lanes.d.ts +20 -0
- package/dist/socket/lanes.d.ts.map +1 -0
- package/dist/socket/lanes.js +77 -0
- package/dist/socket/reads.d.ts +10 -0
- package/dist/socket/reads.d.ts.map +1 -0
- package/dist/socket/reads.js +31 -0
- package/dist/socket/rooms.d.ts +44 -0
- package/dist/socket/rooms.d.ts.map +1 -0
- package/dist/socket/rooms.js +90 -0
- package/dist/socket/session.d.ts +39 -0
- package/dist/socket/session.d.ts.map +1 -0
- package/dist/socket/session.js +23 -0
- package/dist/socket.d.ts +70 -0
- package/dist/socket.d.ts.map +1 -0
- package/dist/socket.js +175 -0
- package/dist/source.d.ts.map +1 -1
- package/dist/source.js +5 -4
- package/dist/store/fences.d.ts +16 -0
- package/dist/store/fences.d.ts.map +1 -0
- package/dist/store/fences.js +26 -0
- package/dist/store/installs.d.ts +30 -0
- package/dist/store/installs.d.ts.map +1 -0
- package/dist/store/installs.js +34 -0
- package/dist/store/readiness.d.ts +10 -0
- package/dist/store/readiness.d.ts.map +1 -0
- package/dist/store/readiness.js +52 -0
- package/dist/store/records.d.ts +212 -0
- package/dist/store/records.d.ts.map +1 -0
- package/dist/store/records.js +431 -0
- package/dist/store/room-held.d.ts +8 -0
- package/dist/store/room-held.d.ts.map +1 -0
- package/dist/store/room-held.js +17 -0
- package/dist/store/space.d.ts +11 -0
- package/dist/store/space.d.ts.map +1 -0
- package/dist/store/space.js +41 -0
- package/dist/store/watchers.d.ts +17 -0
- package/dist/store/watchers.d.ts.map +1 -0
- package/dist/store/watchers.js +56 -0
- package/dist/store/writes.d.ts +24 -0
- package/dist/store/writes.d.ts.map +1 -0
- package/dist/store/writes.js +125 -0
- package/dist/store.d.ts +111 -206
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +142 -398
- package/dist/stored.d.ts +1 -1
- package/dist/stored.d.ts.map +1 -1
- package/dist/stored.js +25 -11
- package/dist/surface.d.ts +88 -0
- package/dist/surface.d.ts.map +1 -0
- package/dist/surface.js +223 -0
- package/dist/sync.d.ts +19 -0
- package/dist/sync.d.ts.map +1 -0
- package/dist/sync.js +532 -0
- package/dist/tables.d.ts +32 -4
- package/dist/tables.d.ts.map +1 -1
- package/dist/tables.js +42 -8
- package/dist/tallies.d.ts +18 -0
- package/dist/tallies.d.ts.map +1 -0
- package/dist/tallies.js +129 -0
- package/dist/wire.d.ts +8 -1
- package/dist/wire.d.ts.map +1 -1
- package/dist/wire.js +4 -0
- package/package.json +2 -2
package/dist/sync.js
ADDED
|
@@ -0,0 +1,532 @@
|
|
|
1
|
+
import { submitAll, submitLater } from './acceptance.js';
|
|
2
|
+
import { resendCalls, resendLater } from './actions.js';
|
|
3
|
+
import { catchUpConversations, reconcileConversations, resendConversations, } from './conversation.js';
|
|
4
|
+
import { applyDiscovery, discoverRooms, malformed, signIn } from './discovery.js';
|
|
5
|
+
import { behind, caughtUpTo, publish, pullBootstrap, pullRefresh, reachedBy, replaced, standingAt, } from './install.js';
|
|
6
|
+
import { heldRooms, listHeld, name, readable } from './listing.js';
|
|
7
|
+
import { declaredAsHeld, keepNaming, retainModel, revoked, scoped } from './models.js';
|
|
8
|
+
import { refuse } from './refusal.js';
|
|
9
|
+
import { emitRooms, moveTo, rest, roomUnreadable, transferring, AUTHORITY_TOPIC } from './shown.js';
|
|
10
|
+
import { unconfirmed } from './transfer.js';
|
|
11
|
+
export const OPENING_LANE = 'opening';
|
|
12
|
+
async function advance(runtime, room, local, authorized, running, unheld) {
|
|
13
|
+
const { store, socket } = runtime;
|
|
14
|
+
const live = () => running() && !store.space.full();
|
|
15
|
+
if (!live())
|
|
16
|
+
return unconfirmed;
|
|
17
|
+
const held = unheld === undefined ? await store.record(room.locator) : undefined;
|
|
18
|
+
if (socket.streamed && (held !== undefined || !store.installs.of(room.locator).beyondHorizon)) {
|
|
19
|
+
socket.rooms.stand(room.locator, { stale: false });
|
|
20
|
+
await name(runtime, room.locator);
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
const refresh = socket.reads.refresh;
|
|
24
|
+
if (held !== undefined && refresh !== undefined) {
|
|
25
|
+
const refreshed = await store.ahead((hold) => refreshedRoom(runtime, room, local, authorized, held, live, hold, refresh));
|
|
26
|
+
if (refreshed === 'behind')
|
|
27
|
+
return advance(runtime, room, local, authorized, live);
|
|
28
|
+
if (refreshed !== 'beyond-horizon')
|
|
29
|
+
return refreshed;
|
|
30
|
+
if (socket.rooms.standing(room.locator).reloadDue)
|
|
31
|
+
return unconfirmed;
|
|
32
|
+
replaced(store, [room.locator]);
|
|
33
|
+
}
|
|
34
|
+
const prior = held === undefined ? undefined : await store.record(room.locator);
|
|
35
|
+
const from = standingAt(store, room.locator, prior);
|
|
36
|
+
const bootstrapped = await pullBootstrap(runtime, authorized, room, local, live, prior, socket.reads, unheld);
|
|
37
|
+
if (bootstrapped.kind !== 'staged')
|
|
38
|
+
return live() ? bootstrapped : unconfirmed;
|
|
39
|
+
const landing = { kind: 'bootstrapped', refreshed: bootstrapped.refreshed, from };
|
|
40
|
+
if (await publish(runtime, local, room, bootstrapped.record, landing, live)) {
|
|
41
|
+
return live() ? null : unconfirmed;
|
|
42
|
+
}
|
|
43
|
+
return (await reachedBy(runtime, room.locator, bootstrapped.record.roomVersion))
|
|
44
|
+
? null
|
|
45
|
+
: advance(runtime, room, local, authorized, live);
|
|
46
|
+
}
|
|
47
|
+
async function refreshedRoom(runtime, room, local, authorized, held, live, hold, refresh) {
|
|
48
|
+
const { store, socket } = runtime;
|
|
49
|
+
const { rooms } = socket;
|
|
50
|
+
const refreshed = await pullRefresh(runtime, authorized, held, live, hold, refresh);
|
|
51
|
+
if (!live())
|
|
52
|
+
return unconfirmed;
|
|
53
|
+
if (refreshed.kind === 'still-current') {
|
|
54
|
+
rooms.stand(room.locator, { stale: false });
|
|
55
|
+
if (rooms.standing(room.locator).unreadable) {
|
|
56
|
+
rooms.stand(room.locator, { refusal: null });
|
|
57
|
+
readable(runtime, room);
|
|
58
|
+
emitRooms(runtime);
|
|
59
|
+
}
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
if (refreshed.kind === 'advanced') {
|
|
63
|
+
const landing = {
|
|
64
|
+
kind: 'refreshed',
|
|
65
|
+
from: refreshed.from,
|
|
66
|
+
remodelled: refreshed.remodelled,
|
|
67
|
+
};
|
|
68
|
+
if (!(await publish(runtime, local, room, refreshed.record, landing, live))) {
|
|
69
|
+
const now = (await store.record(room.locator))?.roomVersion;
|
|
70
|
+
const reached = now !== undefined && socket.reads.reached(room.locator, now, refreshed.record.roomVersion);
|
|
71
|
+
return reached ? null : 'behind';
|
|
72
|
+
}
|
|
73
|
+
await retainModel(runtime, local, room, null);
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
return refreshed.kind === 'beyond-horizon' ? 'beyond-horizon' : refreshed;
|
|
77
|
+
}
|
|
78
|
+
export function advanced(runtime, room, local, authorized) {
|
|
79
|
+
return runtime.socket.lanes.inRoom(room.locator, (live) => advance(runtime, room, local, authorized, live));
|
|
80
|
+
}
|
|
81
|
+
export async function withhold(runtime, withheld, room, local, progress) {
|
|
82
|
+
const { store, socket, journal } = runtime;
|
|
83
|
+
const { rooms } = socket;
|
|
84
|
+
if (withheld.kind === 'unconfirmed' || store.fences.has(room.locator))
|
|
85
|
+
return;
|
|
86
|
+
if (withheld.kind === 'not-ready') {
|
|
87
|
+
progress.complete = false;
|
|
88
|
+
askAgain(runtime, room.locator);
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
rooms.stand(room.locator, { stale: true });
|
|
92
|
+
if (withheld.kind === 'transport-uncertainty' || withheld.kind === 'retryable-refusal') {
|
|
93
|
+
const reset = withheld.kind === 'retryable-refusal' ? withheld.reset : undefined;
|
|
94
|
+
rooms.stand(room.locator, { repairable: { reset } });
|
|
95
|
+
repairLater(runtime, room.locator, reset === undefined ? { again: true } : { at: Date.parse(reset) });
|
|
96
|
+
}
|
|
97
|
+
else
|
|
98
|
+
rooms.stand(room.locator, { repairable: null });
|
|
99
|
+
if (withheld.kind === 'scoped-refusal') {
|
|
100
|
+
await scoped(runtime, withheld, room, local);
|
|
101
|
+
}
|
|
102
|
+
else if (withheld.kind === 'transport-uncertainty') {
|
|
103
|
+
progress.reachable = false;
|
|
104
|
+
}
|
|
105
|
+
else if (withheld.kind === 'retryable-refusal') {
|
|
106
|
+
journal.record(`refusal ${withheld.kind} ${withheld.code}`);
|
|
107
|
+
}
|
|
108
|
+
else if (withheld.kind === 'room-not-readable') {
|
|
109
|
+
roomUnreadable(runtime, room);
|
|
110
|
+
}
|
|
111
|
+
else if (withheld.kind === 'revoked-authorization') {
|
|
112
|
+
await refuse(runtime, 'revoked-authorization');
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
function askAgain(runtime, locator) {
|
|
116
|
+
const { store, socket } = runtime;
|
|
117
|
+
socket.rooms.askAgain(locator, () => {
|
|
118
|
+
const room = socket.rooms.discovered(locator);
|
|
119
|
+
if (socket.closed() ||
|
|
120
|
+
socket.stopping() ||
|
|
121
|
+
(socket.streamed && !socket.isOpen()) ||
|
|
122
|
+
room === undefined)
|
|
123
|
+
return;
|
|
124
|
+
const progress = { complete: true, reachable: true };
|
|
125
|
+
void store
|
|
126
|
+
.open()
|
|
127
|
+
.then((local) => socket.lanes.roomTask(locator, (live) => loadRoom(runtime, room, local, progress, live)))
|
|
128
|
+
.then(() => rest(runtime, progress), () => undefined);
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
async function prepareRoom(runtime, room, local, progress, prior) {
|
|
132
|
+
const { socket, journal } = runtime;
|
|
133
|
+
const { session } = socket;
|
|
134
|
+
if (socket.closed() || session.now().authorization === undefined) {
|
|
135
|
+
progress.complete = false;
|
|
136
|
+
return false;
|
|
137
|
+
}
|
|
138
|
+
if (prior !== undefined && prior.replica.selection !== room.replica.selection) {
|
|
139
|
+
listHeld(runtime, room.locator);
|
|
140
|
+
emitRooms(runtime);
|
|
141
|
+
journal.record(`selection changed ${room.locator}`);
|
|
142
|
+
progress.complete = false;
|
|
143
|
+
return false;
|
|
144
|
+
}
|
|
145
|
+
if (prior !== undefined && !declaredAsHeld(prior, room)) {
|
|
146
|
+
await retainModel(runtime, local, room, null);
|
|
147
|
+
}
|
|
148
|
+
if (prior !== undefined && (prior.name !== room.name || prior.handle !== room.handle)) {
|
|
149
|
+
await keepNaming(runtime, local, room);
|
|
150
|
+
}
|
|
151
|
+
const { paused, authorization } = session.now();
|
|
152
|
+
if (paused || authorization === undefined)
|
|
153
|
+
return false;
|
|
154
|
+
return room.replica.admission === 'admitted';
|
|
155
|
+
}
|
|
156
|
+
async function synchronize(runtime, listed, local, progress, attempt, live) {
|
|
157
|
+
const { store, socket } = runtime;
|
|
158
|
+
const heldNow = await store.rooms(listed.map(({ locator }) => locator));
|
|
159
|
+
const prepared = await Promise.allSettled(listed.map((room) => prepareRoom(runtime, room, local, progress, heldNow.get(room.locator)?.record)));
|
|
160
|
+
if (!live())
|
|
161
|
+
return;
|
|
162
|
+
const ready = listed.filter((_, index) => {
|
|
163
|
+
const outcome = prepared[index];
|
|
164
|
+
return outcome.status === 'fulfilled' && outcome.value;
|
|
165
|
+
});
|
|
166
|
+
if (attempt === 'opened') {
|
|
167
|
+
const held = await heldRooms(runtime, ready);
|
|
168
|
+
if (!live())
|
|
169
|
+
return;
|
|
170
|
+
socket.hand(held);
|
|
171
|
+
}
|
|
172
|
+
const kept = attempt === 'authorized'
|
|
173
|
+
? new Set((await store.rooms(ready.map(({ locator }) => locator))).keys())
|
|
174
|
+
: new Set();
|
|
175
|
+
for (const room of ready) {
|
|
176
|
+
if (attempt === 'opened' || kept.has(room.locator)) {
|
|
177
|
+
if (attempt === 'authorized')
|
|
178
|
+
await name(runtime, room.locator);
|
|
179
|
+
continue;
|
|
180
|
+
}
|
|
181
|
+
void socket.lanes
|
|
182
|
+
.roomTask(room.locator, (live) => loadRoom(runtime, room, local, progress, live))
|
|
183
|
+
.then(() => rest(runtime, progress));
|
|
184
|
+
}
|
|
185
|
+
const failed = prepared.find((room) => room.status === 'rejected');
|
|
186
|
+
if (failed !== undefined)
|
|
187
|
+
throw failed.reason;
|
|
188
|
+
}
|
|
189
|
+
async function caughtUp(runtime, room, local, progress, live) {
|
|
190
|
+
const { socket } = runtime;
|
|
191
|
+
const { authorization } = socket.session.now();
|
|
192
|
+
if (socket.streamed || authorization === undefined)
|
|
193
|
+
return;
|
|
194
|
+
if (!live() || !(await behind(runtime, room)))
|
|
195
|
+
return;
|
|
196
|
+
const withheld = await advance(runtime, room, local, authorization, live);
|
|
197
|
+
if (withheld !== null)
|
|
198
|
+
await withhold(runtime, withheld, room, local, progress);
|
|
199
|
+
}
|
|
200
|
+
export async function loadRoom(runtime, room, local, progress, live, unheld) {
|
|
201
|
+
const { store, socket } = runtime;
|
|
202
|
+
const { authorization } = socket.session.now();
|
|
203
|
+
if (!live() || authorization === undefined)
|
|
204
|
+
return;
|
|
205
|
+
const prior = unheld === undefined ? await store.record(room.locator) : undefined;
|
|
206
|
+
if (prior !== undefined) {
|
|
207
|
+
if (!(await prepareRoom(runtime, room, local, progress, prior)))
|
|
208
|
+
return;
|
|
209
|
+
if (revoked(prior.model)) {
|
|
210
|
+
await reload(runtime, room, local, progress, live);
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
const withheld = await advance(runtime, room, local, authorization, live, unheld);
|
|
215
|
+
if (withheld !== null) {
|
|
216
|
+
await withhold(runtime, withheld, room, local, progress);
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
await caughtUp(runtime, room, local, progress, live);
|
|
220
|
+
}
|
|
221
|
+
export async function reload(runtime, room, local, progress, live) {
|
|
222
|
+
const { store, socket } = runtime;
|
|
223
|
+
try {
|
|
224
|
+
if (live())
|
|
225
|
+
socket.rooms.stand(room.locator, { reloadDue: false });
|
|
226
|
+
const { authorization } = socket.session.now();
|
|
227
|
+
if (!live() || authorization === undefined)
|
|
228
|
+
return;
|
|
229
|
+
const prior = await store.record(room.locator);
|
|
230
|
+
const from = standingAt(store, room.locator, prior);
|
|
231
|
+
const bootstrapped = await pullBootstrap(runtime, authorization, room, local, live, prior);
|
|
232
|
+
if (bootstrapped.kind !== 'staged') {
|
|
233
|
+
if (live())
|
|
234
|
+
await withhold(runtime, bootstrapped, room, local, progress);
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
await publish(runtime, local, room, bootstrapped.record, { kind: 'bootstrapped', refreshed: bootstrapped.refreshed, from }, live);
|
|
238
|
+
await caughtUp(runtime, room, local, progress, live);
|
|
239
|
+
}
|
|
240
|
+
finally {
|
|
241
|
+
caughtUpTo(runtime, room.locator);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
function repairLater(runtime, locator, when) {
|
|
245
|
+
const { socket, recovery } = runtime;
|
|
246
|
+
if (!socket.isOpen() || socket.rooms.standing(locator).repairing)
|
|
247
|
+
return;
|
|
248
|
+
void recovery.attempt(`repair ${locator}`, (signal) => repairPass(runtime, locator, signal), when);
|
|
249
|
+
}
|
|
250
|
+
async function repairPass(runtime, locator, signal) {
|
|
251
|
+
const { store, socket } = runtime;
|
|
252
|
+
const { rooms } = socket;
|
|
253
|
+
const room = rooms.discovered(locator);
|
|
254
|
+
if (!socket.isOpen() ||
|
|
255
|
+
!socket.continuing() ||
|
|
256
|
+
socket.stopping() ||
|
|
257
|
+
!rooms.standing(locator).stale)
|
|
258
|
+
return 'done';
|
|
259
|
+
if (room === undefined || room.replica.admission !== 'admitted')
|
|
260
|
+
return 'done';
|
|
261
|
+
const progress = { complete: true, reachable: true };
|
|
262
|
+
rooms.stand(locator, { repairing: true });
|
|
263
|
+
try {
|
|
264
|
+
const local = await store.open();
|
|
265
|
+
await socket.lanes.roomTask(locator, async (live) => {
|
|
266
|
+
const { authorization } = socket.session.now();
|
|
267
|
+
if (!live() || authorization === undefined)
|
|
268
|
+
return;
|
|
269
|
+
const withheld = await advance(runtime, room, local, authorization, live);
|
|
270
|
+
if (withheld !== null && live())
|
|
271
|
+
await withhold(runtime, withheld, room, local, progress);
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
catch {
|
|
275
|
+
rooms.stand(locator, { stale: true });
|
|
276
|
+
progress.reachable = false;
|
|
277
|
+
}
|
|
278
|
+
finally {
|
|
279
|
+
rooms.stand(locator, { repairing: false });
|
|
280
|
+
}
|
|
281
|
+
if (signal.aborted)
|
|
282
|
+
return 'done';
|
|
283
|
+
await rest(runtime, progress);
|
|
284
|
+
if (!rooms.standing(locator).stale) {
|
|
285
|
+
if ((await (await store.open()).order(locator)).length > 0)
|
|
286
|
+
submitLater(runtime, locator);
|
|
287
|
+
return 'done';
|
|
288
|
+
}
|
|
289
|
+
const { repairable } = rooms.standing(locator);
|
|
290
|
+
if (repairable === null)
|
|
291
|
+
return 'done';
|
|
292
|
+
return repairable.reset === undefined ? 'again' : { at: Date.parse(repairable.reset) };
|
|
293
|
+
}
|
|
294
|
+
export async function finishOpening(runtime, progress, live) {
|
|
295
|
+
const { socket, conversations, recovery } = runtime;
|
|
296
|
+
try {
|
|
297
|
+
if (!live()) {
|
|
298
|
+
progress.complete = false;
|
|
299
|
+
return;
|
|
300
|
+
}
|
|
301
|
+
await submitAll(runtime);
|
|
302
|
+
for (const locator of socket.rooms.standingWhere(({ stale, repairable }) => stale && repairable !== null)) {
|
|
303
|
+
repairLater(runtime, locator, {});
|
|
304
|
+
}
|
|
305
|
+
await reconcileConversations(conversations);
|
|
306
|
+
const reading = { complete: true, reachable: true };
|
|
307
|
+
await catchUpConversations(conversations, reading);
|
|
308
|
+
if (progress.reachable && reading.reachable)
|
|
309
|
+
await resendConversations(conversations, reading);
|
|
310
|
+
if (progress.reachable) {
|
|
311
|
+
void recovery.attempt('calls', (signal) => resendCalls(runtime, signal));
|
|
312
|
+
}
|
|
313
|
+
if (!reading.reachable) {
|
|
314
|
+
progress.reachable = false;
|
|
315
|
+
resendLater(runtime);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
catch {
|
|
319
|
+
progress.complete = false;
|
|
320
|
+
}
|
|
321
|
+
finally {
|
|
322
|
+
if (live()) {
|
|
323
|
+
socket.session.set({ complete: progress.complete });
|
|
324
|
+
await rest(runtime, progress, live);
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
export function sync(runtime, attempt, found) {
|
|
329
|
+
const { store, socket } = runtime;
|
|
330
|
+
const { session } = socket;
|
|
331
|
+
return socket.lanes.task(OPENING_LANE, async (live) => {
|
|
332
|
+
if (!live()) {
|
|
333
|
+
socket.readyFromStore();
|
|
334
|
+
return;
|
|
335
|
+
}
|
|
336
|
+
const progress = { complete: true, reachable: true };
|
|
337
|
+
session.set({
|
|
338
|
+
underway: attempt === 'opened' ? progress : null,
|
|
339
|
+
...(attempt === 'opened' ? { streamed: progress } : {}),
|
|
340
|
+
complete: false,
|
|
341
|
+
recorded: false,
|
|
342
|
+
});
|
|
343
|
+
moveTo(runtime, transferring(runtime));
|
|
344
|
+
try {
|
|
345
|
+
const local = await store.open();
|
|
346
|
+
if (!live())
|
|
347
|
+
return;
|
|
348
|
+
await socket.authorize();
|
|
349
|
+
if (!live())
|
|
350
|
+
return;
|
|
351
|
+
const listed = await discoverRooms(runtime, local, progress, live, found);
|
|
352
|
+
if (listed !== null)
|
|
353
|
+
await synchronize(runtime, listed, local, progress, attempt, live);
|
|
354
|
+
}
|
|
355
|
+
catch {
|
|
356
|
+
progress.complete = false;
|
|
357
|
+
if (attempt === 'opened' && !socket.isHanded())
|
|
358
|
+
progress.reachable = false;
|
|
359
|
+
}
|
|
360
|
+
finally {
|
|
361
|
+
socket.notifyReady();
|
|
362
|
+
}
|
|
363
|
+
if (!live())
|
|
364
|
+
return;
|
|
365
|
+
if (attempt !== 'opened') {
|
|
366
|
+
await finishOpening(runtime, progress, live);
|
|
367
|
+
return;
|
|
368
|
+
}
|
|
369
|
+
if (socket.isHanded() || socket.closed() || progress.reachable)
|
|
370
|
+
return;
|
|
371
|
+
session.set({ underway: null });
|
|
372
|
+
await rest(runtime, progress, live);
|
|
373
|
+
});
|
|
374
|
+
}
|
|
375
|
+
export function resynchronize(runtime) {
|
|
376
|
+
const { store, socket } = runtime;
|
|
377
|
+
return socket.lanes.task(OPENING_LANE, async (live) => {
|
|
378
|
+
if (!live() || !socket.isAnnounced())
|
|
379
|
+
return;
|
|
380
|
+
const progress = { complete: true, reachable: true };
|
|
381
|
+
moveTo(runtime, transferring(runtime));
|
|
382
|
+
try {
|
|
383
|
+
const local = await store.open();
|
|
384
|
+
if (!live())
|
|
385
|
+
return;
|
|
386
|
+
await synchronize(runtime, socket.rooms.discoveredRooms(), local, progress, 'unstreamed', live);
|
|
387
|
+
}
|
|
388
|
+
catch {
|
|
389
|
+
progress.complete = false;
|
|
390
|
+
}
|
|
391
|
+
if (live())
|
|
392
|
+
await finishOpening(runtime, progress, live);
|
|
393
|
+
});
|
|
394
|
+
}
|
|
395
|
+
export function countAuthorityChange({ store, socket, lastAnswers }) {
|
|
396
|
+
const authorityChanges = socket.session.now().authorityChanges + 1;
|
|
397
|
+
socket.session.set({ authorityChanges });
|
|
398
|
+
store.tell(AUTHORITY_TOPIC, authorityChanges);
|
|
399
|
+
lastAnswers.again();
|
|
400
|
+
}
|
|
401
|
+
export function changeAuthority(runtime, change) {
|
|
402
|
+
const { store, socket, journal } = runtime;
|
|
403
|
+
const { session } = socket;
|
|
404
|
+
return socket.lanes.task(OPENING_LANE, async (live) => {
|
|
405
|
+
if (!live() || !socket.isAnnounced())
|
|
406
|
+
return;
|
|
407
|
+
countAuthorityChange(runtime);
|
|
408
|
+
const progress = { complete: true, reachable: true };
|
|
409
|
+
moveTo(runtime, transferring(runtime));
|
|
410
|
+
try {
|
|
411
|
+
const local = await store.open();
|
|
412
|
+
if (!live())
|
|
413
|
+
return;
|
|
414
|
+
const invalid = malformed(change.rooms);
|
|
415
|
+
if (invalid !== null) {
|
|
416
|
+
journal.record(invalid);
|
|
417
|
+
await refuse(runtime, 'missing-required-guarantee');
|
|
418
|
+
return;
|
|
419
|
+
}
|
|
420
|
+
if (change.member !== undefined)
|
|
421
|
+
await signIn(runtime, local, change.member);
|
|
422
|
+
const discoveries = session.now().discoveries + 1;
|
|
423
|
+
session.set({ discoveries });
|
|
424
|
+
const listed = await applyDiscovery(runtime, change.rooms, discoveries, change.left);
|
|
425
|
+
await synchronize(runtime, listed, local, progress, 'authorized', live);
|
|
426
|
+
}
|
|
427
|
+
catch {
|
|
428
|
+
progress.complete = false;
|
|
429
|
+
}
|
|
430
|
+
if (!live())
|
|
431
|
+
return;
|
|
432
|
+
if (!progress.complete)
|
|
433
|
+
session.set({ complete: false });
|
|
434
|
+
await rest(runtime, progress, live);
|
|
435
|
+
});
|
|
436
|
+
}
|
|
437
|
+
async function installCarried(runtime, room, local, change, live, progress) {
|
|
438
|
+
const { store, socket } = runtime;
|
|
439
|
+
const { authorization, underway } = socket.session.now();
|
|
440
|
+
if (authorization === undefined)
|
|
441
|
+
return;
|
|
442
|
+
if (underway === null)
|
|
443
|
+
moveTo(runtime, transferring(runtime));
|
|
444
|
+
const prior = await store.record(room.locator);
|
|
445
|
+
const from = standingAt(store, room.locator, prior);
|
|
446
|
+
const page = await change.read();
|
|
447
|
+
const carried = {
|
|
448
|
+
bootstrap: () => Promise.resolve({
|
|
449
|
+
kind: 'bootstrap',
|
|
450
|
+
roomVersion: page.roomVersion,
|
|
451
|
+
...(page.models === undefined ? {} : { models: page.models }),
|
|
452
|
+
documents: page.documents,
|
|
453
|
+
facts: page.facts,
|
|
454
|
+
revisions: page.revisions,
|
|
455
|
+
...(page.fileIds === undefined ? {} : { fileIds: page.fileIds }),
|
|
456
|
+
...(page.created === undefined ? {} : { created: page.created }),
|
|
457
|
+
changes: page.changes,
|
|
458
|
+
binaryFiles: page.binaryFiles,
|
|
459
|
+
...(page.folders === undefined ? {} : { folders: page.folders }),
|
|
460
|
+
}),
|
|
461
|
+
reached: socket.reads.reached,
|
|
462
|
+
};
|
|
463
|
+
const bootstrapped = await pullBootstrap(runtime, authorization, room, local, live, prior, carried);
|
|
464
|
+
if (bootstrapped.kind !== 'staged') {
|
|
465
|
+
if (live())
|
|
466
|
+
await withhold(runtime, bootstrapped, room, local, progress);
|
|
467
|
+
return;
|
|
468
|
+
}
|
|
469
|
+
await publish(runtime, local, room, bootstrapped.record, { kind: 'bootstrapped', refreshed: bootstrapped.refreshed, from }, live);
|
|
470
|
+
}
|
|
471
|
+
export function applyRoom(runtime, change) {
|
|
472
|
+
const { store, socket } = runtime;
|
|
473
|
+
const { rooms, session } = socket;
|
|
474
|
+
const { locator } = change;
|
|
475
|
+
if (socket.stopping())
|
|
476
|
+
return Promise.resolve();
|
|
477
|
+
return socket.lanes
|
|
478
|
+
.inRoom(locator, async (live) => {
|
|
479
|
+
await socket.answered(locator);
|
|
480
|
+
const progress = session.now().underway ?? { complete: true, reachable: true };
|
|
481
|
+
try {
|
|
482
|
+
const local = await store.open();
|
|
483
|
+
for (;;) {
|
|
484
|
+
if (!live())
|
|
485
|
+
return null;
|
|
486
|
+
const room = rooms.discovered(locator);
|
|
487
|
+
if (room === undefined || room.replica.admission !== 'admitted')
|
|
488
|
+
return null;
|
|
489
|
+
const held = await store.record(locator);
|
|
490
|
+
if (held === undefined) {
|
|
491
|
+
if (change.from !== null)
|
|
492
|
+
return null;
|
|
493
|
+
await installCarried(runtime, room, local, change, live, progress);
|
|
494
|
+
return progress;
|
|
495
|
+
}
|
|
496
|
+
if (held.replica.selection !== room.replica.selection)
|
|
497
|
+
return null;
|
|
498
|
+
const at = held.roomVersion;
|
|
499
|
+
if (socket.reads.reached(locator, at, change.roomVersion))
|
|
500
|
+
return progress;
|
|
501
|
+
if (change.from === null || !socket.reads.reached(locator, at, change.from)) {
|
|
502
|
+
await name(runtime, locator);
|
|
503
|
+
return progress;
|
|
504
|
+
}
|
|
505
|
+
if (session.now().underway === null)
|
|
506
|
+
moveTo(runtime, transferring(runtime));
|
|
507
|
+
const writing = () => live() && !store.space.full();
|
|
508
|
+
const refreshed = await store.ahead((hold) => pullRefresh(runtime, session.now().authorization ?? {}, held, writing, hold, () => change.read()));
|
|
509
|
+
if (refreshed.kind !== 'advanced')
|
|
510
|
+
return progress;
|
|
511
|
+
const landing = {
|
|
512
|
+
kind: 'refreshed',
|
|
513
|
+
from: refreshed.from,
|
|
514
|
+
remodelled: refreshed.remodelled,
|
|
515
|
+
};
|
|
516
|
+
if (await publish(runtime, local, room, refreshed.record, landing, writing)) {
|
|
517
|
+
rooms.stand(locator, { stale: false });
|
|
518
|
+
if (!declaredAsHeld(held, room))
|
|
519
|
+
await retainModel(runtime, local, room, null);
|
|
520
|
+
return progress;
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
catch {
|
|
525
|
+
if (!rooms.standing(locator).stale)
|
|
526
|
+
void name(runtime, locator);
|
|
527
|
+
rooms.stand(locator, { stale: true });
|
|
528
|
+
return progress;
|
|
529
|
+
}
|
|
530
|
+
})
|
|
531
|
+
.then((progress) => rest(runtime, progress), () => undefined);
|
|
532
|
+
}
|
package/dist/tables.d.ts
CHANGED
|
@@ -3,11 +3,14 @@ import type { Composed } from './collection.js';
|
|
|
3
3
|
import type { UnsentWork } from './durability.js';
|
|
4
4
|
import type { JobMarker } from './job.js';
|
|
5
5
|
import { type ConversationWrite, type HeldConversation, type HeldRow, type MessageWindow } from './messages.js';
|
|
6
|
-
import type { Plan } from './query.js';
|
|
6
|
+
import type { GroupTotal, Plan } from './query.js';
|
|
7
|
+
import { type ReadAt } from './reads.js';
|
|
8
|
+
import { type ConversationTally, type RoomTally } from './tallies.js';
|
|
7
9
|
import { type Committed, type Covering, type HeldEntry, type HeldLocators, type HeldRoomRow, type HeldRoomWork, type ReplicaOpened, type Referrer, type Resumed, type RoomCommit, type StoredEntry, type TypedEntry, type View } from './stored.js';
|
|
8
10
|
export type { Committed, Covering, HeldEntry, HeldLocators, HeldRoomRow, HeldRoomWork, OverlayEntry, ReplicaOpened, Referrer, Resumed, RoomCommit, StoredEntry, TypedEntry, View, } from './stored.js';
|
|
9
11
|
export type { QueryAnswer, QueryRoom } from './compile.js';
|
|
10
12
|
export type { ConversationWrite, HeldConversation, HeldRow, MessageWindow } from './messages.js';
|
|
13
|
+
export type { ConversationTally, RoomTally } from './tallies.js';
|
|
11
14
|
export type Value = string | number | bigint | Uint8Array | null;
|
|
12
15
|
export type Row = Readonly<Record<string, Value>>;
|
|
13
16
|
export interface Connection {
|
|
@@ -50,7 +53,7 @@ export interface SqliteDatabase {
|
|
|
50
53
|
export declare function sqliteConnection(engine: SqliteEngine, database: SqliteDatabase): Connection;
|
|
51
54
|
export declare const FILE_PART_BYTES = 1048576;
|
|
52
55
|
export declare const RUNTIME_TABLES: readonly string[];
|
|
53
|
-
export type AuthoredFact = 'holder' | '
|
|
56
|
+
export type AuthoredFact = 'holder' | 'generation';
|
|
54
57
|
export type StoredFile = {
|
|
55
58
|
readonly key: string;
|
|
56
59
|
readonly blob: Blob;
|
|
@@ -113,6 +116,13 @@ export type OpenedFile = {
|
|
|
113
116
|
readonly byteLength: number;
|
|
114
117
|
readonly mediaType: string;
|
|
115
118
|
};
|
|
119
|
+
export type OpenedRoom = GroupTotal & {
|
|
120
|
+
readonly room: string;
|
|
121
|
+
};
|
|
122
|
+
export type OpenedHeld = {
|
|
123
|
+
readonly rooms: readonly OpenedRoom[];
|
|
124
|
+
readonly cleanable: number;
|
|
125
|
+
};
|
|
116
126
|
type Asked<A, R> = {
|
|
117
127
|
readonly asked: A;
|
|
118
128
|
readonly answer: R;
|
|
@@ -217,6 +227,11 @@ export interface RuntimeRequests {
|
|
|
217
227
|
readonly rooms: readonly QueryRoom[];
|
|
218
228
|
readonly budget: number | null;
|
|
219
229
|
}, QueryAnswer>;
|
|
230
|
+
readonly 'replica.tallies': Asked<{
|
|
231
|
+
readonly totals: Plan;
|
|
232
|
+
readonly rooms: readonly QueryRoom[];
|
|
233
|
+
readonly since: string;
|
|
234
|
+
}, readonly RoomTally[]>;
|
|
220
235
|
readonly 'replica.entries': Asked<{
|
|
221
236
|
readonly key: number;
|
|
222
237
|
readonly view: View;
|
|
@@ -234,7 +249,6 @@ export interface RuntimeRequests {
|
|
|
234
249
|
}, readonly Referrer[]>;
|
|
235
250
|
readonly 'replica.folders': Asked<{
|
|
236
251
|
readonly key: number;
|
|
237
|
-
readonly view: View;
|
|
238
252
|
readonly paths: readonly string[];
|
|
239
253
|
}, readonly string[]>;
|
|
240
254
|
readonly 'replica.typedWithin': Asked<{
|
|
@@ -337,6 +351,7 @@ export interface RuntimeRequests {
|
|
|
337
351
|
readonly key: string;
|
|
338
352
|
}, null>;
|
|
339
353
|
readonly 'opened.clean': Asked<Nothing, number>;
|
|
354
|
+
readonly 'opened.held': Asked<Nothing, OpenedHeld>;
|
|
340
355
|
readonly 'file.part': Asked<{
|
|
341
356
|
readonly key: string;
|
|
342
357
|
readonly part: number;
|
|
@@ -365,10 +380,21 @@ export interface RuntimeRequests {
|
|
|
365
380
|
readonly 'conversation.jobs': Asked<{
|
|
366
381
|
readonly conversation: string;
|
|
367
382
|
}, readonly JobMarker[]>;
|
|
383
|
+
readonly 'conversation.tallies': Asked<{
|
|
384
|
+
readonly conversations: readonly string[] | null;
|
|
385
|
+
readonly since: string;
|
|
386
|
+
}, readonly ConversationTally[]>;
|
|
368
387
|
readonly 'conversation.drop': Asked<{
|
|
369
388
|
readonly conversations: readonly string[];
|
|
370
389
|
}, null>;
|
|
371
390
|
readonly 'space.probe': Asked<Nothing, null>;
|
|
391
|
+
readonly 'read.stored': Asked<ReadAt, string | null>;
|
|
392
|
+
readonly 'read.keep': Asked<ReadAt & {
|
|
393
|
+
readonly answer: string;
|
|
394
|
+
}, null>;
|
|
395
|
+
readonly 'read.builds': Asked<{
|
|
396
|
+
readonly build: string;
|
|
397
|
+
}, null>;
|
|
372
398
|
}
|
|
373
399
|
export type RuntimeKind = keyof RuntimeRequests;
|
|
374
400
|
export type RuntimeRequest<K extends RuntimeKind = RuntimeKind> = {
|
|
@@ -383,6 +409,8 @@ export interface RuntimeDatabase {
|
|
|
383
409
|
export declare function isRuntime(request: {
|
|
384
410
|
readonly kind: string;
|
|
385
411
|
}): request is RuntimeRequest;
|
|
386
|
-
export declare function readsRuntime(request:
|
|
412
|
+
export declare function readsRuntime(request: {
|
|
413
|
+
readonly kind: string;
|
|
414
|
+
}): boolean;
|
|
387
415
|
export declare function answerRuntime(connection: Connection, request: RuntimeRequest, spool: FileSpool): unknown;
|
|
388
416
|
//# sourceMappingURL=tables.d.ts.map
|