@agentshouse/mdruntime 0.1.0-cd507e16e5fc0 → 0.1.0-cd574a610e9c8

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.
Files changed (269) hide show
  1. package/README.md +21 -19
  2. package/dist/acceptance.d.ts +0 -3
  3. package/dist/acceptance.d.ts.map +1 -1
  4. package/dist/acceptance.js +75 -165
  5. package/dist/act-lanes.d.ts +30 -0
  6. package/dist/act-lanes.d.ts.map +1 -0
  7. package/dist/act-lanes.js +225 -0
  8. package/dist/actions.d.ts +8 -2
  9. package/dist/actions.d.ts.map +1 -1
  10. package/dist/actions.js +118 -67
  11. package/dist/adapter.d.ts +90 -58
  12. package/dist/adapter.d.ts.map +1 -1
  13. package/dist/attached-model.d.ts +0 -1
  14. package/dist/attached-model.d.ts.map +1 -1
  15. package/dist/attached-model.js +0 -5
  16. package/dist/authored.d.ts +88 -0
  17. package/dist/authored.d.ts.map +1 -0
  18. package/dist/authored.js +345 -0
  19. package/dist/bootstrap.d.ts +1 -1
  20. package/dist/bootstrap.d.ts.map +1 -1
  21. package/dist/bootstrap.js +6 -19
  22. package/dist/change-set.d.ts +4 -0
  23. package/dist/change-set.d.ts.map +1 -1
  24. package/dist/change-set.js +6 -0
  25. package/dist/change.d.ts +4 -0
  26. package/dist/change.d.ts.map +1 -1
  27. package/dist/change.js +7 -2
  28. package/dist/chat-types.d.ts +0 -2
  29. package/dist/chat-types.d.ts.map +1 -1
  30. package/dist/chat-types.js +0 -2
  31. package/dist/client.d.ts +13 -20
  32. package/dist/client.d.ts.map +1 -1
  33. package/dist/client.js +36 -20
  34. package/dist/collection.d.ts +25 -4
  35. package/dist/collection.d.ts.map +1 -1
  36. package/dist/collection.js +19 -2
  37. package/dist/column.d.ts +5 -0
  38. package/dist/column.d.ts.map +1 -0
  39. package/dist/column.js +9 -0
  40. package/dist/compile.d.ts +2 -0
  41. package/dist/compile.d.ts.map +1 -1
  42. package/dist/compile.js +31 -25
  43. package/dist/connection.d.ts.map +1 -1
  44. package/dist/connection.js +31 -24
  45. package/dist/context.d.ts.map +1 -1
  46. package/dist/context.js +1 -1
  47. package/dist/conversation-live.d.ts +26 -12
  48. package/dist/conversation-live.d.ts.map +1 -1
  49. package/dist/conversation-live.js +23 -12
  50. package/dist/conversation-row.d.ts +8 -1
  51. package/dist/conversation-row.d.ts.map +1 -1
  52. package/dist/conversation-row.js +20 -7
  53. package/dist/conversation.d.ts +37 -12
  54. package/dist/conversation.d.ts.map +1 -1
  55. package/dist/conversation.js +320 -234
  56. package/dist/declaration.d.ts +10 -0
  57. package/dist/declaration.d.ts.map +1 -0
  58. package/dist/declaration.js +24 -0
  59. package/dist/discovery.d.ts.map +1 -1
  60. package/dist/discovery.js +19 -44
  61. package/dist/durability.d.ts +4 -0
  62. package/dist/durability.d.ts.map +1 -1
  63. package/dist/durability.js +4 -0
  64. package/dist/entry.js +1 -1
  65. package/dist/expectation.d.ts +26 -13
  66. package/dist/expectation.d.ts.map +1 -1
  67. package/dist/expectation.js +72 -19
  68. package/dist/failure.d.ts +3 -0
  69. package/dist/failure.d.ts.map +1 -1
  70. package/dist/failure.js +6 -0
  71. package/dist/figures.d.ts.map +1 -1
  72. package/dist/figures.js +4 -2
  73. package/dist/file.d.ts +1 -1
  74. package/dist/file.d.ts.map +1 -1
  75. package/dist/file.js +3 -2
  76. package/dist/host.d.ts +18 -2
  77. package/dist/host.d.ts.map +1 -1
  78. package/dist/host.js +59 -15
  79. package/dist/index.d.ts +16 -11
  80. package/dist/index.d.ts.map +1 -1
  81. package/dist/index.js +12 -7
  82. package/dist/install.d.ts +10 -6
  83. package/dist/install.d.ts.map +1 -1
  84. package/dist/install.js +92 -111
  85. package/dist/lifecycle.d.ts +1 -1
  86. package/dist/lifecycle.d.ts.map +1 -1
  87. package/dist/lifecycle.js +54 -40
  88. package/dist/listing.d.ts +11 -12
  89. package/dist/listing.d.ts.map +1 -1
  90. package/dist/listing.js +48 -72
  91. package/dist/live.d.ts +5 -3
  92. package/dist/live.d.ts.map +1 -1
  93. package/dist/live.js +74 -33
  94. package/dist/loaded.d.ts +5 -0
  95. package/dist/loaded.d.ts.map +1 -0
  96. package/dist/loaded.js +40 -0
  97. package/dist/locks.d.ts +2 -4
  98. package/dist/locks.d.ts.map +1 -1
  99. package/dist/locks.js +10 -39
  100. package/dist/lost.d.ts.map +1 -1
  101. package/dist/lost.js +11 -23
  102. package/dist/media.d.ts +6 -1
  103. package/dist/media.d.ts.map +1 -1
  104. package/dist/media.js +68 -17
  105. package/dist/memory.d.ts +8 -3
  106. package/dist/memory.d.ts.map +1 -1
  107. package/dist/memory.js +92 -33
  108. package/dist/messages.d.ts +12 -6
  109. package/dist/messages.d.ts.map +1 -1
  110. package/dist/messages.js +30 -38
  111. package/dist/model.d.ts +0 -1
  112. package/dist/model.d.ts.map +1 -1
  113. package/dist/model.js +0 -5
  114. package/dist/models.d.ts +4 -8
  115. package/dist/models.d.ts.map +1 -1
  116. package/dist/models.js +97 -139
  117. package/dist/observation.d.ts +27 -12
  118. package/dist/observation.d.ts.map +1 -1
  119. package/dist/observation.js +184 -85
  120. package/dist/opened.d.ts +1 -1
  121. package/dist/opened.d.ts.map +1 -1
  122. package/dist/opened.js +5 -5
  123. package/dist/opening.d.ts.map +1 -1
  124. package/dist/opening.js +5 -9
  125. package/dist/outcome.d.ts +13 -1
  126. package/dist/outcome.d.ts.map +1 -1
  127. package/dist/outcome.js +32 -2
  128. package/dist/overlay.d.ts +6 -2
  129. package/dist/overlay.d.ts.map +1 -1
  130. package/dist/overlay.js +37 -24
  131. package/dist/page-metadata.d.ts +8 -0
  132. package/dist/page-metadata.d.ts.map +1 -0
  133. package/dist/page-metadata.js +19 -0
  134. package/dist/parts.d.ts +3 -58
  135. package/dist/parts.d.ts.map +1 -1
  136. package/dist/parts.js +10 -115
  137. package/dist/preparation.d.ts +27 -6
  138. package/dist/preparation.d.ts.map +1 -1
  139. package/dist/preparation.js +156 -68
  140. package/dist/presence.d.ts +58 -0
  141. package/dist/presence.d.ts.map +1 -0
  142. package/dist/presence.js +231 -0
  143. package/dist/queries.d.ts +2 -2
  144. package/dist/queries.d.ts.map +1 -1
  145. package/dist/queries.js +67 -31
  146. package/dist/query.d.ts +0 -1
  147. package/dist/query.d.ts.map +1 -1
  148. package/dist/questions.d.ts +1 -5
  149. package/dist/questions.d.ts.map +1 -1
  150. package/dist/questions.js +1 -7
  151. package/dist/queue.d.ts +40 -0
  152. package/dist/queue.d.ts.map +1 -0
  153. package/dist/queue.js +480 -0
  154. package/dist/reach.d.ts +2 -3
  155. package/dist/reach.d.ts.map +1 -1
  156. package/dist/reach.js +88 -26
  157. package/dist/react.d.ts +8 -1
  158. package/dist/react.d.ts.map +1 -1
  159. package/dist/react.js +33 -1
  160. package/dist/readiness.d.ts +9 -3
  161. package/dist/readiness.d.ts.map +1 -1
  162. package/dist/readiness.js +3 -5
  163. package/dist/reads.d.ts +4 -2
  164. package/dist/reads.d.ts.map +1 -1
  165. package/dist/reads.js +11 -4
  166. package/dist/recovery.d.ts +3 -1
  167. package/dist/recovery.d.ts.map +1 -1
  168. package/dist/recovery.js +29 -7
  169. package/dist/refresh.js +2 -2
  170. package/dist/refusal.d.ts.map +1 -1
  171. package/dist/refusal.js +5 -6
  172. package/dist/replica.d.ts +5 -11
  173. package/dist/replica.d.ts.map +1 -1
  174. package/dist/replica.js +15 -17
  175. package/dist/retried.d.ts +30 -0
  176. package/dist/retried.d.ts.map +1 -0
  177. package/dist/retried.js +72 -0
  178. package/dist/room-draft.d.ts +31 -8
  179. package/dist/room-draft.d.ts.map +1 -1
  180. package/dist/room-draft.js +273 -66
  181. package/dist/room-drafts.d.ts.map +1 -1
  182. package/dist/room-drafts.js +22 -18
  183. package/dist/room-list.d.ts +10 -0
  184. package/dist/room-list.d.ts.map +1 -0
  185. package/dist/room-list.js +45 -0
  186. package/dist/rows.d.ts +2 -1
  187. package/dist/rows.d.ts.map +1 -1
  188. package/dist/rows.js +9 -10
  189. package/dist/runtime.d.ts +9 -18
  190. package/dist/runtime.d.ts.map +1 -1
  191. package/dist/save.d.ts +42 -90
  192. package/dist/save.d.ts.map +1 -1
  193. package/dist/save.js +327 -229
  194. package/dist/saves.d.ts +4 -40
  195. package/dist/saves.d.ts.map +1 -1
  196. package/dist/saves.js +143 -714
  197. package/dist/seed.d.ts.map +1 -1
  198. package/dist/seed.js +4 -5
  199. package/dist/shared.d.ts +0 -5
  200. package/dist/shared.d.ts.map +1 -1
  201. package/dist/shared.js +4 -90
  202. package/dist/shown.d.ts +7 -5
  203. package/dist/shown.d.ts.map +1 -1
  204. package/dist/shown.js +77 -63
  205. package/dist/socket/lanes.d.ts +12 -4
  206. package/dist/socket/lanes.d.ts.map +1 -1
  207. package/dist/socket/lanes.js +34 -8
  208. package/dist/socket/session.d.ts +0 -1
  209. package/dist/socket/session.d.ts.map +1 -1
  210. package/dist/socket.d.ts +3 -6
  211. package/dist/socket.d.ts.map +1 -1
  212. package/dist/socket.js +5 -16
  213. package/dist/source.d.ts +5 -7
  214. package/dist/source.d.ts.map +1 -1
  215. package/dist/source.js +18 -6
  216. package/dist/store/installs.d.ts +2 -2
  217. package/dist/store/installs.d.ts.map +1 -1
  218. package/dist/store/installs.js +10 -4
  219. package/dist/store/readiness.d.ts +5 -4
  220. package/dist/store/readiness.d.ts.map +1 -1
  221. package/dist/store/readiness.js +28 -12
  222. package/dist/store/records.d.ts +18 -7
  223. package/dist/store/records.d.ts.map +1 -1
  224. package/dist/store/records.js +58 -24
  225. package/dist/store/rooms-shown.d.ts +8 -0
  226. package/dist/store/rooms-shown.d.ts.map +1 -0
  227. package/dist/store/rooms-shown.js +13 -0
  228. package/dist/store/space.d.ts +1 -1
  229. package/dist/store/space.d.ts.map +1 -1
  230. package/dist/store/space.js +0 -2
  231. package/dist/store/watchers.js +1 -2
  232. package/dist/store.d.ts +23 -14
  233. package/dist/store.d.ts.map +1 -1
  234. package/dist/store.js +46 -17
  235. package/dist/stored.d.ts +25 -14
  236. package/dist/stored.d.ts.map +1 -1
  237. package/dist/stored.js +83 -32
  238. package/dist/surface.d.ts +5 -3
  239. package/dist/surface.d.ts.map +1 -1
  240. package/dist/surface.js +25 -23
  241. package/dist/sync.d.ts +1 -1
  242. package/dist/sync.d.ts.map +1 -1
  243. package/dist/sync.js +96 -92
  244. package/dist/tables.d.ts +16 -57
  245. package/dist/tables.d.ts.map +1 -1
  246. package/dist/tables.js +91 -332
  247. package/dist/tallies.d.ts.map +1 -1
  248. package/dist/tallies.js +6 -7
  249. package/dist/validation.d.ts.map +1 -1
  250. package/dist/validation.js +4 -10
  251. package/dist/wire.d.ts +53 -7
  252. package/dist/wire.d.ts.map +1 -1
  253. package/dist/wire.js +17 -4
  254. package/package.json +3 -2
  255. package/dist/attempt.d.ts +0 -16
  256. package/dist/attempt.d.ts.map +0 -1
  257. package/dist/attempt.js +0 -70
  258. package/dist/job.d.ts +0 -33
  259. package/dist/job.d.ts.map +0 -1
  260. package/dist/job.js +0 -54
  261. package/dist/log.d.ts +0 -6
  262. package/dist/log.d.ts.map +0 -1
  263. package/dist/log.js +0 -14
  264. package/dist/socket/rooms.d.ts +0 -44
  265. package/dist/socket/rooms.d.ts.map +0 -1
  266. package/dist/socket/rooms.js +0 -90
  267. package/dist/store/fences.d.ts +0 -16
  268. package/dist/store/fences.d.ts.map +0 -1
  269. package/dist/store/fences.js +0 -26
package/dist/queue.js ADDED
@@ -0,0 +1,480 @@
1
+ import { changeSet, mergeChangeSets } from './change-set.js';
2
+ import { leaving as leavingIn, partnerOf } from './change.js';
3
+ import { composedOf, definitionsAt } from './collection.js';
4
+ import { declared } from './declaration.js';
5
+ import { runtimeError } from './failure.js';
6
+ import { roomDraftRevision } from './identity.js';
7
+ import { landed, movedBy, overlayOf, replaying, slicing, slicingWith, standing, storedRecord, touchedBy, } from './replica.js';
8
+ import { joinedOver, marksOver, returnedBy, returnedInto, } from './room-draft.js';
9
+ import { documentKey } from './rows.js';
10
+ import { stepped } from './turn.js';
11
+ export function withdrawable(states) {
12
+ return (batch) => {
13
+ const state = states.get(batch.id);
14
+ return state !== undefined && state.submission.state !== 'submitted' && !state.lost;
15
+ };
16
+ }
17
+ export async function sliceAt(store, record, view, queue, extra = [], moved = []) {
18
+ const local = await store.open();
19
+ const needed = new Set([...touchedBy(queue), ...extra]);
20
+ const movedPaths = [...new Set([...movedBy(queue, record.locator), ...moved])];
21
+ if (movedPaths.length > 0) {
22
+ for (const { path } of await local.referrers(record.key, view, movedPaths)) {
23
+ needed.add(path);
24
+ }
25
+ }
26
+ const paths = [...needed];
27
+ return stepped(slicing(await local.entries(record.key, view, paths), paths));
28
+ }
29
+ async function landedWhole(store, record, batch, confirmedLayer, current) {
30
+ if (!landed(batch, confirmedLayer, store.composed(record), current))
31
+ return false;
32
+ const partner = partnerOf(batch, record.locator);
33
+ if (partner === null)
34
+ return true;
35
+ const other = await store.replica(partner);
36
+ const half = other?.queue.find((one) => one.id === batch.id);
37
+ if (other === undefined || half === undefined)
38
+ return false;
39
+ return landed(half, await sliceAt(store, other.record, 'confirmed', [half]), store.composed(other.record));
40
+ }
41
+ async function returnedDrafts(store, locator, work, leaving, composition, visible) {
42
+ const written = new Map();
43
+ for (const { batch, returned } of leaving) {
44
+ if (returned === null || batch.between?.destination.room === locator)
45
+ continue;
46
+ for (const saved of work.states.get(batch.id)?.drafts ?? []) {
47
+ const existing = written.get(saved.path) ?? (await store.draft(locator, saved.path));
48
+ const parts = returnedInto(existing?.parts, saved.parts, composition === undefined ? undefined : definitionsAt(composition, saved.path));
49
+ const record = parts === null
50
+ ? { ...existing, returned }
51
+ : {
52
+ locator,
53
+ path: saved.path,
54
+ revision: roomDraftRevision(),
55
+ parts,
56
+ marks: existing?.marks ?? {},
57
+ returned,
58
+ };
59
+ const join = visible === undefined ? null : joinedOver(record.parts, record.marks, saved.path, visible);
60
+ written.set(saved.path, join === null ? record : { ...record, ...join, revision: roomDraftRevision() });
61
+ }
62
+ }
63
+ return written;
64
+ }
65
+ function unheldComposition({ store, presence }, locator) {
66
+ const model = presence.unheldModel(locator);
67
+ const listed = presence.room(locator);
68
+ if (model === null || listed === undefined)
69
+ return undefined;
70
+ return store.composed({ model, declaration: declared(listed) });
71
+ }
72
+ async function carriedBack(runtime, locator, unlanded, written) {
73
+ const { store } = runtime;
74
+ const back = new Map();
75
+ const taken = [];
76
+ for (const batch of unlanded) {
77
+ const between = batch.between;
78
+ if (between === undefined)
79
+ continue;
80
+ const source = between.source.room;
81
+ const destination = between.destination.room;
82
+ const local = await store.open();
83
+ const arrived = (await local.pending(destination, batch.id)).state?.drafts ?? [];
84
+ for (const { path: to } of arrived) {
85
+ const record = await store.draft(destination, to);
86
+ const path = between.moves.find((move) => move.to === to)?.path;
87
+ if (record === undefined || path === undefined)
88
+ continue;
89
+ const [into, key] = source === locator ? [written, path] : [back, documentKey(source, path)];
90
+ const existing = into.get(key) ?? (await store.draft(source, path));
91
+ const held = await store.record(source);
92
+ const composition = held === undefined ? unheldComposition(runtime, source) : store.composed(held);
93
+ const parts = returnedInto(existing?.parts, record.parts, composition === undefined ? undefined : definitionsAt(composition, path));
94
+ if (parts === null)
95
+ continue;
96
+ taken.push({ locator: destination, path: to });
97
+ into.set(key, {
98
+ locator: source,
99
+ path,
100
+ revision: roomDraftRevision(),
101
+ parts,
102
+ marks: marksOver(existing?.marks ?? {}, record.marks),
103
+ returned: existing?.returned ?? null,
104
+ });
105
+ }
106
+ }
107
+ const records = [...back.values()];
108
+ const elsewhere = taken.filter((one) => one.locator !== locator);
109
+ const rooms = new Set([...records, ...elsewhere].map((one) => one.locator));
110
+ return {
111
+ taken: taken.filter((one) => one.locator === locator).map(({ path }) => path),
112
+ writes: [...rooms].map((room) => ({
113
+ locator: room,
114
+ roomDrafts: records.filter((record) => record.locator === room),
115
+ consumedRoomDrafts: elsewhere.filter((one) => one.locator === room).map(({ path }) => path),
116
+ })),
117
+ changes: [...rooms].map((room) => changeSet(room, {
118
+ drafts: [...records, ...elsewhere]
119
+ .filter((one) => one.locator === room)
120
+ .map(({ path }) => path),
121
+ })),
122
+ };
123
+ }
124
+ function confirmedAgain(store, locator) {
125
+ store.installs.change(locator, (held) => ({
126
+ ...held,
127
+ confirmations: held.confirmations + 1,
128
+ }));
129
+ }
130
+ function replayed(store, record, confirmedLayer, queue) {
131
+ return stepped(replaying(confirmedLayer, queue, record.locator, store.composed(record)));
132
+ }
133
+ async function overlayDiff(record, before, visible, touched) {
134
+ const kept = before !== undefined && before.record.key === record.key ? before.overlaid : new Set();
135
+ return {
136
+ overlay: {
137
+ set: await stepped(overlayOf(visible, touched)),
138
+ cleared: [...kept].filter((path) => !touched.has(path)),
139
+ },
140
+ touched,
141
+ };
142
+ }
143
+ function unsent(state, batch, locator) {
144
+ if (state === undefined)
145
+ return false;
146
+ return !leavingIn(batch, locator) || withdrawable(new Map([[batch.id, state]]))(batch);
147
+ }
148
+ async function together(runtime, local, settlements) {
149
+ const settled = new Set(settlements.map(({ locator }) => locator));
150
+ const all = [...settlements];
151
+ for (let wave = settlements; wave.length > 0;) {
152
+ const partnered = new Map();
153
+ for (const { locator, left } of wave) {
154
+ for (const batch of left) {
155
+ const partner = partnerOf(batch, locator);
156
+ if (partner === null ||
157
+ settled.has(partner) ||
158
+ !unsent((await local.pending(partner, batch.id)).state, batch, partner)) {
159
+ continue;
160
+ }
161
+ partnered.set(partner, [...(partnered.get(partner) ?? []), batch]);
162
+ }
163
+ }
164
+ const partners = [];
165
+ for (const [partner, batches] of partnered) {
166
+ settled.add(partner);
167
+ partners.push(await unpairing(runtime, local, partner, batches));
168
+ }
169
+ all.push(...partners);
170
+ wave = partners;
171
+ }
172
+ const answer = await local.commit({
173
+ rooms: all.flatMap(({ commit }) => commit.rooms),
174
+ writes: all.flatMap(({ commit }) => commit.writes),
175
+ });
176
+ return mergeChangeSets(all.map((one) => one.apply(answer)));
177
+ }
178
+ async function settlement(runtime, local, locator, work, record, queue, settling = {}) {
179
+ const { store, localSaves } = runtime;
180
+ const before = work.replica;
181
+ const view = settling.view ?? 'confirmed';
182
+ const previousQueue = work.queue;
183
+ const overrides = settling.changes;
184
+ const read = await sliceAt(store, record, view, queue, [
185
+ ...(before !== undefined && before.record.key === record.key ? before.overlaid : []),
186
+ ...(overrides?.set.map(({ path }) => path) ?? []),
187
+ ...(overrides?.removed ?? []),
188
+ ...[...work.states.values()].flatMap(({ drafts }) => drafts.map(({ path }) => path)),
189
+ ]);
190
+ const confirmedLayer = overrides === undefined
191
+ ? read
192
+ : await stepped(slicingWith(read, overrides.set, overrides.removed));
193
+ const composition = store.composed(record);
194
+ const shown = queue.filter((batch) => {
195
+ const held = store.conflicted.of(locator, batch.id);
196
+ return (held !== undefined &&
197
+ Object.entries(held.revisions).some(([path, revision]) => confirmedLayer.revisions[path] !== revision));
198
+ });
199
+ const unshown = queue.filter((batch) => !shown.includes(batch));
200
+ const { withdrawn, kept } = await stepped(standing(confirmedLayer, unshown, withdrawable(work.states), localSaves, locator, composition));
201
+ const founded = kept.filter((batch) => !unshown.includes(batch));
202
+ const queueChanged = kept.length !== previousQueue.length || founded.length > 0;
203
+ const unqueued = shown.map((batch) => {
204
+ const { returned } = store.conflicted.of(locator, batch.id);
205
+ return {
206
+ batch,
207
+ returned: returned === null || landed(batch, confirmedLayer, composition) ? null : returned,
208
+ };
209
+ });
210
+ for (const batch of withdrawn) {
211
+ const held = await landedWhole(store, record, batch, confirmedLayer);
212
+ unqueued.push({ batch, returned: held ? null : returnedBy() });
213
+ }
214
+ const returning = [
215
+ ...[...unqueued].reverse().map(({ batch, returned }) => ({
216
+ batch,
217
+ returned: localSaves ? null : returned,
218
+ })),
219
+ ...(settling.leaving ?? []),
220
+ ];
221
+ const replayedLayer = await replayed(store, record, confirmedLayer, kept);
222
+ const written = await returnedDrafts(store, locator, work, returning, composition, replayedLayer.visible);
223
+ const carried = await carriedBack(runtime, locator, [
224
+ ...[...unqueued]
225
+ .reverse()
226
+ .flatMap(({ batch, returned }) => (returned === null ? [] : [batch])),
227
+ ...(settling.leaving ?? []).flatMap(({ batch, returned }) => returned === null ? [] : [batch]),
228
+ ], written);
229
+ const { overlay } = await overlayDiff(record, before, replayedLayer.visible, replayedLayer.touched);
230
+ const commit = {
231
+ rooms: [
232
+ {
233
+ locator,
234
+ key: record.key,
235
+ record: storedRecord(record),
236
+ roots: record.declaration.typedSelection?.roots ?? [],
237
+ composed: composedOf(composition),
238
+ ...settling.commit,
239
+ ...(overrides === undefined
240
+ ? {}
241
+ : { confirmed: { set: overrides.set, removed: overrides.removed } }),
242
+ overlay,
243
+ },
244
+ ],
245
+ writes: [
246
+ {
247
+ locator,
248
+ queue: kept,
249
+ stored: previousQueue,
250
+ founded,
251
+ roomDrafts: [...written.values()],
252
+ consumedRoomDrafts: carried.taken,
253
+ },
254
+ ...carried.writes,
255
+ ],
256
+ };
257
+ const staying = new Set(kept.map((batch) => batch.id));
258
+ return {
259
+ locator,
260
+ left: previousQueue.filter((batch) => !staying.has(batch.id)),
261
+ commit,
262
+ apply: (answer) => {
263
+ for (const batch of previousQueue) {
264
+ if (!staying.has(batch.id))
265
+ store.conflicted.drop(locator, batch.id);
266
+ }
267
+ const drafts = [...written.keys(), ...carried.taken];
268
+ const changed = answer.changed[locator];
269
+ if (settling.commit?.published !== undefined ||
270
+ settling.commit?.refreshed === true ||
271
+ overrides !== undefined) {
272
+ confirmedAgain(store, locator);
273
+ }
274
+ return mergeChangeSets([
275
+ changeSet(locator, {
276
+ documents: changed === undefined ? [] : changed,
277
+ room: settling.room,
278
+ queue: queueChanged,
279
+ drafts,
280
+ unindexed: answer.indexed[locator] === false,
281
+ due: kept.length > 0 && settling.refused !== true,
282
+ }),
283
+ ...carried.changes,
284
+ ]);
285
+ },
286
+ };
287
+ }
288
+ async function unpairing(runtime, local, locator, batches) {
289
+ const { store, localSaves } = runtime;
290
+ const ids = new Set(batches.map(({ id }) => id));
291
+ const leaving = batches.map((batch) => ({
292
+ batch,
293
+ returned: !localSaves && leavingIn(batch, locator) ? returnedBy() : null,
294
+ }));
295
+ const work = await store.work(locator);
296
+ const current = work.replica;
297
+ if (current !== undefined) {
298
+ return settlement(runtime, local, locator, work, current.record, current.queue.filter((one) => !ids.has(one.id)), { leaving });
299
+ }
300
+ const queue = work.queue.filter((one) => !ids.has(one.id));
301
+ const written = await returnedDrafts(store, locator, work, leaving, unheldComposition(runtime, locator), undefined);
302
+ const carried = await carriedBack(runtime, locator, leaving.flatMap(({ batch, returned }) => (returned === null ? [] : [batch])), written);
303
+ return {
304
+ locator,
305
+ left: batches,
306
+ commit: {
307
+ rooms: [],
308
+ writes: [
309
+ {
310
+ locator,
311
+ queue,
312
+ stored: work.queue,
313
+ roomDrafts: [...written.values()],
314
+ consumedRoomDrafts: carried.taken,
315
+ },
316
+ ...carried.writes,
317
+ ],
318
+ },
319
+ apply() {
320
+ return mergeChangeSets([
321
+ changeSet(locator, {
322
+ queue: true,
323
+ drafts: [...written.keys(), ...carried.taken],
324
+ due: queue.length > 0,
325
+ }),
326
+ ...carried.changes,
327
+ ]);
328
+ },
329
+ };
330
+ }
331
+ async function orphaned(local) {
332
+ const { queued, moving } = await local.moving();
333
+ const halves = new Map();
334
+ for (const { locator, batch, state } of moving) {
335
+ const partner = partnerOf(batch, locator);
336
+ if (partner === null || queued.get(partner)?.includes(batch.id) === true)
337
+ continue;
338
+ if (unsent(state, batch, locator))
339
+ halves.set(locator, [...(halves.get(locator) ?? []), batch]);
340
+ }
341
+ return halves;
342
+ }
343
+ async function sweep(runtime, local) {
344
+ if (!runtime.socket.continuing())
345
+ return;
346
+ const halves = await orphaned(local);
347
+ if (halves.size === 0)
348
+ return;
349
+ const settlements = [];
350
+ for (const [locator, batches] of halves) {
351
+ settlements.push(await unpairing(runtime, local, locator, batches));
352
+ }
353
+ void runtime.store.changed(await together(runtime, local, settlements));
354
+ }
355
+ async function settled(runtime, local, settlements, steps) {
356
+ const set = await together(runtime, local, settlements);
357
+ for (const step of steps)
358
+ step();
359
+ void runtime.store.changed(set);
360
+ await sweep(runtime, local);
361
+ }
362
+ export function settle(runtime, locators, decide) {
363
+ const { store } = runtime;
364
+ return store.exclusive(async () => {
365
+ const local = await store.open();
366
+ const held = new Map();
367
+ for (const locator of locators)
368
+ held.set(locator, await store.work(locator));
369
+ const decided = await decide(held);
370
+ if (decided.length === 0)
371
+ return;
372
+ const settlements = [];
373
+ for (const { locator, record, accepted, adopted, installed, refused } of decided) {
374
+ const work = held.get(locator) ?? (await store.work(locator));
375
+ settlements.push(await settlement(runtime, local, locator, work, record, work.queue.filter((batch) => batch.id !== accepted), {
376
+ room: true,
377
+ view: installed?.refreshed === true ? 'refreshed' : 'confirmed',
378
+ ...(installed === undefined ? {} : { commit: installed }),
379
+ ...(adopted === undefined ? {} : { changes: adopted }),
380
+ ...(refused === undefined ? {} : { refused }),
381
+ }));
382
+ }
383
+ await settled(runtime, local, settlements, decided.flatMap(({ after }) => (after === undefined ? [] : [after])));
384
+ });
385
+ }
386
+ function awaited(head, confirmedLayer, composition, { affected }, held) {
387
+ const touched = [...touchedBy([head])];
388
+ if (held)
389
+ return landed(head, confirmedLayer, composition) ? [] : touched;
390
+ return touched.filter((path) => Object.hasOwn(affected, path) && confirmedLayer.documents[path] !== affected[path]);
391
+ }
392
+ export function answered(runtime, locator, head, answer) {
393
+ const { store, socket } = runtime;
394
+ return store.exclusive(async () => {
395
+ if (!socket.continuing())
396
+ return;
397
+ const local = await store.open();
398
+ const work = await store.work(locator);
399
+ const current = work.replica;
400
+ if (current === undefined || !current.queue.some((batch) => batch.id === head.id))
401
+ return;
402
+ const confirmedLayer = await sliceAt(store, current.record, 'confirmed', [head]);
403
+ const held = answer.kind === 'conflicted' &&
404
+ (await landedWhole(store, current.record, head, confirmedLayer, answer.affected));
405
+ const returned = {
406
+ kind: answer.kind,
407
+ code: answer.code,
408
+ fields: answer.fields,
409
+ retryable: answer.retryable,
410
+ };
411
+ if (answer.kind === 'conflicted' && partnerOf(head, locator) === null) {
412
+ const behind = awaited(head, confirmedLayer, store.composed(current.record), answer, held);
413
+ if (behind.length > 0) {
414
+ store.conflicted.hold(locator, head.id, {
415
+ revisions: Object.fromEntries(behind.map((path) => [path, confirmedLayer.revisions[path]])),
416
+ returned: held ? null : returned,
417
+ });
418
+ return;
419
+ }
420
+ }
421
+ await settled(runtime, local, [
422
+ await settlement(runtime, local, locator, work, current.record, current.queue.filter((batch) => batch.id !== head.id), { leaving: [{ batch: head, returned: held ? null : returned }] }),
423
+ ], []);
424
+ });
425
+ }
426
+ export function unpair(runtime) {
427
+ return runtime.store.durably((local) => sweep(runtime, local));
428
+ }
429
+ export async function append(runtime, appending) {
430
+ const { plan, files, held, after } = appending;
431
+ if (plan.kind === 'refused')
432
+ return { outcome: 'refused', ...plan.refusal };
433
+ const { store } = runtime;
434
+ const local = await store.open();
435
+ const rooms = [];
436
+ const writes = [];
437
+ for (const { locator, queue, saved, consumed, carried } of plan.rooms) {
438
+ const { replica, confirmed } = held.get(locator);
439
+ const { record } = replica;
440
+ const replayedLayer = await replayed(store, record, confirmed, queue);
441
+ const { overlay } = await overlayDiff(record, replica, replayedLayer.visible, replayedLayer.touched);
442
+ rooms.push({
443
+ locator,
444
+ key: record.key,
445
+ roots: record.declaration.typedSelection?.roots ?? [],
446
+ composed: composedOf(store.composed(record)),
447
+ overlay,
448
+ });
449
+ writes.push({
450
+ locator,
451
+ queue,
452
+ stored: replica.queue,
453
+ saved,
454
+ consumedRoomDrafts: consumed,
455
+ roomDrafts: carried,
456
+ });
457
+ }
458
+ let answer;
459
+ try {
460
+ answer = await local.commit({ rooms, writes, files, whole: true });
461
+ }
462
+ catch {
463
+ return { outcome: 'refused', code: 'durable-write', retryable: true };
464
+ }
465
+ const lost = answer.fenced ?? plan.rooms.find(({ locator }) => runtime.presence.lost(locator))?.locator;
466
+ if (lost !== undefined)
467
+ throw runtimeError('unknown-room', `Unknown Room ${lost}`);
468
+ const [saving] = plan.rooms;
469
+ await Promise.all([
470
+ store.changed(mergeChangeSets(plan.rooms.map(({ locator, consumed, carried }) => changeSet(locator, {
471
+ documents: answer.changed[locator] ?? [],
472
+ queue: true,
473
+ drafts: [...consumed, ...carried.map(({ path }) => path)],
474
+ unindexed: answer.indexed[locator] === false,
475
+ due: locator === saving?.locator,
476
+ })))),
477
+ after?.(),
478
+ ]);
479
+ return { outcome: 'saved', identifier: plan.identifier };
480
+ }
package/dist/reach.d.ts CHANGED
@@ -1,8 +1,7 @@
1
1
  import type { AppRoom } from './listing.js';
2
- import type { ReadinessPort } from './preparation.js';
2
+ import type { ReadinessMessage, ReadinessPort } from './preparation.js';
3
3
  import type { MdRuntime, RuntimeTopic } from './surface.js';
4
4
  import type { Plan, PlanReach, QueryResult } from './query.js';
5
- import type { Readiness } from './readiness.js';
6
5
  import type { SearchResult } from './search.js';
7
6
  export type ReachedDocument = {
8
7
  readonly room: string;
@@ -34,7 +33,7 @@ export type Reachable = RuntimeView & {
34
33
  query(plan: Plan): Promise<QueryResult>;
35
34
  watchPlan(plan: Plan, deliver: Deliver, fail: Fail): () => void;
36
35
  search(input: unknown, reach: PortReach | null): Promise<SearchResult>;
37
- watchReadiness(port: ReadinessPort, reach: PortReach | null, deliver: (readiness: Readiness) => void): () => void;
36
+ watchReadiness(port: ReadinessPort, reach: PortReach | null, deliver: (readiness: ReadinessMessage) => void): () => void;
38
37
  locked(room: string): Promise<boolean>;
39
38
  lockedRooms(): Promise<readonly string[]>;
40
39
  watchLocks(notify: () => void): () => void;
@@ -1 +1 @@
1
- {"version":3,"file":"reach.d.ts","sourceRoot":"","sources":["../src/reach.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"reach.d.ts","sourceRoot":"","sources":["../src/reach.ts"],"names":[],"mappings":"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"}