atom.io 0.30.6 → 0.31.0
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/data/dist/index.d.ts +20 -18
- package/data/dist/index.js +104 -172
- package/data/src/join.ts +138 -210
- package/dist/{chunk-LSCRHXLI.js → chunk-42UH5F5Q.js} +385 -773
- package/dist/chunk-ICGFFQ3H.js +272 -0
- package/dist/index.d.ts +52 -103
- package/dist/index.js +3 -11
- package/eslint-plugin/dist/index.d.ts +22 -3
- package/eslint-plugin/dist/index.js +7 -7
- package/immortal/dist/index.d.ts +1 -2
- package/immortal/dist/index.js +0 -3
- package/immortal/src/seek-state.ts +2 -14
- package/internal/dist/index.d.ts +59 -95
- package/internal/dist/index.js +2 -2
- package/internal/src/atom/dispose-atom.ts +31 -15
- package/internal/src/families/dispose-from-store.ts +15 -44
- package/internal/src/families/find-in-store.ts +15 -8
- package/internal/src/families/init-family-member.ts +1 -1
- package/internal/src/families/seek-in-store.ts +2 -14
- package/internal/src/get-state/get-from-store.ts +13 -79
- package/internal/src/get-trace.ts +7 -0
- package/internal/src/index.ts +2 -1
- package/internal/src/ingest-updates/ingest-creation-disposal.ts +63 -70
- package/internal/src/ingest-updates/ingest-transaction-update.ts +4 -0
- package/internal/src/junction.ts +52 -12
- package/internal/src/lineage.ts +0 -7
- package/internal/src/molecule.ts +7 -0
- package/internal/src/mutable/transceiver.ts +5 -5
- package/internal/src/pretty-print.ts +0 -4
- package/internal/src/selector/dispose-selector.ts +3 -5
- package/internal/src/selector/register-selector.ts +2 -26
- package/internal/src/set-state/set-into-store.ts +3 -2
- package/internal/src/store/counterfeit.ts +11 -25
- package/internal/src/store/deposit.ts +5 -39
- package/internal/src/store/index.ts +1 -0
- package/internal/src/store/store.ts +51 -12
- package/internal/src/store/withdraw.ts +3 -26
- package/internal/src/timeline/create-timeline.ts +133 -237
- package/internal/src/timeline/time-travel.ts +1 -8
- package/internal/src/transaction/build-transaction.ts +10 -5
- package/internal/src/transaction/index.ts +1 -1
- package/internal/src/utility-types.ts +2 -0
- package/introspection/dist/index.d.ts +2 -3
- package/introspection/dist/index.js +9 -9
- package/introspection/src/refinery.ts +1 -3
- package/json/dist/index.js +9 -40
- package/json/src/index.ts +2 -0
- package/json/src/select-json-family.ts +7 -44
- package/package.json +34 -29
- package/react/dist/index.js +2 -10
- package/react/src/parse-state-overloads.ts +3 -11
- package/react-devtools/dist/index.js +13 -13
- package/react-devtools/src/Updates.tsx +2 -0
- package/realtime-client/dist/index.d.ts +20 -12
- package/realtime-client/dist/index.js +241 -244
- package/realtime-client/src/continuity/index.ts +3 -0
- package/realtime-client/src/continuity/register-and-attempt-confirmed-update.ts +231 -0
- package/realtime-client/src/continuity/use-conceal-state.ts +11 -0
- package/realtime-client/src/continuity/use-reveal-state.ts +19 -0
- package/realtime-client/src/index.ts +1 -0
- package/realtime-client/src/sync-continuity.ts +18 -262
- package/realtime-react/dist/index.js +2 -2
- package/realtime-server/dist/index.d.ts +1 -1
- package/realtime-server/dist/index.js +2 -2
- package/realtime-server/src/index.ts +1 -1
- package/realtime-testing/dist/index.js +2 -3
- package/realtime-testing/src/setup-realtime-test.tsx +1 -2
- package/src/allocate.ts +311 -145
- package/src/dispose-state.ts +5 -21
- package/src/get-state.ts +3 -21
- package/src/molecule.ts +11 -133
- package/src/silo.ts +1 -12
- package/src/timeline.ts +2 -3
- package/src/transaction.ts +25 -38
- package/dist/chunk-ADMEAXYU.js +0 -167
- package/internal/src/molecule/create-molecule-family.ts +0 -30
- package/internal/src/molecule/dispose-molecule.ts +0 -79
- package/internal/src/molecule/grow-molecule-in-store.ts +0 -95
- package/internal/src/molecule/index.ts +0 -5
- package/internal/src/molecule/make-molecule-in-store.ts +0 -191
- package/internal/src/molecule/molecule-internal.ts +0 -52
|
@@ -1,23 +1,31 @@
|
|
|
1
1
|
import * as AtomIO from 'atom.io';
|
|
2
|
+
import { AtomToken } from 'atom.io';
|
|
2
3
|
import * as Internal from 'atom.io/internal';
|
|
3
|
-
import { Store,
|
|
4
|
+
import { Store, Func, Transceiver } from 'atom.io/internal';
|
|
5
|
+
import { Socket } from 'atom.io/realtime-server';
|
|
4
6
|
import { Json } from 'atom.io/json';
|
|
5
|
-
import { Socket } from 'socket.io-client';
|
|
7
|
+
import { Socket as Socket$1 } from 'socket.io-client';
|
|
6
8
|
import { ContinuityToken } from 'atom.io/realtime';
|
|
7
9
|
|
|
8
|
-
declare
|
|
10
|
+
declare const useRegisterAndAttemptConfirmedUpdate: (store: Store, continuityKey: string, socket: Socket, optimisticUpdates: AtomIO.TransactionUpdate<any>[], confirmedUpdates: AtomIO.TransactionUpdate<any>[]) => (confirmed: AtomIO.TransactionUpdate<Func>) => void;
|
|
9
11
|
|
|
10
|
-
declare function
|
|
12
|
+
declare function useConcealState(store: Store): (concealed: AtomToken<unknown>[]) => void;
|
|
11
13
|
|
|
12
|
-
declare function
|
|
14
|
+
declare function useRevealState(store: Store): (revealed: Json.Array) => void;
|
|
13
15
|
|
|
14
|
-
declare function
|
|
16
|
+
declare function pullAtom<J extends Json.Serializable>(token: AtomIO.RegularAtomToken<J>, socket: Socket$1, store: Store): () => void;
|
|
15
17
|
|
|
16
|
-
declare function
|
|
18
|
+
declare function pullAtomFamilyMember<J extends Json.Serializable>(token: AtomIO.RegularAtomToken<J>, socket: Socket$1, store: Store): () => void;
|
|
17
19
|
|
|
18
|
-
declare function
|
|
20
|
+
declare function pullMutableAtom<T extends Transceiver<any>, J extends Json.Serializable>(token: AtomIO.MutableAtomToken<T, J>, socket: Socket$1, store: Store): () => void;
|
|
19
21
|
|
|
20
|
-
declare function
|
|
22
|
+
declare function pullMutableAtomFamilyMember<T extends Transceiver<any>, J extends Json.Serializable>(token: AtomIO.MutableAtomToken<T, J>, socket: Socket$1, store: Store): () => void;
|
|
23
|
+
|
|
24
|
+
declare function pullSelector<T>(token: AtomIO.SelectorToken<T>, socket: Socket$1, store: Store): () => void;
|
|
25
|
+
|
|
26
|
+
declare function pullSelectorFamilyMember<T>(token: AtomIO.SelectorToken<T>, socket: Socket$1, store: Store): () => void;
|
|
27
|
+
|
|
28
|
+
declare function pushState<J extends Json.Serializable>(token: AtomIO.WritableToken<J>, socket: Socket$1, store: Internal.Store): () => void;
|
|
21
29
|
|
|
22
30
|
declare const myIdState__INTERNAL: AtomIO.RegularAtomToken<string | undefined>;
|
|
23
31
|
declare const myIdState: AtomIO.ReadonlySelectorToken<string | undefined>;
|
|
@@ -26,8 +34,8 @@ declare const myUsernameState: AtomIO.RegularAtomToken<string | null>;
|
|
|
26
34
|
declare const optimisticUpdateQueue: AtomIO.RegularAtomToken<AtomIO.TransactionUpdate<any>[]>;
|
|
27
35
|
declare const confirmedUpdateQueue: AtomIO.RegularAtomToken<AtomIO.TransactionUpdate<any>[]>;
|
|
28
36
|
|
|
29
|
-
declare function serverAction<F extends Internal.Func>(token: AtomIO.TransactionToken<F>, socket: Socket, store: Internal.Store): () => void;
|
|
37
|
+
declare function serverAction<F extends Internal.Func>(token: AtomIO.TransactionToken<F>, socket: Socket$1, store: Internal.Store): () => void;
|
|
30
38
|
|
|
31
|
-
declare function syncContinuity
|
|
39
|
+
declare function syncContinuity(continuity: ContinuityToken, socket: Socket$1, store: Store): () => void;
|
|
32
40
|
|
|
33
|
-
export { confirmedUpdateQueue, myIdState, myIdState__INTERNAL, myUsernameState, optimisticUpdateQueue, pullAtom, pullAtomFamilyMember, pullMutableAtom, pullMutableAtomFamilyMember, pullSelector, pullSelectorFamilyMember, pushState, serverAction, syncContinuity };
|
|
41
|
+
export { confirmedUpdateQueue, myIdState, myIdState__INTERNAL, myUsernameState, optimisticUpdateQueue, pullAtom, pullAtomFamilyMember, pullMutableAtom, pullMutableAtomFamilyMember, pullSelector, pullSelectorFamilyMember, pushState, serverAction, syncContinuity, useConcealState, useRegisterAndAttemptConfirmedUpdate, useRevealState };
|
|
@@ -1,11 +1,231 @@
|
|
|
1
1
|
import '../../dist/chunk-XWL6SNVU.js';
|
|
2
2
|
import * as Internal from 'atom.io/internal';
|
|
3
|
-
import { setIntoStore,
|
|
3
|
+
import { setIntoStore, getEpochNumberOfContinuity, isRootStore, ingestTransactionUpdate, setEpochNumberOfContinuity, disposeAtom, getJsonToken, getUpdateToken, getFromStore, assignTransactionToContinuity, subscribeToTransaction, actUponStore } from 'atom.io/internal';
|
|
4
|
+
import { confirmedUpdateQueue, optimisticUpdateQueue } from 'atom.io/realtime-client';
|
|
4
5
|
import { parseJson } from 'atom.io/json';
|
|
5
6
|
import * as AtomIO from 'atom.io';
|
|
6
7
|
import { persistSync } from 'atom.io/web';
|
|
7
|
-
import { optimisticUpdateQueue as optimisticUpdateQueue$1, confirmedUpdateQueue as confirmedUpdateQueue$1 } from 'atom.io/realtime-client';
|
|
8
8
|
|
|
9
|
+
var useRegisterAndAttemptConfirmedUpdate = (store, continuityKey, socket, optimisticUpdates, confirmedUpdates) => (confirmed) => {
|
|
10
|
+
function reconcileEpoch(optimisticUpdate, confirmedUpdate) {
|
|
11
|
+
store.logger.info(
|
|
12
|
+
`\u{1F9D1}\u200D\u2696\uFE0F`,
|
|
13
|
+
`continuity`,
|
|
14
|
+
continuityKey,
|
|
15
|
+
`reconciling updates`
|
|
16
|
+
);
|
|
17
|
+
setIntoStore(store, optimisticUpdateQueue, (queue) => {
|
|
18
|
+
queue.shift();
|
|
19
|
+
return queue;
|
|
20
|
+
});
|
|
21
|
+
if (optimisticUpdate.id === confirmedUpdate.id) {
|
|
22
|
+
const clientResult = JSON.stringify(optimisticUpdate.updates);
|
|
23
|
+
const serverResult = JSON.stringify(confirmedUpdate.updates);
|
|
24
|
+
if (clientResult === serverResult) {
|
|
25
|
+
store.logger.info(
|
|
26
|
+
`\u2705`,
|
|
27
|
+
`continuity`,
|
|
28
|
+
continuityKey,
|
|
29
|
+
`results for ${optimisticUpdate.id} match between client and server`
|
|
30
|
+
);
|
|
31
|
+
socket.emit(`ack:${continuityKey}`, confirmedUpdate.epoch);
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
} else {
|
|
35
|
+
store.logger.info(
|
|
36
|
+
`\u274C`,
|
|
37
|
+
`continuity`,
|
|
38
|
+
continuityKey,
|
|
39
|
+
`thought update #${confirmedUpdate.epoch} was ${optimisticUpdate.key}:${optimisticUpdate.id}, but it was actually ${confirmedUpdate.key}:${confirmedUpdate.id}`
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
store.logger.info(
|
|
43
|
+
`\u{1F9D1}\u200D\u2696\uFE0F`,
|
|
44
|
+
`continuity`,
|
|
45
|
+
continuityKey,
|
|
46
|
+
`updates do not match`,
|
|
47
|
+
optimisticUpdate,
|
|
48
|
+
confirmedUpdate
|
|
49
|
+
);
|
|
50
|
+
const reversedOptimisticUpdates = optimisticUpdates.toReversed();
|
|
51
|
+
for (const subsequentOptimistic of reversedOptimisticUpdates) {
|
|
52
|
+
ingestTransactionUpdate(`oldValue`, subsequentOptimistic, store);
|
|
53
|
+
}
|
|
54
|
+
store.logger.info(
|
|
55
|
+
`\u23EA`,
|
|
56
|
+
`continuity`,
|
|
57
|
+
continuityKey,
|
|
58
|
+
`undid optimistic updates:`,
|
|
59
|
+
reversedOptimisticUpdates
|
|
60
|
+
);
|
|
61
|
+
ingestTransactionUpdate(`oldValue`, optimisticUpdate, store);
|
|
62
|
+
store.logger.info(
|
|
63
|
+
`\u23EA`,
|
|
64
|
+
`continuity`,
|
|
65
|
+
continuityKey,
|
|
66
|
+
`undid zeroth optimistic update`,
|
|
67
|
+
optimisticUpdate
|
|
68
|
+
);
|
|
69
|
+
ingestTransactionUpdate(`newValue`, confirmedUpdate, store);
|
|
70
|
+
store.logger.info(
|
|
71
|
+
`\u23E9`,
|
|
72
|
+
`continuity`,
|
|
73
|
+
continuityKey,
|
|
74
|
+
`applied confirmed update`,
|
|
75
|
+
confirmedUpdate
|
|
76
|
+
);
|
|
77
|
+
socket.emit(`ack:${continuityKey}`, confirmedUpdate.epoch);
|
|
78
|
+
for (const subsequentOptimistic of optimisticUpdates) {
|
|
79
|
+
const token = {
|
|
80
|
+
type: `transaction`,
|
|
81
|
+
key: subsequentOptimistic.key
|
|
82
|
+
};
|
|
83
|
+
const { id, params } = subsequentOptimistic;
|
|
84
|
+
actUponStore(token, id, store)(...params);
|
|
85
|
+
}
|
|
86
|
+
store.logger.info(
|
|
87
|
+
`\u23E9`,
|
|
88
|
+
`continuity`,
|
|
89
|
+
continuityKey,
|
|
90
|
+
`reapplied subsequent optimistic updates:`,
|
|
91
|
+
optimisticUpdates
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
store.logger.info(
|
|
95
|
+
`\u{1F9D1}\u200D\u2696\uFE0F`,
|
|
96
|
+
`continuity`,
|
|
97
|
+
continuityKey,
|
|
98
|
+
`integrating confirmed update`,
|
|
99
|
+
{ confirmedUpdate: confirmed, confirmedUpdates, optimisticUpdates }
|
|
100
|
+
);
|
|
101
|
+
const zerothOptimisticUpdate = optimisticUpdates[0];
|
|
102
|
+
if (zerothOptimisticUpdate) {
|
|
103
|
+
store.logger.info(
|
|
104
|
+
`\u{1F9D1}\u200D\u2696\uFE0F`,
|
|
105
|
+
`continuity`,
|
|
106
|
+
continuityKey,
|
|
107
|
+
`has optimistic updates to reconcile`
|
|
108
|
+
);
|
|
109
|
+
if (confirmed.epoch === zerothOptimisticUpdate.epoch) {
|
|
110
|
+
store.logger.info(
|
|
111
|
+
`\u{1F9D1}\u200D\u2696\uFE0F`,
|
|
112
|
+
`continuity`,
|
|
113
|
+
continuityKey,
|
|
114
|
+
`epoch of confirmed update #${confirmed.epoch} matches zeroth optimistic update`
|
|
115
|
+
);
|
|
116
|
+
reconcileEpoch(zerothOptimisticUpdate, confirmed);
|
|
117
|
+
for (const nextConfirmed of confirmedUpdates) {
|
|
118
|
+
const nextOptimistic = optimisticUpdates[0];
|
|
119
|
+
if (nextConfirmed.epoch === nextOptimistic?.epoch) {
|
|
120
|
+
reconcileEpoch(nextOptimistic, nextConfirmed);
|
|
121
|
+
} else {
|
|
122
|
+
break;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
} else {
|
|
126
|
+
store.logger.info(
|
|
127
|
+
`\u{1F9D1}\u200D\u2696\uFE0F`,
|
|
128
|
+
`continuity`,
|
|
129
|
+
continuityKey,
|
|
130
|
+
`epoch of confirmed update #${confirmed.epoch} does not match zeroth optimistic update #${zerothOptimisticUpdate.epoch}`
|
|
131
|
+
);
|
|
132
|
+
const confirmedUpdateIsAlreadyEnqueued = confirmedUpdates.some(
|
|
133
|
+
(update) => update.epoch === confirmed.epoch
|
|
134
|
+
);
|
|
135
|
+
if (!confirmedUpdateIsAlreadyEnqueued) {
|
|
136
|
+
store.logger.info(
|
|
137
|
+
`\u{1F448}`,
|
|
138
|
+
`continuity`,
|
|
139
|
+
continuityKey,
|
|
140
|
+
`pushing confirmed update to queue`,
|
|
141
|
+
confirmed
|
|
142
|
+
);
|
|
143
|
+
setIntoStore(store, confirmedUpdateQueue, (queue) => {
|
|
144
|
+
queue.push(confirmed);
|
|
145
|
+
queue.sort((a, b) => a.epoch - b.epoch);
|
|
146
|
+
return queue;
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
} else {
|
|
151
|
+
store.logger.info(
|
|
152
|
+
`\u{1F9D1}\u200D\u2696\uFE0F`,
|
|
153
|
+
`continuity`,
|
|
154
|
+
continuityKey,
|
|
155
|
+
`has no optimistic updates to deal with`
|
|
156
|
+
);
|
|
157
|
+
const continuityEpoch = getEpochNumberOfContinuity(continuityKey, store);
|
|
158
|
+
const isRoot = isRootStore(store);
|
|
159
|
+
if (isRoot && continuityEpoch === confirmed.epoch - 1) {
|
|
160
|
+
store.logger.info(
|
|
161
|
+
`\u2705`,
|
|
162
|
+
`continuity`,
|
|
163
|
+
continuityKey,
|
|
164
|
+
`integrating update #${confirmed.epoch} (${confirmed.key} ${confirmed.id})`
|
|
165
|
+
);
|
|
166
|
+
ingestTransactionUpdate(`newValue`, confirmed, store);
|
|
167
|
+
socket.emit(`ack:${continuityKey}`, confirmed.epoch);
|
|
168
|
+
setEpochNumberOfContinuity(continuityKey, confirmed.epoch, store);
|
|
169
|
+
} else if (isRoot && continuityEpoch !== undefined) {
|
|
170
|
+
store.logger.info(
|
|
171
|
+
`\u{1F9D1}\u200D\u2696\uFE0F`,
|
|
172
|
+
`continuity`,
|
|
173
|
+
continuityKey,
|
|
174
|
+
`received update #${confirmed.epoch} but still waiting for update #${continuityEpoch + 1}`,
|
|
175
|
+
{
|
|
176
|
+
clientEpoch: continuityEpoch,
|
|
177
|
+
serverEpoch: confirmed.epoch
|
|
178
|
+
}
|
|
179
|
+
);
|
|
180
|
+
const confirmedUpdateIsAlreadyEnqueued = confirmedUpdates.some(
|
|
181
|
+
(update) => update.epoch === confirmed.epoch
|
|
182
|
+
);
|
|
183
|
+
if (confirmedUpdateIsAlreadyEnqueued) {
|
|
184
|
+
store.logger.info(
|
|
185
|
+
`\u{1F44D}`,
|
|
186
|
+
`continuity`,
|
|
187
|
+
continuityKey,
|
|
188
|
+
`confirmed update #${confirmed.epoch} is already enqueued`
|
|
189
|
+
);
|
|
190
|
+
} else {
|
|
191
|
+
store.logger.info(
|
|
192
|
+
`\u{1F448}`,
|
|
193
|
+
`continuity`,
|
|
194
|
+
continuityKey,
|
|
195
|
+
`pushing confirmed update #${confirmed.epoch} to queue`
|
|
196
|
+
);
|
|
197
|
+
setIntoStore(store, confirmedUpdateQueue, (queue) => {
|
|
198
|
+
queue.push(confirmed);
|
|
199
|
+
queue.sort((a, b) => a.epoch - b.epoch);
|
|
200
|
+
return queue;
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
};
|
|
206
|
+
function useConcealState(store) {
|
|
207
|
+
return (concealed) => {
|
|
208
|
+
for (const token of concealed) {
|
|
209
|
+
disposeAtom(token, store);
|
|
210
|
+
}
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
function useRevealState(store) {
|
|
214
|
+
return (revealed) => {
|
|
215
|
+
let i = 0;
|
|
216
|
+
let k;
|
|
217
|
+
let v;
|
|
218
|
+
for (const x of revealed) {
|
|
219
|
+
if (i % 2 === 0) {
|
|
220
|
+
k = x;
|
|
221
|
+
} else {
|
|
222
|
+
v = x;
|
|
223
|
+
setIntoStore(store, k, v);
|
|
224
|
+
}
|
|
225
|
+
i++;
|
|
226
|
+
}
|
|
227
|
+
};
|
|
228
|
+
}
|
|
9
229
|
function pullAtom(token, socket, store) {
|
|
10
230
|
const setServedValue = (data) => {
|
|
11
231
|
setIntoStore(store, token, data);
|
|
@@ -158,7 +378,7 @@ function pushState(token, socket, store) {
|
|
|
158
378
|
}
|
|
159
379
|
var myIdState__INTERNAL = AtomIO.atom({
|
|
160
380
|
key: `mySocketId__INTERNAL`,
|
|
161
|
-
default:
|
|
381
|
+
default: undefined
|
|
162
382
|
});
|
|
163
383
|
var myIdState = AtomIO.selector({
|
|
164
384
|
key: `mySocketId`,
|
|
@@ -169,11 +389,11 @@ var myUsernameState = AtomIO.atom({
|
|
|
169
389
|
default: null,
|
|
170
390
|
effects: typeof window === `undefined` ? [] : [persistSync(window.localStorage, JSON, `myUsername`)]
|
|
171
391
|
});
|
|
172
|
-
var
|
|
392
|
+
var optimisticUpdateQueue2 = AtomIO.atom({
|
|
173
393
|
key: `updateQueue`,
|
|
174
394
|
default: []
|
|
175
395
|
});
|
|
176
|
-
var
|
|
396
|
+
var confirmedUpdateQueue2 = AtomIO.atom(
|
|
177
397
|
{
|
|
178
398
|
key: `serverConfirmedUpdateQueue`,
|
|
179
399
|
default: []
|
|
@@ -194,8 +414,8 @@ function serverAction(token, socket, store) {
|
|
|
194
414
|
}
|
|
195
415
|
function syncContinuity(continuity, socket, store) {
|
|
196
416
|
const continuityKey = continuity.key;
|
|
197
|
-
const optimisticUpdates = getFromStore(store, optimisticUpdateQueue
|
|
198
|
-
const confirmedUpdates = getFromStore(store, confirmedUpdateQueue
|
|
417
|
+
const optimisticUpdates = getFromStore(store, optimisticUpdateQueue);
|
|
418
|
+
const confirmedUpdates = getFromStore(store, confirmedUpdateQueue);
|
|
199
419
|
const initializeContinuity = (epoch, payload) => {
|
|
200
420
|
socket.off(`continuity-init:${continuityKey}`, initializeContinuity);
|
|
201
421
|
let i = 0;
|
|
@@ -217,203 +437,13 @@ function syncContinuity(continuity, socket, store) {
|
|
|
217
437
|
};
|
|
218
438
|
socket.off(`continuity-init:${continuityKey}`);
|
|
219
439
|
socket.on(`continuity-init:${continuityKey}`, initializeContinuity);
|
|
220
|
-
const registerAndAttemptConfirmedUpdate = (
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
);
|
|
228
|
-
setIntoStore(store, optimisticUpdateQueue$1, (queue) => {
|
|
229
|
-
queue.shift();
|
|
230
|
-
return queue;
|
|
231
|
-
});
|
|
232
|
-
if (optimisticUpdate.id === confirmedUpdate.id) {
|
|
233
|
-
const clientResult = JSON.stringify(optimisticUpdate.updates);
|
|
234
|
-
const serverResult = JSON.stringify(confirmedUpdate.updates);
|
|
235
|
-
if (clientResult === serverResult) {
|
|
236
|
-
store.logger.info(
|
|
237
|
-
`\u2705`,
|
|
238
|
-
`continuity`,
|
|
239
|
-
continuityKey,
|
|
240
|
-
`results for ${optimisticUpdate.id} match between client and server`
|
|
241
|
-
);
|
|
242
|
-
socket.emit(`ack:${continuityKey}`, confirmedUpdate.epoch);
|
|
243
|
-
return;
|
|
244
|
-
}
|
|
245
|
-
} else {
|
|
246
|
-
store.logger.info(
|
|
247
|
-
`\u274C`,
|
|
248
|
-
`continuity`,
|
|
249
|
-
continuityKey,
|
|
250
|
-
`thought update #${confirmedUpdate.epoch} was ${optimisticUpdate.key}:${optimisticUpdate.id}, but it was actually ${confirmedUpdate.key}:${confirmedUpdate.id}`
|
|
251
|
-
);
|
|
252
|
-
}
|
|
253
|
-
store.logger.info(
|
|
254
|
-
`\u{1F9D1}\u200D\u2696\uFE0F`,
|
|
255
|
-
`continuity`,
|
|
256
|
-
continuityKey,
|
|
257
|
-
`updates do not match`,
|
|
258
|
-
optimisticUpdate,
|
|
259
|
-
confirmedUpdate
|
|
260
|
-
);
|
|
261
|
-
const reversedOptimisticUpdates = optimisticUpdates.toReversed();
|
|
262
|
-
for (const subsequentOptimistic of reversedOptimisticUpdates) {
|
|
263
|
-
ingestTransactionUpdate(`oldValue`, subsequentOptimistic, store);
|
|
264
|
-
}
|
|
265
|
-
store.logger.info(
|
|
266
|
-
`\u23EA`,
|
|
267
|
-
`continuity`,
|
|
268
|
-
continuityKey,
|
|
269
|
-
`undid optimistic updates:`,
|
|
270
|
-
reversedOptimisticUpdates
|
|
271
|
-
);
|
|
272
|
-
ingestTransactionUpdate(`oldValue`, optimisticUpdate, store);
|
|
273
|
-
store.logger.info(
|
|
274
|
-
`\u23EA`,
|
|
275
|
-
`continuity`,
|
|
276
|
-
continuityKey,
|
|
277
|
-
`undid zeroth optimistic update`,
|
|
278
|
-
optimisticUpdate
|
|
279
|
-
);
|
|
280
|
-
ingestTransactionUpdate(`newValue`, confirmedUpdate, store);
|
|
281
|
-
store.logger.info(
|
|
282
|
-
`\u23E9`,
|
|
283
|
-
`continuity`,
|
|
284
|
-
continuityKey,
|
|
285
|
-
`applied confirmed update`,
|
|
286
|
-
confirmedUpdate
|
|
287
|
-
);
|
|
288
|
-
socket.emit(`ack:${continuityKey}`, confirmedUpdate.epoch);
|
|
289
|
-
for (const subsequentOptimistic of optimisticUpdates) {
|
|
290
|
-
const token = {
|
|
291
|
-
type: `transaction`,
|
|
292
|
-
key: subsequentOptimistic.key
|
|
293
|
-
};
|
|
294
|
-
const { id, params } = subsequentOptimistic;
|
|
295
|
-
actUponStore(token, id, store)(...params);
|
|
296
|
-
}
|
|
297
|
-
store.logger.info(
|
|
298
|
-
`\u23E9`,
|
|
299
|
-
`continuity`,
|
|
300
|
-
continuityKey,
|
|
301
|
-
`reapplied subsequent optimistic updates:`,
|
|
302
|
-
optimisticUpdates
|
|
303
|
-
);
|
|
304
|
-
}
|
|
305
|
-
store.logger.info(
|
|
306
|
-
`\u{1F9D1}\u200D\u2696\uFE0F`,
|
|
307
|
-
`continuity`,
|
|
308
|
-
continuityKey,
|
|
309
|
-
`integrating confirmed update`,
|
|
310
|
-
{ confirmedUpdate: confirmed, confirmedUpdates, optimisticUpdates }
|
|
311
|
-
);
|
|
312
|
-
const zerothOptimisticUpdate = optimisticUpdates[0];
|
|
313
|
-
if (zerothOptimisticUpdate) {
|
|
314
|
-
store.logger.info(
|
|
315
|
-
`\u{1F9D1}\u200D\u2696\uFE0F`,
|
|
316
|
-
`continuity`,
|
|
317
|
-
continuityKey,
|
|
318
|
-
`has optimistic updates to reconcile`
|
|
319
|
-
);
|
|
320
|
-
if (confirmed.epoch === zerothOptimisticUpdate.epoch) {
|
|
321
|
-
store.logger.info(
|
|
322
|
-
`\u{1F9D1}\u200D\u2696\uFE0F`,
|
|
323
|
-
`continuity`,
|
|
324
|
-
continuityKey,
|
|
325
|
-
`epoch of confirmed update #${confirmed.epoch} matches zeroth optimistic update`
|
|
326
|
-
);
|
|
327
|
-
reconcileEpoch(zerothOptimisticUpdate, confirmed);
|
|
328
|
-
for (const nextConfirmed of confirmedUpdates) {
|
|
329
|
-
const nextOptimistic = optimisticUpdates[0];
|
|
330
|
-
if (nextConfirmed.epoch === nextOptimistic?.epoch) {
|
|
331
|
-
reconcileEpoch(nextOptimistic, nextConfirmed);
|
|
332
|
-
} else {
|
|
333
|
-
break;
|
|
334
|
-
}
|
|
335
|
-
}
|
|
336
|
-
} else {
|
|
337
|
-
store.logger.info(
|
|
338
|
-
`\u{1F9D1}\u200D\u2696\uFE0F`,
|
|
339
|
-
`continuity`,
|
|
340
|
-
continuityKey,
|
|
341
|
-
`epoch of confirmed update #${confirmed.epoch} does not match zeroth optimistic update #${zerothOptimisticUpdate.epoch}`
|
|
342
|
-
);
|
|
343
|
-
const confirmedUpdateIsAlreadyEnqueued = confirmedUpdates.some(
|
|
344
|
-
(update) => update.epoch === confirmed.epoch
|
|
345
|
-
);
|
|
346
|
-
if (!confirmedUpdateIsAlreadyEnqueued) {
|
|
347
|
-
store.logger.info(
|
|
348
|
-
`\u{1F448}`,
|
|
349
|
-
`continuity`,
|
|
350
|
-
continuityKey,
|
|
351
|
-
`pushing confirmed update to queue`,
|
|
352
|
-
confirmed
|
|
353
|
-
);
|
|
354
|
-
setIntoStore(store, confirmedUpdateQueue$1, (queue) => {
|
|
355
|
-
queue.push(confirmed);
|
|
356
|
-
queue.sort((a, b) => a.epoch - b.epoch);
|
|
357
|
-
return queue;
|
|
358
|
-
});
|
|
359
|
-
}
|
|
360
|
-
}
|
|
361
|
-
} else {
|
|
362
|
-
store.logger.info(
|
|
363
|
-
`\u{1F9D1}\u200D\u2696\uFE0F`,
|
|
364
|
-
`continuity`,
|
|
365
|
-
continuityKey,
|
|
366
|
-
`has no optimistic updates to deal with`
|
|
367
|
-
);
|
|
368
|
-
const continuityEpoch = getEpochNumberOfContinuity(continuityKey, store);
|
|
369
|
-
const isRoot = isRootStore(store);
|
|
370
|
-
if (isRoot && continuityEpoch === confirmed.epoch - 1) {
|
|
371
|
-
store.logger.info(
|
|
372
|
-
`\u2705`,
|
|
373
|
-
`continuity`,
|
|
374
|
-
continuityKey,
|
|
375
|
-
`integrating update #${confirmed.epoch} (${confirmed.key} ${confirmed.id})`
|
|
376
|
-
);
|
|
377
|
-
ingestTransactionUpdate(`newValue`, confirmed, store);
|
|
378
|
-
socket.emit(`ack:${continuityKey}`, confirmed.epoch);
|
|
379
|
-
setEpochNumberOfContinuity(continuityKey, confirmed.epoch, store);
|
|
380
|
-
} else if (isRoot && continuityEpoch !== void 0) {
|
|
381
|
-
store.logger.info(
|
|
382
|
-
`\u{1F9D1}\u200D\u2696\uFE0F`,
|
|
383
|
-
`continuity`,
|
|
384
|
-
continuityKey,
|
|
385
|
-
`received update #${confirmed.epoch} but still waiting for update #${continuityEpoch + 1}`,
|
|
386
|
-
{
|
|
387
|
-
clientEpoch: continuityEpoch,
|
|
388
|
-
serverEpoch: confirmed.epoch
|
|
389
|
-
}
|
|
390
|
-
);
|
|
391
|
-
const confirmedUpdateIsAlreadyEnqueued = confirmedUpdates.some(
|
|
392
|
-
(update) => update.epoch === confirmed.epoch
|
|
393
|
-
);
|
|
394
|
-
if (confirmedUpdateIsAlreadyEnqueued) {
|
|
395
|
-
store.logger.info(
|
|
396
|
-
`\u{1F44D}`,
|
|
397
|
-
`continuity`,
|
|
398
|
-
continuityKey,
|
|
399
|
-
`confirmed update #${confirmed.epoch} is already enqueued`
|
|
400
|
-
);
|
|
401
|
-
} else {
|
|
402
|
-
store.logger.info(
|
|
403
|
-
`\u{1F448}`,
|
|
404
|
-
`continuity`,
|
|
405
|
-
continuityKey,
|
|
406
|
-
`pushing confirmed update #${confirmed.epoch} to queue`
|
|
407
|
-
);
|
|
408
|
-
setIntoStore(store, confirmedUpdateQueue$1, (queue) => {
|
|
409
|
-
queue.push(confirmed);
|
|
410
|
-
queue.sort((a, b) => a.epoch - b.epoch);
|
|
411
|
-
return queue;
|
|
412
|
-
});
|
|
413
|
-
}
|
|
414
|
-
}
|
|
415
|
-
}
|
|
416
|
-
};
|
|
440
|
+
const registerAndAttemptConfirmedUpdate = useRegisterAndAttemptConfirmedUpdate(
|
|
441
|
+
store,
|
|
442
|
+
continuityKey,
|
|
443
|
+
socket,
|
|
444
|
+
optimisticUpdates,
|
|
445
|
+
confirmedUpdates
|
|
446
|
+
);
|
|
417
447
|
socket.off(`tx-new:${continuityKey}`);
|
|
418
448
|
socket.on(`tx-new:${continuityKey}`, registerAndAttemptConfirmedUpdate);
|
|
419
449
|
const unsubscribeFunctions = continuity.actions.map((transaction) => {
|
|
@@ -437,7 +467,7 @@ function syncContinuity(continuity, socket, store) {
|
|
|
437
467
|
continuityKey,
|
|
438
468
|
`enqueuing new optimistic update`
|
|
439
469
|
);
|
|
440
|
-
setIntoStore(store, optimisticUpdateQueue
|
|
470
|
+
setIntoStore(store, optimisticUpdateQueue, (queue) => {
|
|
441
471
|
queue.push(clientUpdate);
|
|
442
472
|
queue.sort((a, b) => a.epoch - b.epoch);
|
|
443
473
|
return queue;
|
|
@@ -449,7 +479,7 @@ function syncContinuity(continuity, socket, store) {
|
|
|
449
479
|
continuityKey,
|
|
450
480
|
`replacing existing optimistic update at index ${optimisticUpdateIndex}`
|
|
451
481
|
);
|
|
452
|
-
setIntoStore(store, optimisticUpdateQueue
|
|
482
|
+
setIntoStore(store, optimisticUpdateQueue, (queue) => {
|
|
453
483
|
queue[optimisticUpdateIndex] = clientUpdate;
|
|
454
484
|
return queue;
|
|
455
485
|
});
|
|
@@ -465,28 +495,10 @@ function syncContinuity(continuity, socket, store) {
|
|
|
465
495
|
);
|
|
466
496
|
return unsubscribeFromTransactionUpdates;
|
|
467
497
|
});
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
for (const x of revealed) {
|
|
473
|
-
if (i % 2 === 0) {
|
|
474
|
-
k = x;
|
|
475
|
-
} else {
|
|
476
|
-
v = x;
|
|
477
|
-
upsertState(k, v, store);
|
|
478
|
-
}
|
|
479
|
-
i++;
|
|
480
|
-
}
|
|
481
|
-
});
|
|
482
|
-
socket.on(
|
|
483
|
-
`conceal:${continuityKey}`,
|
|
484
|
-
(concealed) => {
|
|
485
|
-
for (const token of concealed) {
|
|
486
|
-
disposeAtom(token, store);
|
|
487
|
-
}
|
|
488
|
-
}
|
|
489
|
-
);
|
|
498
|
+
const revealState = useRevealState(store);
|
|
499
|
+
const concealState = useConcealState(store);
|
|
500
|
+
socket.on(`reveal:${continuityKey}`, revealState);
|
|
501
|
+
socket.on(`conceal:${continuityKey}`, concealState);
|
|
490
502
|
socket.emit(`get:${continuityKey}`);
|
|
491
503
|
return () => {
|
|
492
504
|
socket.off(`continuity-init:${continuityKey}`);
|
|
@@ -494,20 +506,5 @@ function syncContinuity(continuity, socket, store) {
|
|
|
494
506
|
for (const unsubscribe of unsubscribeFunctions) unsubscribe();
|
|
495
507
|
};
|
|
496
508
|
}
|
|
497
|
-
function upsertState(store, token, value) {
|
|
498
|
-
if (token.family) {
|
|
499
|
-
const family = store.families.get(token.family.key);
|
|
500
|
-
if (family) {
|
|
501
|
-
const molecule = store.molecules.get(token.family.subKey);
|
|
502
|
-
if (molecule) {
|
|
503
|
-
growMoleculeInStore(molecule, family, store);
|
|
504
|
-
} else if (store.config.lifespan === `immortal`) {
|
|
505
|
-
throw new Error(`No molecule found for key "${token.family.subKey}"`);
|
|
506
|
-
}
|
|
507
|
-
initFamilyMemberInStore(store, family, parseJson(token.family.subKey));
|
|
508
|
-
}
|
|
509
|
-
}
|
|
510
|
-
setIntoStore(store, token, value);
|
|
511
|
-
}
|
|
512
509
|
|
|
513
|
-
export { confirmedUpdateQueue, myIdState, myIdState__INTERNAL, myUsernameState, optimisticUpdateQueue, pullAtom, pullAtomFamilyMember, pullMutableAtom, pullMutableAtomFamilyMember, pullSelector, pullSelectorFamilyMember, pushState, serverAction, syncContinuity };
|
|
510
|
+
export { confirmedUpdateQueue2 as confirmedUpdateQueue, myIdState, myIdState__INTERNAL, myUsernameState, optimisticUpdateQueue2 as optimisticUpdateQueue, pullAtom, pullAtomFamilyMember, pullMutableAtom, pullMutableAtomFamilyMember, pullSelector, pullSelectorFamilyMember, pushState, serverAction, syncContinuity, useConcealState, useRegisterAndAttemptConfirmedUpdate, useRevealState };
|