@agentshouse/mdruntime 0.1.0-c069136dcb4e8 → 0.1.0-c076b00ebf42a
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 +21 -19
- package/dist/acceptance.d.ts +3 -0
- package/dist/acceptance.d.ts.map +1 -0
- package/dist/acceptance.js +299 -0
- package/dist/act-lanes.d.ts +30 -0
- package/dist/act-lanes.d.ts.map +1 -0
- package/dist/act-lanes.js +225 -0
- package/dist/actions.d.ts +26 -0
- package/dist/actions.d.ts.map +1 -0
- package/dist/actions.js +302 -0
- package/dist/adapter.d.ts +108 -85
- package/dist/adapter.d.ts.map +1 -1
- package/dist/attached-model.d.ts +3 -11
- package/dist/attached-model.d.ts.map +1 -1
- package/dist/attached-model.js +20 -60
- package/dist/bootstrap.d.ts +9 -5
- package/dist/bootstrap.d.ts.map +1 -1
- package/dist/bootstrap.js +204 -85
- package/dist/cell.d.ts +6 -0
- package/dist/cell.d.ts.map +1 -0
- package/dist/cell.js +9 -0
- package/dist/chain.d.ts +2 -1
- package/dist/chain.d.ts.map +1 -1
- package/dist/change-set.d.ts +4 -0
- package/dist/change-set.d.ts.map +1 -1
- package/dist/change-set.js +6 -0
- package/dist/change.d.ts +1 -0
- package/dist/change.d.ts.map +1 -1
- package/dist/change.js +4 -2
- package/dist/chat-types.d.ts +3 -0
- package/dist/chat-types.d.ts.map +1 -0
- package/dist/chat-types.js +11 -0
- package/dist/client.d.ts +29 -22
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +36 -20
- package/dist/collection.d.ts +26 -4
- package/dist/collection.d.ts.map +1 -1
- package/dist/collection.js +19 -2
- package/dist/compile.d.ts +8 -6
- package/dist/compile.d.ts.map +1 -1
- package/dist/compile.js +286 -336
- package/dist/connection.d.ts +5 -142
- package/dist/connection.d.ts.map +1 -1
- package/dist/connection.js +110 -4970
- package/dist/context.d.ts +2 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +7 -0
- package/dist/conversation-live.d.ts +150 -0
- package/dist/conversation-live.d.ts.map +1 -0
- package/dist/conversation-live.js +259 -0
- package/dist/conversation-row.d.ts +35 -0
- package/dist/conversation-row.d.ts.map +1 -0
- package/dist/conversation-row.js +55 -0
- package/dist/conversation.d.ts +65 -44
- package/dist/conversation.d.ts.map +1 -1
- package/dist/conversation.js +999 -881
- package/dist/declaration.d.ts +10 -0
- package/dist/declaration.d.ts.map +1 -0
- package/dist/declaration.js +24 -0
- package/dist/discovery.d.ts +10 -0
- package/dist/discovery.d.ts.map +1 -0
- package/dist/discovery.js +150 -0
- package/dist/durability.d.ts +19 -0
- package/dist/durability.d.ts.map +1 -1
- package/dist/durability.js +4 -0
- package/dist/entry.d.ts +2 -2
- package/dist/entry.d.ts.map +1 -1
- package/dist/entry.js +18 -8
- package/dist/expectation.d.ts +26 -13
- package/dist/expectation.d.ts.map +1 -1
- package/dist/expectation.js +72 -19
- package/dist/failure.d.ts +3 -0
- package/dist/failure.d.ts.map +1 -1
- package/dist/failure.js +6 -0
- package/dist/figures.d.ts +49 -0
- package/dist/figures.d.ts.map +1 -0
- package/dist/figures.js +199 -0
- package/dist/file.d.ts.map +1 -1
- package/dist/file.js +2 -1
- 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 +21 -7
- package/dist/host.d.ts.map +1 -1
- package/dist/host.js +77 -41
- package/dist/identity.d.ts +0 -1
- package/dist/identity.d.ts.map +1 -1
- package/dist/identity.js +0 -3
- package/dist/index.d.ts +34 -12
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +16 -5
- package/dist/install.d.ts +60 -0
- package/dist/install.d.ts.map +1 -0
- package/dist/install.js +537 -0
- package/dist/lifecycle.d.ts +7 -0
- package/dist/lifecycle.d.ts.map +1 -0
- package/dist/lifecycle.js +278 -0
- package/dist/listing.d.ts +52 -0
- package/dist/listing.d.ts.map +1 -0
- package/dist/listing.js +152 -0
- package/dist/live.d.ts +9 -6
- package/dist/live.d.ts.map +1 -1
- package/dist/live.js +118 -36
- package/dist/locks.d.ts +7 -0
- package/dist/locks.d.ts.map +1 -0
- package/dist/locks.js +32 -0
- package/dist/lost.d.ts +5 -0
- package/dist/lost.d.ts.map +1 -0
- package/dist/lost.js +49 -0
- package/dist/media.d.ts +1 -1
- package/dist/media.d.ts.map +1 -1
- package/dist/media.js +10 -13
- package/dist/memory.d.ts +15 -6
- package/dist/memory.d.ts.map +1 -1
- package/dist/memory.js +178 -89
- package/dist/messages.d.ts +35 -5
- package/dist/messages.d.ts.map +1 -1
- package/dist/messages.js +108 -36
- package/dist/model.d.ts +2 -10
- package/dist/model.d.ts.map +1 -1
- package/dist/model.js +0 -14
- package/dist/models.d.ts +10 -0
- package/dist/models.d.ts.map +1 -0
- package/dist/models.js +153 -0
- package/dist/observation.d.ts +28 -13
- package/dist/observation.d.ts.map +1 -1
- package/dist/observation.js +185 -81
- package/dist/opened.d.ts +1 -1
- package/dist/opened.d.ts.map +1 -1
- package/dist/opened.js +5 -5
- package/dist/opening.d.ts +4 -0
- package/dist/opening.d.ts.map +1 -0
- package/dist/opening.js +53 -0
- package/dist/outcome.d.ts +11 -1
- package/dist/outcome.d.ts.map +1 -1
- package/dist/outcome.js +26 -2
- package/dist/overlay.d.ts +6 -1
- package/dist/overlay.d.ts.map +1 -1
- package/dist/overlay.js +47 -21
- package/dist/page-metadata.d.ts +8 -0
- package/dist/page-metadata.d.ts.map +1 -0
- package/dist/page-metadata.js +19 -0
- package/dist/parts.d.ts +4 -0
- package/dist/parts.d.ts.map +1 -0
- package/dist/parts.js +13 -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 +41 -0
- package/dist/preparation.d.ts.map +1 -0
- package/dist/preparation.js +314 -0
- package/dist/presence.d.ts +58 -0
- package/dist/presence.d.ts.map +1 -0
- package/dist/presence.js +233 -0
- package/dist/queries.d.ts +16 -0
- package/dist/queries.d.ts.map +1 -0
- package/dist/queries.js +308 -0
- package/dist/query.d.ts +14 -210
- package/dist/query.d.ts.map +1 -1
- package/dist/query.js +3 -505
- package/dist/questions.d.ts +29 -0
- package/dist/questions.d.ts.map +1 -0
- package/dist/questions.js +115 -0
- package/dist/queue.d.ts +40 -0
- package/dist/queue.d.ts.map +1 -0
- package/dist/queue.js +450 -0
- package/dist/reach.d.ts +16 -15
- package/dist/reach.d.ts.map +1 -1
- package/dist/reach.js +248 -147
- package/dist/react.d.ts +17 -3
- package/dist/react.d.ts.map +1 -1
- package/dist/react.js +33 -1
- package/dist/read.d.ts +7 -0
- package/dist/read.d.ts.map +1 -0
- package/dist/read.js +17 -0
- package/dist/readiness.d.ts +9 -6
- package/dist/readiness.d.ts.map +1 -1
- package/dist/readiness.js +3 -5
- package/dist/reads.d.ts +39 -0
- package/dist/reads.d.ts.map +1 -0
- package/dist/reads.js +178 -0
- package/dist/recovery.d.ts +3 -1
- package/dist/recovery.d.ts.map +1 -1
- package/dist/recovery.js +38 -8
- package/dist/refresh.d.ts +2 -1
- package/dist/refresh.d.ts.map +1 -1
- package/dist/refresh.js +31 -3
- package/dist/refusal.d.ts +5 -0
- package/dist/refusal.d.ts.map +1 -0
- package/dist/refusal.js +55 -0
- package/dist/replica.d.ts +11 -16
- package/dist/replica.d.ts.map +1 -1
- package/dist/replica.js +64 -30
- package/dist/retried.d.ts +30 -0
- package/dist/retried.d.ts.map +1 -0
- package/dist/retried.js +72 -0
- package/dist/room-draft.d.ts +7 -8
- package/dist/room-draft.d.ts.map +1 -1
- package/dist/room-draft.js +113 -111
- 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/rows.d.ts +16 -22
- package/dist/rows.d.ts.map +1 -1
- package/dist/rows.js +49 -186
- package/dist/runtime.d.ts +34 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +1 -0
- package/dist/save.d.ts +42 -86
- package/dist/save.d.ts.map +1 -1
- package/dist/save.js +344 -174
- package/dist/saves.d.ts +32 -0
- package/dist/saves.d.ts.map +1 -0
- package/dist/saves.js +409 -0
- package/dist/search.d.ts +12 -63
- package/dist/search.d.ts.map +1 -1
- package/dist/search.js +9 -52
- package/dist/seed.d.ts +11 -2
- package/dist/seed.d.ts.map +1 -1
- package/dist/seed.js +71 -1
- 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 +33 -0
- package/dist/shown.d.ts.map +1 -0
- package/dist/shown.js +309 -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 +28 -0
- package/dist/socket/lanes.d.ts.map +1 -0
- package/dist/socket/lanes.js +103 -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/session.d.ts +38 -0
- package/dist/socket/session.d.ts.map +1 -0
- package/dist/socket/session.js +23 -0
- package/dist/socket.d.ts +67 -0
- package/dist/socket.d.ts.map +1 -0
- package/dist/socket.js +164 -0
- package/dist/source.d.ts +54 -0
- package/dist/source.d.ts.map +1 -0
- package/dist/source.js +82 -0
- package/dist/status.d.ts +0 -2
- package/dist/status.d.ts.map +1 -1
- package/dist/status.js +0 -6
- package/dist/store/installs.d.ts +30 -0
- package/dist/store/installs.d.ts.map +1 -0
- package/dist/store/installs.js +40 -0
- package/dist/store/readiness.d.ts +11 -0
- package/dist/store/readiness.d.ts.map +1 -0
- package/dist/store/readiness.js +68 -0
- package/dist/store/records.d.ts +217 -0
- package/dist/store/records.d.ts.map +1 -0
- package/dist/store/records.js +464 -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/rooms-shown.d.ts +8 -0
- package/dist/store/rooms-shown.d.ts.map +1 -0
- package/dist/store/rooms-shown.js +13 -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 +113 -144
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +171 -364
- package/dist/stored.d.ts +72 -35
- package/dist/stored.d.ts.map +1 -1
- package/dist/stored.js +340 -197
- package/dist/surface.d.ts +89 -0
- package/dist/surface.d.ts.map +1 -0
- package/dist/surface.js +222 -0
- package/dist/sync.d.ts +19 -0
- package/dist/sync.d.ts.map +1 -0
- package/dist/sync.js +535 -0
- package/dist/tables.d.ts +124 -30
- package/dist/tables.d.ts.map +1 -1
- package/dist/tables.js +242 -62
- package/dist/tallies.d.ts +18 -0
- package/dist/tallies.d.ts.map +1 -0
- package/dist/tallies.js +128 -0
- package/dist/validation.d.ts.map +1 -1
- package/dist/validation.js +9 -12
- package/dist/windows.d.ts +1 -12
- package/dist/windows.d.ts.map +1 -1
- package/dist/windows.js +2 -75
- package/dist/wire.d.ts +58 -9
- package/dist/wire.d.ts.map +1 -1
- package/dist/wire.js +21 -5
- package/package.json +3 -2
- package/dist/attempt.d.ts +0 -16
- package/dist/attempt.d.ts.map +0 -1
- package/dist/attempt.js +0 -70
- package/dist/fence.d.ts +0 -6
- package/dist/fence.d.ts.map +0 -1
- package/dist/fence.js +0 -10
- package/dist/fulltext.d.ts +0 -27
- package/dist/fulltext.d.ts.map +0 -1
- package/dist/fulltext.js +0 -370
- package/dist/log.d.ts +0 -5
- package/dist/log.d.ts.map +0 -1
- package/dist/log.js +0 -14
- package/dist/words.d.ts +0 -19
- package/dist/words.d.ts.map +0 -1
- package/dist/words.js +0 -156
package/dist/seed.js
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
|
+
import { queryKey } from '@agentshouse/mdmodel';
|
|
2
|
+
import { pendingChange, whole } from './observation.js';
|
|
1
3
|
import { documentKey } from './rows.js';
|
|
4
|
+
const seedTopic = (key) => `seed\u0000${key}`;
|
|
2
5
|
function plain(value) {
|
|
3
6
|
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
4
7
|
}
|
|
@@ -59,7 +62,6 @@ export function seededResult(seed) {
|
|
|
59
62
|
generation,
|
|
60
63
|
current: false,
|
|
61
64
|
})),
|
|
62
|
-
indexes: [],
|
|
63
65
|
overlay: [],
|
|
64
66
|
};
|
|
65
67
|
if ('groups' in seed.rows) {
|
|
@@ -73,3 +75,71 @@ export function seededResult(seed) {
|
|
|
73
75
|
keys: seed.rows.documents.map((document) => documentKey(document.room, document.path)),
|
|
74
76
|
};
|
|
75
77
|
}
|
|
78
|
+
function seedRoomHeld({ socket }, room, version, held) {
|
|
79
|
+
const stored = held.rooms.get(room);
|
|
80
|
+
return (stored !== undefined &&
|
|
81
|
+
stored.indexed &&
|
|
82
|
+
socket.reads.reached(room, stored.roomVersion, version));
|
|
83
|
+
}
|
|
84
|
+
function seedHeld(runtime, at, held) {
|
|
85
|
+
const { socket, presence } = runtime;
|
|
86
|
+
return Object.entries(at).every(([room, version]) => (socket.session.now().roomsListed &&
|
|
87
|
+
presence.room(room) === undefined &&
|
|
88
|
+
!held.rooms.has(room)) ||
|
|
89
|
+
seedRoomHeld(runtime, room, version, held));
|
|
90
|
+
}
|
|
91
|
+
export function seedApplies(runtime, plan, held) {
|
|
92
|
+
const { seeds } = runtime.store;
|
|
93
|
+
const seed = seeds.of(plan.key);
|
|
94
|
+
if (seed === undefined)
|
|
95
|
+
return null;
|
|
96
|
+
if (!seedHeld(runtime, seed.at, held))
|
|
97
|
+
return seed;
|
|
98
|
+
seeds.drop(plan.key);
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
101
|
+
function seedBehind(runtime, plan, cover, held) {
|
|
102
|
+
const seed = seedApplies(runtime, plan, held);
|
|
103
|
+
if (seed === null || 'pending' in cover)
|
|
104
|
+
return cover;
|
|
105
|
+
return {
|
|
106
|
+
pending: Object.entries(seed.at)
|
|
107
|
+
.filter(([room, version]) => !seedRoomHeld(runtime, room, version, held))
|
|
108
|
+
.map(([room]) => ({ room, awaits: 'acquisition' })),
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
export function keepEntrySeed(store, entry) {
|
|
112
|
+
for (const { query, rows } of entry.queries) {
|
|
113
|
+
const key = queryKey(query);
|
|
114
|
+
store.seeds.keep(key, { rows, at: entry.at });
|
|
115
|
+
for (const watcher of store.watching(seedTopic(key)))
|
|
116
|
+
watcher.answer(null);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
export function watchSeeded(runtime, plan, deliver, watch) {
|
|
120
|
+
const { store } = runtime;
|
|
121
|
+
let seeded = false;
|
|
122
|
+
let pending = true;
|
|
123
|
+
const shown = () => {
|
|
124
|
+
const seed = store.seeds.of(plan.key);
|
|
125
|
+
if (seed === undefined || seeded || !pending)
|
|
126
|
+
return;
|
|
127
|
+
seeded = true;
|
|
128
|
+
deliver(seededResult(seed));
|
|
129
|
+
};
|
|
130
|
+
const watcher = store.watch(seedTopic(plan.key), shown);
|
|
131
|
+
const stop = watch((cover, held) => seedBehind(runtime, plan, cover, held), (message) => {
|
|
132
|
+
const answered = message;
|
|
133
|
+
pending = whole(answered) ? 'pending' in answered.result : pendingChange(answered);
|
|
134
|
+
if (pending && store.seeds.of(plan.key) !== undefined) {
|
|
135
|
+
shown();
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
seeded = false;
|
|
139
|
+
deliver(message);
|
|
140
|
+
});
|
|
141
|
+
return () => {
|
|
142
|
+
watcher.stop();
|
|
143
|
+
stop();
|
|
144
|
+
};
|
|
145
|
+
}
|
package/dist/shared.d.ts
CHANGED
|
@@ -1,14 +1,9 @@
|
|
|
1
1
|
export type Paths<V> = Readonly<Record<string, V>>;
|
|
2
|
+
export declare function guarding<V>(values: Paths<V>, handler: ProxyHandler<Paths<V>>): Paths<V>;
|
|
2
3
|
export declare function entriesIn<V>(map: Paths<V>): Generator<readonly [string, V]>;
|
|
3
4
|
export declare function sortedKeys(map: Paths<unknown>): Generator<number, readonly string[], void>;
|
|
4
5
|
export declare function sorting(keys: Iterable<string>): Generator<number, readonly string[], void>;
|
|
5
|
-
export declare function sharing<V>(map: Paths<V>): Generator<number, Paths<V>, void>;
|
|
6
|
-
export declare function shared<V>(map: Paths<V>): Paths<V>;
|
|
7
|
-
export declare function patched<V>(base: Paths<V>, set: Iterable<readonly [string, V]>, removed?: Iterable<string>): Paths<V>;
|
|
8
6
|
export declare function patching<V>(base: Paths<V>, set: Iterable<readonly [string, V]>, removed?: Iterable<string>): Generator<number, Paths<V>, void>;
|
|
9
|
-
export declare function sizeOf<V>(map: Paths<V>): number;
|
|
10
|
-
export declare function differences<V>(left: Paths<V>, right: Paths<V>, same?: (left: V, right: V) => boolean): Generator<number, ReadonlySet<string>, void>;
|
|
11
|
-
export declare function differing<V>(left: Paths<V>, right: Paths<V>, same?: (left: V, right: V) => boolean): ReadonlySet<string>;
|
|
12
7
|
export declare function drafted<V>(base: Paths<V>): Record<string, V>;
|
|
13
8
|
export declare function settled<V>(draft: Record<string, V>): Paths<V>;
|
|
14
9
|
export declare function settling<V>(draft: Record<string, V>): Generator<number, Paths<V>, void>;
|
package/dist/shared.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shared.d.ts","sourceRoot":"","sources":["../src/shared.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,KAAK,CAAC,CAAC,IAAI,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"shared.d.ts","sourceRoot":"","sources":["../src/shared.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,KAAK,CAAC,CAAC,IAAI,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC;AA8LnD,wBAAgB,QAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAIvF;AAED,wBAAiB,SAAS,CAAC,CAAC,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAQ5E;AAqCD,wBAAiB,UAAU,CAAC,GAAG,EAAE,KAAK,CAAC,OAAO,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,EAAE,IAAI,CAAC,CAE3F;AAED,wBAAiB,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,EAAE,IAAI,CAAC,CAoB3F;AAED,wBAAiB,QAAQ,CAAC,CAAC,EACzB,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,EACd,GAAG,EAAE,QAAQ,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EACnC,OAAO,GAAE,QAAQ,CAAC,MAAM,CAAM,GAC7B,SAAS,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAgBnC;AAMD,wBAAgB,OAAO,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAiD5D;AAED,wBAAgB,OAAO,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAE7D;AAED,wBAAiB,QAAQ,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAUxF"}
|
package/dist/shared.js
CHANGED
|
@@ -100,21 +100,15 @@ function lone(node) {
|
|
|
100
100
|
}
|
|
101
101
|
function taken(node, hash, key, shift) {
|
|
102
102
|
if (isLeaf(node))
|
|
103
|
-
return
|
|
103
|
+
return undefined;
|
|
104
104
|
if (isCollision(node)) {
|
|
105
105
|
const leaves = node.leaves.filter((leaf) => leaf.key !== key);
|
|
106
|
-
if (leaves.length === node.leaves.length)
|
|
107
|
-
return node;
|
|
108
106
|
return leaves.length === 1 ? leaves[0] : { hash: node.hash, leaves };
|
|
109
107
|
}
|
|
110
108
|
const bit = 1 << fragment(hash, shift);
|
|
111
|
-
if ((node.bitmap & bit) === 0)
|
|
112
|
-
return node;
|
|
113
109
|
const at = slot(node.bitmap, bit);
|
|
114
110
|
const child = node.children[at];
|
|
115
111
|
const next = taken(child, hash, key, shift + BITS);
|
|
116
|
-
if (next === child)
|
|
117
|
-
return node;
|
|
118
112
|
if (next === undefined) {
|
|
119
113
|
if (node.children.length === 1)
|
|
120
114
|
return undefined;
|
|
@@ -179,11 +173,18 @@ function facade(root) {
|
|
|
179
173
|
roots.set(map, root);
|
|
180
174
|
return map;
|
|
181
175
|
}
|
|
176
|
+
const guarded = new WeakMap();
|
|
177
|
+
export function guarding(values, handler) {
|
|
178
|
+
const map = new Proxy(values, handler);
|
|
179
|
+
guarded.set(map, values);
|
|
180
|
+
return map;
|
|
181
|
+
}
|
|
182
182
|
export function* entriesIn(map) {
|
|
183
183
|
const root = roots.get(map);
|
|
184
184
|
if (root === undefined) {
|
|
185
|
-
|
|
186
|
-
|
|
185
|
+
const values = guarded.get(map) ?? map;
|
|
186
|
+
for (const key of Object.keys(values))
|
|
187
|
+
yield [key, values[key]];
|
|
187
188
|
return;
|
|
188
189
|
}
|
|
189
190
|
for (const leaf of leavesOf(root.node))
|
|
@@ -194,13 +195,11 @@ function* rooted(map) {
|
|
|
194
195
|
if (held !== undefined)
|
|
195
196
|
return held;
|
|
196
197
|
let node;
|
|
197
|
-
let size = 0;
|
|
198
198
|
for (const [key, value] of entriesIn(map)) {
|
|
199
199
|
node = put(node, { key, hash: hashOf(key), value }, 0);
|
|
200
|
-
size += 1;
|
|
201
200
|
yield ROW_WEIGHT;
|
|
202
201
|
}
|
|
203
|
-
return { node
|
|
202
|
+
return { node };
|
|
204
203
|
}
|
|
205
204
|
const RUN = 1 << 10;
|
|
206
205
|
function* merged(left, right) {
|
|
@@ -244,106 +243,25 @@ export function* sorting(keys) {
|
|
|
244
243
|
}
|
|
245
244
|
return runs[0] ?? [];
|
|
246
245
|
}
|
|
247
|
-
export function* sharing(map) {
|
|
248
|
-
return roots.has(map) ? map : facade(yield* rooted(map));
|
|
249
|
-
}
|
|
250
|
-
export function shared(map) {
|
|
251
|
-
return finished(sharing(map));
|
|
252
|
-
}
|
|
253
|
-
export function patched(base, set, removed = []) {
|
|
254
|
-
return finished(patching(base, set, removed));
|
|
255
|
-
}
|
|
256
246
|
export function* patching(base, set, removed = []) {
|
|
257
247
|
const root = yield* rooted(base);
|
|
258
248
|
let node = root.node;
|
|
259
|
-
let size = root.size;
|
|
260
249
|
for (const key of removed) {
|
|
261
250
|
if (node === undefined)
|
|
262
251
|
break;
|
|
263
|
-
const before = lookup({ node
|
|
252
|
+
const before = lookup({ node }, key);
|
|
264
253
|
if (before === undefined)
|
|
265
254
|
continue;
|
|
266
255
|
node = taken(node, before.hash, key, 0);
|
|
267
|
-
size -= 1;
|
|
268
256
|
yield ROW_WEIGHT;
|
|
269
257
|
}
|
|
270
258
|
for (const [key, value] of set) {
|
|
271
|
-
const before = lookup({ node, size }, key);
|
|
272
259
|
node = put(node, { key, hash: hashOf(key), value }, 0);
|
|
273
|
-
if (before === undefined)
|
|
274
|
-
size += 1;
|
|
275
260
|
yield ROW_WEIGHT;
|
|
276
261
|
}
|
|
277
262
|
if (node === root.node && roots.has(base))
|
|
278
263
|
return base;
|
|
279
|
-
return facade({ node
|
|
280
|
-
}
|
|
281
|
-
export function sizeOf(map) {
|
|
282
|
-
return roots.get(map)?.size ?? Object.keys(map).length;
|
|
283
|
-
}
|
|
284
|
-
function* compared(left, right, same, into) {
|
|
285
|
-
const pending = [[left, right]];
|
|
286
|
-
for (let pair = pending.pop(); pair !== undefined; pair = pending.pop()) {
|
|
287
|
-
const [one, other] = pair;
|
|
288
|
-
if (one === other)
|
|
289
|
-
continue;
|
|
290
|
-
if (one !== undefined &&
|
|
291
|
-
other !== undefined &&
|
|
292
|
-
!isLeaf(one) &&
|
|
293
|
-
!isCollision(one) &&
|
|
294
|
-
!isLeaf(other) &&
|
|
295
|
-
!isCollision(other)) {
|
|
296
|
-
const children = [];
|
|
297
|
-
for (let remaining = one.bitmap | other.bitmap; remaining !== 0; remaining &= remaining - 1) {
|
|
298
|
-
const bit = remaining & -remaining;
|
|
299
|
-
children.push([
|
|
300
|
-
(one.bitmap & bit) === 0 ? undefined : one.children[slot(one.bitmap, bit)],
|
|
301
|
-
(other.bitmap & bit) === 0 ? undefined : other.children[slot(other.bitmap, bit)],
|
|
302
|
-
]);
|
|
303
|
-
}
|
|
304
|
-
pending.push(...children.reverse());
|
|
305
|
-
continue;
|
|
306
|
-
}
|
|
307
|
-
const before = new Map();
|
|
308
|
-
for (const leaf of leavesOf(one)) {
|
|
309
|
-
before.set(leaf.key, leaf.value);
|
|
310
|
-
yield ROW_WEIGHT;
|
|
311
|
-
}
|
|
312
|
-
for (const leaf of leavesOf(other)) {
|
|
313
|
-
const held = before.get(leaf.key);
|
|
314
|
-
before.delete(leaf.key);
|
|
315
|
-
if (held === undefined || !same(held, leaf.value))
|
|
316
|
-
into.add(leaf.key);
|
|
317
|
-
yield ROW_WEIGHT;
|
|
318
|
-
}
|
|
319
|
-
for (const key of before.keys())
|
|
320
|
-
into.add(key);
|
|
321
|
-
}
|
|
322
|
-
}
|
|
323
|
-
export function* differences(left, right, same = Object.is) {
|
|
324
|
-
const into = new Set();
|
|
325
|
-
if (left === right)
|
|
326
|
-
return into;
|
|
327
|
-
const leftRoot = roots.get(left);
|
|
328
|
-
const rightRoot = roots.get(right);
|
|
329
|
-
if (leftRoot !== undefined && rightRoot !== undefined) {
|
|
330
|
-
yield* compared(leftRoot.node, rightRoot.node, same, into);
|
|
331
|
-
return into;
|
|
332
|
-
}
|
|
333
|
-
for (const [key, value] of entriesIn(left)) {
|
|
334
|
-
if (!Object.hasOwn(right, key) || !same(value, right[key]))
|
|
335
|
-
into.add(key);
|
|
336
|
-
yield ROW_WEIGHT;
|
|
337
|
-
}
|
|
338
|
-
for (const [key] of entriesIn(right)) {
|
|
339
|
-
if (!Object.hasOwn(left, key))
|
|
340
|
-
into.add(key);
|
|
341
|
-
yield ROW_WEIGHT;
|
|
342
|
-
}
|
|
343
|
-
return into;
|
|
344
|
-
}
|
|
345
|
-
export function differing(left, right, same = Object.is) {
|
|
346
|
-
return finished(differences(left, right, same));
|
|
264
|
+
return facade({ node });
|
|
347
265
|
}
|
|
348
266
|
const drafts = new WeakMap();
|
|
349
267
|
const GONE = Symbol('gone');
|
package/dist/shown.d.ts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { Member } from './adapter.js';
|
|
2
|
+
import { type ChangeSet } from './change-set.js';
|
|
3
|
+
import type { QueueEntry } from './outcome.js';
|
|
4
|
+
import type { Runtime } from './runtime.js';
|
|
5
|
+
import type { Live, Moving } from './socket.js';
|
|
6
|
+
import { type CycleProgress } from './status.js';
|
|
7
|
+
export declare const ROOMS_TOPIC = "rooms";
|
|
8
|
+
export declare const STATUS_TOPIC = "sync-status";
|
|
9
|
+
export declare const REFUSAL_TOPIC = "connection-refusal";
|
|
10
|
+
export declare const STORAGE_LOSS_TOPIC = "storage-loss";
|
|
11
|
+
export declare const SERVICE_MODE_TOPIC = "service-mode";
|
|
12
|
+
export declare const MEMBER_TOPIC = "member";
|
|
13
|
+
export declare const AUTHORITY_TOPIC = "authority-changes";
|
|
14
|
+
export declare const LOCKS_TOPIC = "locks";
|
|
15
|
+
export declare const queueTopic: (locator: string) => string;
|
|
16
|
+
export declare function recoverReads({ liveQueries, figures }: Runtime, locators?: readonly string[]): void;
|
|
17
|
+
export declare function emitRooms(runtime: Runtime, changed?: readonly string[]): Promise<void>;
|
|
18
|
+
export declare function emitKnownRooms(runtime: Runtime): void;
|
|
19
|
+
export declare function emitRefusal(runtime: Runtime): void;
|
|
20
|
+
export declare function storageLossNow({ store }: Runtime): string | null;
|
|
21
|
+
export declare function emitStorageLoss(runtime: Runtime): void;
|
|
22
|
+
export declare function emitMember({ store }: Runtime, member: Member | null): void;
|
|
23
|
+
export declare function show(runtime: Runtime): Promise<void>;
|
|
24
|
+
export declare function moveTo(runtime: Runtime, next: Moving): Promise<void>;
|
|
25
|
+
export declare function statusShown(runtime: Runtime): Promise<void>;
|
|
26
|
+
export declare function transferring({ socket }: Runtime): Moving;
|
|
27
|
+
export declare function pendingShown(runtime: Runtime): Promise<void>;
|
|
28
|
+
export declare function entriesOf(runtime: Runtime, locator: string): Promise<readonly QueueEntry[]>;
|
|
29
|
+
export declare function publishChangeSet(runtime: Runtime, set: ChangeSet): Promise<void>;
|
|
30
|
+
export declare function submissionDue(runtime: Runtime, locators?: readonly string[]): Promise<void>;
|
|
31
|
+
export declare function roomUnreadable(runtime: Runtime, locator: string): void;
|
|
32
|
+
export declare function rest(runtime: Runtime, progress: CycleProgress | null, live?: Live): Promise<void>;
|
|
33
|
+
//# sourceMappingURL=shown.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shown.d.ts","sourceRoot":"","sources":["../src/shown.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAE3C,OAAO,EAA8B,KAAK,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAI7E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE/C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAA6B,KAAK,aAAa,EAAmB,MAAM,aAAa,CAAC;AAiB7F,eAAO,MAAM,WAAW,UAAU,CAAC;AAEnC,eAAO,MAAM,YAAY,gBAAgB,CAAC;AAE1C,eAAO,MAAM,aAAa,uBAAuB,CAAC;AAElD,eAAO,MAAM,kBAAkB,iBAAiB,CAAC;AAEjD,eAAO,MAAM,kBAAkB,iBAAiB,CAAC;AAEjD,eAAO,MAAM,YAAY,WAAW,CAAC;AAErC,eAAO,MAAM,eAAe,sBAAsB,CAAC;AAEnD,eAAO,MAAM,WAAW,UAAU,CAAC;AAEnC,eAAO,MAAM,UAAU,YAAa,MAAM,WAA4B,CAAC;AAqCvE,wBAAgB,YAAY,CAAC,EAAE,WAAW,EAAE,OAAO,EAAE,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,QAG3F;AAED,wBAAgB,SAAS,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAMtF;AAED,wBAAgB,cAAc,CAAC,OAAO,EAAE,OAAO,QAI9C;AAiFD,wBAAgB,WAAW,CAAC,OAAO,EAAE,OAAO,QAK3C;AAED,wBAAgB,cAAc,CAAC,EAAE,KAAK,EAAE,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAGhE;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,OAAO,QAG/C;AAED,wBAAgB,UAAU,CAAC,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,QAEnE;AA0BD,wBAAgB,IAAI,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAepD;AAED,wBAAgB,MAAM,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAIpE;AAED,wBAAgB,WAAW,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAE3D;AAED,wBAAgB,YAAY,CAAC,EAAE,MAAM,EAAE,EAAE,OAAO,GAAG,MAAM,CAExD;AAED,wBAAgB,YAAY,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAK5D;AAYD,wBAAsB,SAAS,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,UAAU,EAAE,CAAC,CAGjG;AAcD,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAuBhF;AAED,wBAAsB,aAAa,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAOjG;AAED,wBAAgB,cAAc,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,QAG/D;AAED,wBAAsB,IAAI,CACxB,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,aAAa,GAAG,IAAI,EAC9B,IAAI,GAAE,IAAqC,iBAiC5C"}
|
package/dist/shown.js
ADDED
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
import { changeSet, mergeChangeSets } from './change-set.js';
|
|
2
|
+
import { conversationsChanged, conversationsLearned } from './conversation.js';
|
|
3
|
+
import { lossStated } from './durability.js';
|
|
4
|
+
import { listedEntries, listingNow, shownChange, shownRooms } from './listing.js';
|
|
5
|
+
import { emitPresentation, publishRoomDrafts } from './room-drafts.js';
|
|
6
|
+
import { same } from './status.js';
|
|
7
|
+
export const ROOMS_TOPIC = 'rooms';
|
|
8
|
+
export const STATUS_TOPIC = 'sync-status';
|
|
9
|
+
export const REFUSAL_TOPIC = 'connection-refusal';
|
|
10
|
+
export const STORAGE_LOSS_TOPIC = 'storage-loss';
|
|
11
|
+
export const SERVICE_MODE_TOPIC = 'service-mode';
|
|
12
|
+
export const MEMBER_TOPIC = 'member';
|
|
13
|
+
export const AUTHORITY_TOPIC = 'authority-changes';
|
|
14
|
+
export const LOCKS_TOPIC = 'locks';
|
|
15
|
+
export const queueTopic = (locator) => `queue\u0000${locator}`;
|
|
16
|
+
async function attended({ store, localSaves }) {
|
|
17
|
+
const held = await store.status();
|
|
18
|
+
const attentionRequired = held.returned.flatMap((record) => record.returned === null
|
|
19
|
+
? []
|
|
20
|
+
: [{ room: record.locator, path: record.path, returned: structuredClone(record.returned) }]);
|
|
21
|
+
attentionRequired.sort((left, right) => {
|
|
22
|
+
if (left.room !== right.room)
|
|
23
|
+
return left.room < right.room ? -1 : 1;
|
|
24
|
+
if (left.path !== right.path)
|
|
25
|
+
return left.path < right.path ? -1 : 1;
|
|
26
|
+
return 0;
|
|
27
|
+
});
|
|
28
|
+
const changed = new Map();
|
|
29
|
+
if (!localSaves) {
|
|
30
|
+
for (const change of held.unsent)
|
|
31
|
+
changed.set(`${change.room}\u0000${change.path}`, change);
|
|
32
|
+
}
|
|
33
|
+
const unsent = [...changed]
|
|
34
|
+
.sort(([left], [right]) => (left < right ? -1 : left > right ? 1 : 0))
|
|
35
|
+
.map(([, change]) => change);
|
|
36
|
+
return {
|
|
37
|
+
queued: !localSaves && held.queued.length > 0,
|
|
38
|
+
lastCompleted: held.lastCompleted,
|
|
39
|
+
attentionRequired,
|
|
40
|
+
unsent,
|
|
41
|
+
reset: held.resets.reduce((earliest, { reset }) => (earliest !== null && earliest <= reset ? earliest : reset), null),
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
async function queuedWork({ store, localSaves }) {
|
|
45
|
+
return !localSaves && (await store.queued()).length > 0;
|
|
46
|
+
}
|
|
47
|
+
export function recoverReads({ liveQueries, figures }, locators) {
|
|
48
|
+
liveQueries.recover(locators);
|
|
49
|
+
figures.recover();
|
|
50
|
+
}
|
|
51
|
+
export function emitRooms(runtime, changed) {
|
|
52
|
+
recoverReads(runtime, changed);
|
|
53
|
+
runtime.store.readiness.queue(changed);
|
|
54
|
+
return changed === undefined
|
|
55
|
+
? publishRooms(runtime, 'all')
|
|
56
|
+
: publishRooms(runtime, 'changed', changed);
|
|
57
|
+
}
|
|
58
|
+
export function emitKnownRooms(runtime) {
|
|
59
|
+
conversationsLearned(runtime.conversations);
|
|
60
|
+
if (runtime.store.watching(ROOMS_TOPIC, 'waiting').length === 0)
|
|
61
|
+
return;
|
|
62
|
+
void publishRooms(runtime, 'known');
|
|
63
|
+
}
|
|
64
|
+
function roomsOwedWith(held, mode, touched) {
|
|
65
|
+
if (held === undefined) {
|
|
66
|
+
return {
|
|
67
|
+
all: mode === 'all',
|
|
68
|
+
changed: new Set(mode === 'changed' ? touched : []),
|
|
69
|
+
counted: new Set(mode === 'changed' ? [] : touched),
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
held.all ||= mode === 'all';
|
|
73
|
+
for (const locator of touched) {
|
|
74
|
+
(mode === 'changed' ? held.changed : held.counted).add(locator);
|
|
75
|
+
}
|
|
76
|
+
return held;
|
|
77
|
+
}
|
|
78
|
+
async function patchedRooms(runtime, owed) {
|
|
79
|
+
const { store } = runtime;
|
|
80
|
+
const touched = [...new Set([...owed.changed, ...owed.counted])];
|
|
81
|
+
const entries = await listedEntries(runtime, touched);
|
|
82
|
+
const shown = store.roomsShown.now();
|
|
83
|
+
if (entries === null || shown === null)
|
|
84
|
+
return false;
|
|
85
|
+
if (runtime.socket.closed())
|
|
86
|
+
return true;
|
|
87
|
+
const moved = entries.filter(({ locator, documents }) => owed.changed.has(locator) || shown.get(locator)?.documents !== documents);
|
|
88
|
+
const counted = moved.flatMap(({ locator }) => (owed.changed.has(locator) ? [] : [locator]));
|
|
89
|
+
if (counted.length > 0) {
|
|
90
|
+
recoverReads(runtime, counted);
|
|
91
|
+
store.readiness.queue(counted);
|
|
92
|
+
}
|
|
93
|
+
store.roomsShown.patch(moved);
|
|
94
|
+
if (moved.length === 0)
|
|
95
|
+
return true;
|
|
96
|
+
const change = shownChange(runtime, moved);
|
|
97
|
+
for (const watcher of store.watching(ROOMS_TOPIC, 'ready'))
|
|
98
|
+
watcher.answer(change);
|
|
99
|
+
return true;
|
|
100
|
+
}
|
|
101
|
+
async function deliverRooms(runtime, owed) {
|
|
102
|
+
const { store, socket } = runtime;
|
|
103
|
+
const waiting = () => store.watching(ROOMS_TOPIC, 'waiting');
|
|
104
|
+
if (socket.closed() || store.watching(ROOMS_TOPIC).length === 0)
|
|
105
|
+
return;
|
|
106
|
+
const touched = owed.changed.size > 0 || owed.counted.size > 0;
|
|
107
|
+
if (!owed.all && touched && waiting().length === 0 && (await patchedRooms(runtime, owed)))
|
|
108
|
+
return;
|
|
109
|
+
if (touched)
|
|
110
|
+
owed.all = true;
|
|
111
|
+
const listing = await listingNow(runtime);
|
|
112
|
+
if (socket.closed())
|
|
113
|
+
return;
|
|
114
|
+
const { roomsListed, refusal, moving } = socket.session.now();
|
|
115
|
+
const joining = waiting().length > 0 &&
|
|
116
|
+
(roomsListed || listing.size > 0 || refusal !== null || moving.providerUnreachable);
|
|
117
|
+
if (!owed.all && !joining)
|
|
118
|
+
return;
|
|
119
|
+
const value = shownRooms(runtime, listing);
|
|
120
|
+
const shown = store.roomsShown.now();
|
|
121
|
+
const moved = owed.all ||
|
|
122
|
+
(shown !== null && JSON.stringify(shownRooms(runtime, shown)) !== JSON.stringify(value));
|
|
123
|
+
if (moved)
|
|
124
|
+
for (const watcher of store.watching(ROOMS_TOPIC, 'ready'))
|
|
125
|
+
watcher.answer(value);
|
|
126
|
+
if (joining)
|
|
127
|
+
for (const watcher of waiting())
|
|
128
|
+
watcher.answer(value);
|
|
129
|
+
store.roomsShown.show(store.watching(ROOMS_TOPIC, 'ready').length === 0 ? null : listing);
|
|
130
|
+
}
|
|
131
|
+
function publishRooms(runtime, mode, touched = []) {
|
|
132
|
+
if (runtime.socket.closed())
|
|
133
|
+
return Promise.resolve();
|
|
134
|
+
return runtime.store.owing(ROOMS_TOPIC, (held) => roomsOwedWith(held, mode, touched), (owed) => deliverRooms(runtime, owed));
|
|
135
|
+
}
|
|
136
|
+
export function emitRefusal(runtime) {
|
|
137
|
+
const { store, socket } = runtime;
|
|
138
|
+
store.readiness.queue([]);
|
|
139
|
+
store.tell(REFUSAL_TOPIC, socket.session.now().refusal);
|
|
140
|
+
emitKnownRooms(runtime);
|
|
141
|
+
}
|
|
142
|
+
export function storageLossNow({ store }) {
|
|
143
|
+
const { persistence, storageLoss } = store.device.now();
|
|
144
|
+
return lossStated(persistence, storageLoss);
|
|
145
|
+
}
|
|
146
|
+
export function emitStorageLoss(runtime) {
|
|
147
|
+
runtime.store.readiness.queue([]);
|
|
148
|
+
runtime.store.tell(STORAGE_LOSS_TOPIC, storageLossNow(runtime));
|
|
149
|
+
}
|
|
150
|
+
export function emitMember({ store }, member) {
|
|
151
|
+
store.tell(MEMBER_TOPIC, member);
|
|
152
|
+
}
|
|
153
|
+
async function deliverStatus(runtime, owed) {
|
|
154
|
+
const { store, socket } = runtime;
|
|
155
|
+
const held = await attended(runtime);
|
|
156
|
+
if (socket.closed())
|
|
157
|
+
return;
|
|
158
|
+
for (const { moving, current } of owed) {
|
|
159
|
+
const state = moving.resting && held.queued ? 'pending' : moving.state;
|
|
160
|
+
const next = {
|
|
161
|
+
state: state === 'synced' && !current ? 'syncing' : state,
|
|
162
|
+
lastCompleted: held.lastCompleted,
|
|
163
|
+
providerUnreachable: moving.providerUnreachable,
|
|
164
|
+
attentionRequired: held.attentionRequired,
|
|
165
|
+
unsent: held.unsent,
|
|
166
|
+
reset: held.reset,
|
|
167
|
+
};
|
|
168
|
+
if (same(store.device.now().status, next))
|
|
169
|
+
continue;
|
|
170
|
+
store.device.set({ status: next });
|
|
171
|
+
store.tell(STATUS_TOPIC, next);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
function conversationsCurrent({ conversations }) {
|
|
175
|
+
return conversations.listed() && conversations.current();
|
|
176
|
+
}
|
|
177
|
+
export function show(runtime) {
|
|
178
|
+
const { store, socket } = runtime;
|
|
179
|
+
if (socket.closed())
|
|
180
|
+
return Promise.resolve();
|
|
181
|
+
store.readiness.queue([]);
|
|
182
|
+
emitKnownRooms(runtime);
|
|
183
|
+
const moved = { moving: socket.session.now().moving, current: conversationsCurrent(runtime) };
|
|
184
|
+
return store.owing(STATUS_TOPIC, (held) => {
|
|
185
|
+
if (held === undefined)
|
|
186
|
+
return [moved];
|
|
187
|
+
held.push(moved);
|
|
188
|
+
return held;
|
|
189
|
+
}, (owed) => deliverStatus(runtime, owed));
|
|
190
|
+
}
|
|
191
|
+
export function moveTo(runtime, next) {
|
|
192
|
+
if (runtime.socket.closed())
|
|
193
|
+
return Promise.resolve();
|
|
194
|
+
runtime.socket.session.set({ moving: next });
|
|
195
|
+
return show(runtime);
|
|
196
|
+
}
|
|
197
|
+
export function statusShown(runtime) {
|
|
198
|
+
return moveTo(runtime, runtime.socket.session.now().moving);
|
|
199
|
+
}
|
|
200
|
+
export function transferring({ socket }) {
|
|
201
|
+
return { ...socket.session.now().moving, state: 'syncing', resting: false };
|
|
202
|
+
}
|
|
203
|
+
export function pendingShown(runtime) {
|
|
204
|
+
const { socket, localSaves } = runtime;
|
|
205
|
+
if (!localSaves)
|
|
206
|
+
socket.session.set({ recorded: false });
|
|
207
|
+
const { moving } = socket.session.now();
|
|
208
|
+
return moveTo(runtime, localSaves ? moving : { ...moving, state: 'pending', resting: false });
|
|
209
|
+
}
|
|
210
|
+
function entryOf({ localSaves }, states, batch) {
|
|
211
|
+
if (localSaves)
|
|
212
|
+
return Object.freeze({ batch, state: 'local' });
|
|
213
|
+
const state = states.get(batch.id);
|
|
214
|
+
return Object.freeze({ batch, ...(state?.submission ?? { state: 'waiting' }) });
|
|
215
|
+
}
|
|
216
|
+
export async function entriesOf(runtime, locator) {
|
|
217
|
+
const { queue, states } = await runtime.store.work(locator);
|
|
218
|
+
return queue.map((batch) => entryOf(runtime, states, batch));
|
|
219
|
+
}
|
|
220
|
+
function emitQueue(runtime, locator) {
|
|
221
|
+
const { store, socket } = runtime;
|
|
222
|
+
const listening = () => store.watching(queueTopic(locator));
|
|
223
|
+
if (socket.closed() || listening().length === 0)
|
|
224
|
+
return Promise.resolve();
|
|
225
|
+
return store.publication(async () => {
|
|
226
|
+
if (socket.closed() || listening().length === 0)
|
|
227
|
+
return;
|
|
228
|
+
const entries = await entriesOf(runtime, locator);
|
|
229
|
+
if (socket.closed())
|
|
230
|
+
return;
|
|
231
|
+
for (const watcher of listening())
|
|
232
|
+
watcher.answer(entries);
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
export function publishChangeSet(runtime, set) {
|
|
236
|
+
const { store, liveQueries, figures, conversations } = runtime;
|
|
237
|
+
liveQueries.touched(set);
|
|
238
|
+
figures.touched(set);
|
|
239
|
+
for (const { locator, path } of set.documents) {
|
|
240
|
+
if (path !== null)
|
|
241
|
+
store.attached.drop(locator, path);
|
|
242
|
+
}
|
|
243
|
+
const shownNow = [];
|
|
244
|
+
if (set.queues.length > 0 || set.drafts.length > 0)
|
|
245
|
+
shownNow.push(show(runtime));
|
|
246
|
+
if (set.rooms.length > 0)
|
|
247
|
+
shownNow.push(emitRooms(runtime, set.rooms));
|
|
248
|
+
else if (set.documents.length > 0) {
|
|
249
|
+
shownNow.push(publishRooms(runtime, 'counted', [...new Set(set.documents.map(({ locator }) => locator))]));
|
|
250
|
+
}
|
|
251
|
+
for (const locator of set.queues)
|
|
252
|
+
shownNow.push(emitQueue(runtime, locator));
|
|
253
|
+
if (set.drafts.length > 0)
|
|
254
|
+
shownNow.push(publishRoomDrafts(runtime, false));
|
|
255
|
+
else if (set.documents.length > 0) {
|
|
256
|
+
shownNow.push(publishRoomDrafts(runtime, false, set.documents));
|
|
257
|
+
}
|
|
258
|
+
for (const app of set.presentations)
|
|
259
|
+
shownNow.push(emitPresentation(runtime, app));
|
|
260
|
+
conversationsChanged(conversations, set);
|
|
261
|
+
return Promise.all(shownNow).then(() => undefined);
|
|
262
|
+
}
|
|
263
|
+
export async function submissionDue(runtime, locators) {
|
|
264
|
+
const { store } = runtime;
|
|
265
|
+
const due = (await store.queued()).filter((locator) => locators === undefined || locators.includes(locator));
|
|
266
|
+
if (due.length === 0)
|
|
267
|
+
return;
|
|
268
|
+
await store.changed(mergeChangeSets(due.map((locator) => changeSet(locator, { due: true }))));
|
|
269
|
+
}
|
|
270
|
+
export function roomUnreadable(runtime, locator) {
|
|
271
|
+
runtime.presence.refused(locator, null);
|
|
272
|
+
emitRooms(runtime, [locator]);
|
|
273
|
+
}
|
|
274
|
+
export async function rest(runtime, progress, live = () => !runtime.socket.closed()) {
|
|
275
|
+
const { store, socket, presence } = runtime;
|
|
276
|
+
const { session, lanes } = socket;
|
|
277
|
+
if (!live())
|
|
278
|
+
return;
|
|
279
|
+
const settled = () => session.now().complete &&
|
|
280
|
+
lanes.roomWork() === 0 &&
|
|
281
|
+
!socket.naming() &&
|
|
282
|
+
presence.settled() &&
|
|
283
|
+
conversationsCurrent(runtime);
|
|
284
|
+
let synced = settled();
|
|
285
|
+
if (synced && !session.now().recorded) {
|
|
286
|
+
const queued = await queuedWork(runtime).catch(() => true);
|
|
287
|
+
if (!live())
|
|
288
|
+
return;
|
|
289
|
+
synced = !queued && settled();
|
|
290
|
+
}
|
|
291
|
+
if (synced && !session.now().recorded) {
|
|
292
|
+
const completedAt = new Date().toISOString();
|
|
293
|
+
try {
|
|
294
|
+
await (await store.open()).fact('lastCompleted', completedAt);
|
|
295
|
+
if (!live())
|
|
296
|
+
return;
|
|
297
|
+
session.set({ recorded: true });
|
|
298
|
+
}
|
|
299
|
+
catch {
|
|
300
|
+
synced = false;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
const { complete, moving } = session.now();
|
|
304
|
+
moveTo(runtime, {
|
|
305
|
+
state: synced && complete && lanes.roomWork() === 0 && !socket.naming() ? 'synced' : 'syncing',
|
|
306
|
+
providerUnreachable: progress === null ? moving.providerUnreachable : !progress.reachable,
|
|
307
|
+
resting: true,
|
|
308
|
+
});
|
|
309
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"admission.d.ts","sourceRoot":"","sources":["../../src/socket/admission.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,SAAS,GAAG;IACtB,UAAU,IAAI,OAAO,CAAC,MAAM,IAAI,CAAC,CAAC;IAClC,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1B,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,IAAI,CAAC;CAClC,CAAC;AAEF,wBAAgB,eAAe,IAAI,SAAS,CAmC3C"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
const STREAMS_HELD = 4;
|
|
2
|
+
const QUEUED_TEXT = 1 << 23;
|
|
3
|
+
export function createAdmission() {
|
|
4
|
+
let streamsFree = STREAMS_HELD;
|
|
5
|
+
let queuedText = 0;
|
|
6
|
+
const installWaiters = [];
|
|
7
|
+
function once(release) {
|
|
8
|
+
let released = false;
|
|
9
|
+
return () => {
|
|
10
|
+
if (released)
|
|
11
|
+
return;
|
|
12
|
+
released = true;
|
|
13
|
+
release();
|
|
14
|
+
for (const admit of installWaiters.splice(0))
|
|
15
|
+
admit();
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
return {
|
|
19
|
+
async heldStream() {
|
|
20
|
+
while (streamsFree === 0)
|
|
21
|
+
await new Promise((admit) => installWaiters.push(admit));
|
|
22
|
+
streamsFree -= 1;
|
|
23
|
+
return once(() => {
|
|
24
|
+
streamsFree += 1;
|
|
25
|
+
});
|
|
26
|
+
},
|
|
27
|
+
async unqueued() {
|
|
28
|
+
while (queuedText >= QUEUED_TEXT) {
|
|
29
|
+
await new Promise((admit) => installWaiters.push(admit));
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
queued(text) {
|
|
33
|
+
queuedText += text;
|
|
34
|
+
return once(() => {
|
|
35
|
+
queuedText -= text;
|
|
36
|
+
});
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
}
|