atom.io 0.16.2 → 0.17.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/dist/chunk-H4Q5FTPZ.js +11 -0
- package/dist/chunk-H4Q5FTPZ.js.map +1 -0
- package/dist/index.cjs +35 -60
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +8 -8
- package/dist/index.js +12 -36
- package/dist/index.js.map +1 -1
- package/internal/dist/index.cjs +268 -195
- package/internal/dist/index.cjs.map +1 -1
- package/internal/dist/index.d.ts +36 -11
- package/internal/dist/index.js +258 -195
- package/internal/dist/index.js.map +1 -1
- package/internal/src/atom/create-regular-atom.ts +2 -3
- package/internal/src/families/find-in-store.ts +74 -0
- package/internal/src/families/index.ts +1 -0
- package/internal/src/get-state/get-from-store.ts +14 -0
- package/internal/src/get-state/index.ts +2 -0
- package/internal/src/{read-or-compute-value.ts → get-state/read-or-compute-value.ts} +3 -3
- package/internal/src/index.ts +1 -1
- package/internal/src/ingest-updates/ingest-atom-update.ts +2 -2
- package/internal/src/ingest-updates/ingest-transaction-update.ts +1 -0
- package/internal/src/mutable/create-mutable-atom.ts +3 -4
- package/internal/src/mutable/tracker.ts +43 -35
- package/internal/src/mutable/transceiver.ts +1 -1
- package/internal/src/not-found-error.ts +14 -3
- package/internal/src/operation.ts +2 -1
- package/internal/src/selector/create-writable-selector.ts +2 -1
- package/internal/src/selector/register-selector.ts +6 -5
- package/internal/src/set-state/index.ts +1 -0
- package/internal/src/set-state/set-atom.ts +17 -3
- package/internal/src/set-state/set-into-store.ts +24 -0
- package/internal/src/set-state/stow-update.ts +2 -4
- package/internal/src/store/store.ts +13 -4
- package/internal/src/subscribe/subscribe-to-root-atoms.ts +1 -1
- package/internal/src/timeline/add-atom-to-timeline.ts +5 -5
- package/internal/src/transaction/abort-transaction.ts +2 -1
- package/internal/src/transaction/apply-transaction.ts +5 -3
- package/internal/src/transaction/build-transaction.ts +20 -11
- package/internal/src/transaction/create-transaction.ts +2 -3
- package/internal/src/transaction/index.ts +3 -2
- package/internal/src/transaction/is-root-store.ts +23 -0
- package/package.json +10 -10
- package/react/dist/index.cjs +27 -21
- package/react/dist/index.cjs.map +1 -1
- package/react/dist/index.d.ts +8 -2
- package/react/dist/index.js +28 -22
- package/react/dist/index.js.map +1 -1
- package/react/src/index.ts +4 -1
- package/react/src/use-i.ts +35 -0
- package/react/src/use-json.ts +38 -0
- package/react/src/use-o.ts +33 -0
- package/react/src/use-tl.ts +45 -0
- package/realtime-client/dist/index.cjs +167 -64
- package/realtime-client/dist/index.cjs.map +1 -1
- package/realtime-client/dist/index.d.ts +10 -6
- package/realtime-client/dist/index.js +158 -63
- package/realtime-client/dist/index.js.map +1 -1
- package/realtime-client/src/index.ts +2 -1
- package/realtime-client/src/pull-family-member.ts +3 -3
- package/realtime-client/src/pull-mutable-family-member.ts +4 -4
- package/realtime-client/src/pull-mutable.ts +4 -4
- package/realtime-client/src/pull-state.ts +7 -6
- package/realtime-client/src/{realtime-client-store.ts → realtime-client-stores/client-main-store.ts} +0 -8
- package/realtime-client/src/realtime-client-stores/client-sync-store.ts +15 -0
- package/realtime-client/src/realtime-client-stores/index.ts +2 -0
- package/realtime-client/src/sync-server-action.ts +134 -40
- package/realtime-client/src/sync-state.ts +19 -0
- package/realtime-react/dist/index.cjs +43 -26
- package/realtime-react/dist/index.cjs.map +1 -1
- package/realtime-react/dist/index.d.ts +3 -1
- package/realtime-react/dist/index.js +41 -25
- package/realtime-react/dist/index.js.map +1 -1
- package/realtime-react/src/index.ts +1 -0
- package/realtime-react/src/on-mount.ts +3 -21
- package/realtime-react/src/use-realtime-service.ts +1 -1
- package/realtime-react/src/use-single-effect.ts +29 -0
- package/realtime-react/src/use-sync-server-action.ts +4 -7
- package/realtime-react/src/use-sync.ts +17 -0
- package/realtime-server/dist/index.cjs +239 -56
- package/realtime-server/dist/index.cjs.map +1 -1
- package/realtime-server/dist/index.d.ts +140 -9
- package/realtime-server/dist/index.js +228 -58
- package/realtime-server/dist/index.js.map +1 -1
- package/realtime-server/src/index.ts +2 -0
- package/realtime-server/src/realtime-action-synchronizer.ts +95 -14
- package/realtime-server/src/realtime-family-provider.ts +11 -6
- package/realtime-server/src/realtime-mutable-family-provider.ts +8 -6
- package/realtime-server/src/realtime-mutable-provider.ts +3 -2
- package/realtime-server/src/realtime-server-stores/index.ts +2 -0
- package/realtime-server/src/realtime-server-stores/server-sync-store.ts +115 -0
- package/realtime-server/src/realtime-server-stores/server-user-store.ts +45 -0
- package/realtime-server/src/realtime-state-provider.ts +18 -11
- package/realtime-server/src/realtime-state-receiver.ts +2 -2
- package/realtime-server/src/realtime-state-synchronizer.ts +23 -0
- package/realtime-testing/dist/index.cjs +65 -26
- package/realtime-testing/dist/index.cjs.map +1 -1
- package/realtime-testing/dist/index.d.ts +11 -7
- package/realtime-testing/dist/index.js +64 -26
- package/realtime-testing/dist/index.js.map +1 -1
- package/realtime-testing/src/setup-realtime-test.tsx +83 -43
- package/src/find-state.ts +8 -16
- package/src/get-state.ts +2 -11
- package/src/logger.ts +1 -0
- package/src/set-state.ts +1 -13
- package/src/silo.ts +7 -3
- package/src/transaction.ts +3 -3
- package/react/src/store-hooks.ts +0 -87
- package/realtime-server/src/realtime-server-store.ts +0 -39
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { redo, undo } from "atom.io"
|
|
2
|
+
import type { TimelineToken } from "atom.io"
|
|
3
|
+
import { subscribeToTimeline, withdraw } from "atom.io/internal"
|
|
4
|
+
import * as React from "react"
|
|
5
|
+
|
|
6
|
+
import { StoreContext } from "./store-context"
|
|
7
|
+
|
|
8
|
+
export type TimelineMeta = {
|
|
9
|
+
at: number
|
|
10
|
+
length: number
|
|
11
|
+
undo: () => void
|
|
12
|
+
redo: () => void
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function useTL(token: TimelineToken<any>): TimelineMeta {
|
|
16
|
+
const store = React.useContext(StoreContext)
|
|
17
|
+
const id = React.useId()
|
|
18
|
+
const timeline = withdraw(token, store)
|
|
19
|
+
const tokenRef = React.useRef(token)
|
|
20
|
+
const rebuildMeta = () => {
|
|
21
|
+
return {
|
|
22
|
+
at: timeline?.at ?? NaN,
|
|
23
|
+
length: timeline?.history.length ?? NaN,
|
|
24
|
+
undo: () => undo(token),
|
|
25
|
+
redo: () => redo(token),
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
const meta = React.useRef<TimelineMeta>(rebuildMeta())
|
|
29
|
+
const retrieve = () => {
|
|
30
|
+
if (
|
|
31
|
+
meta.current.at !== timeline?.at ||
|
|
32
|
+
meta.current.length !== timeline?.history.length ||
|
|
33
|
+
tokenRef.current !== token
|
|
34
|
+
) {
|
|
35
|
+
tokenRef.current = token
|
|
36
|
+
meta.current = rebuildMeta()
|
|
37
|
+
}
|
|
38
|
+
return meta.current
|
|
39
|
+
}
|
|
40
|
+
return React.useSyncExternalStore<TimelineMeta>(
|
|
41
|
+
(dispatch) => subscribeToTimeline(token, dispatch, `use-tl:${id}`, store),
|
|
42
|
+
retrieve,
|
|
43
|
+
retrieve,
|
|
44
|
+
)
|
|
45
|
+
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var AtomIO = require('atom.io');
|
|
4
|
-
var json = require('atom.io/json');
|
|
5
3
|
var Internal3 = require('atom.io/internal');
|
|
4
|
+
var json = require('atom.io/json');
|
|
5
|
+
var AtomIO = require('atom.io');
|
|
6
6
|
|
|
7
7
|
function _interopNamespace(e) {
|
|
8
8
|
if (e && e.__esModule) return e;
|
|
@@ -22,29 +22,18 @@ function _interopNamespace(e) {
|
|
|
22
22
|
return Object.freeze(n);
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
var AtomIO__namespace = /*#__PURE__*/_interopNamespace(AtomIO);
|
|
26
25
|
var Internal3__namespace = /*#__PURE__*/_interopNamespace(Internal3);
|
|
26
|
+
var AtomIO__namespace = /*#__PURE__*/_interopNamespace(AtomIO);
|
|
27
27
|
|
|
28
|
-
// realtime-client/src/
|
|
29
|
-
var myIdState__INTERNAL = AtomIO__namespace.atom({
|
|
30
|
-
key: `myId__INTERNAL`,
|
|
31
|
-
default: void 0
|
|
32
|
-
});
|
|
33
|
-
var myIdState = AtomIO__namespace.selector({
|
|
34
|
-
key: `myId`,
|
|
35
|
-
get: ({ get }) => get(myIdState__INTERNAL)
|
|
36
|
-
});
|
|
37
|
-
var updateQueueAtoms = AtomIO__namespace.atomFamily({
|
|
38
|
-
key: `updateQueue`,
|
|
39
|
-
default: []
|
|
40
|
-
});
|
|
28
|
+
// realtime-client/src/pull-state.ts
|
|
41
29
|
function pullState(token, socket, store) {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
}
|
|
30
|
+
const setServedValue = (data) => {
|
|
31
|
+
Internal3.setIntoStore(token, data, store);
|
|
32
|
+
};
|
|
33
|
+
socket.on(`serve:${token.key}`, setServedValue);
|
|
45
34
|
socket.emit(`sub:${token.key}`);
|
|
46
35
|
return () => {
|
|
47
|
-
socket.off(`serve:${token.key}
|
|
36
|
+
socket.off(`serve:${token.key}`, setServedValue);
|
|
48
37
|
socket.emit(`unsub:${token.key}`);
|
|
49
38
|
};
|
|
50
39
|
}
|
|
@@ -57,7 +46,7 @@ function pullFamilyMember(token, socket, store) {
|
|
|
57
46
|
const { key: familyKey, subKey: serializedSubKey } = token.family;
|
|
58
47
|
const subKey = json.parseJson(serializedSubKey);
|
|
59
48
|
socket == null ? void 0 : socket.on(`serve:${token.key}`, (data) => {
|
|
60
|
-
|
|
49
|
+
Internal3.setIntoStore(token, data, store);
|
|
61
50
|
});
|
|
62
51
|
socket == null ? void 0 : socket.emit(`sub:${familyKey}`, subKey);
|
|
63
52
|
return () => {
|
|
@@ -69,12 +58,12 @@ function pullMutableState(token, socket, store) {
|
|
|
69
58
|
const jsonToken = Internal3.getJsonToken(token);
|
|
70
59
|
const updateToken = Internal3.getUpdateToken(token);
|
|
71
60
|
socket.on(`init:${token.key}`, (data) => {
|
|
72
|
-
|
|
61
|
+
Internal3.setIntoStore(jsonToken, data, store);
|
|
73
62
|
});
|
|
74
63
|
socket.on(
|
|
75
64
|
`next:${token.key}`,
|
|
76
65
|
(data) => {
|
|
77
|
-
|
|
66
|
+
Internal3.setIntoStore(updateToken, data, store);
|
|
78
67
|
}
|
|
79
68
|
);
|
|
80
69
|
socket.emit(`sub:${token.key}`);
|
|
@@ -94,13 +83,13 @@ function pullMutableFamilyMember(token, socket, store) {
|
|
|
94
83
|
const subKey = json.parseJson(serializedSubKey);
|
|
95
84
|
socket == null ? void 0 : socket.on(`init:${token.key}`, (data) => {
|
|
96
85
|
const jsonToken = Internal3.getJsonToken(token);
|
|
97
|
-
|
|
86
|
+
Internal3.setIntoStore(jsonToken, data, store);
|
|
98
87
|
});
|
|
99
88
|
socket == null ? void 0 : socket.on(
|
|
100
89
|
`next:${token.key}`,
|
|
101
90
|
(data) => {
|
|
102
91
|
const trackerToken = Internal3.getUpdateToken(token);
|
|
103
|
-
|
|
92
|
+
Internal3.setIntoStore(trackerToken, data, store);
|
|
104
93
|
}
|
|
105
94
|
);
|
|
106
95
|
socket == null ? void 0 : socket.emit(`sub:${familyKey}`, subKey);
|
|
@@ -137,63 +126,165 @@ function serverAction(token, socket, store) {
|
|
|
137
126
|
unsubscribeFromLocalUpdates();
|
|
138
127
|
};
|
|
139
128
|
}
|
|
140
|
-
|
|
141
|
-
|
|
129
|
+
var myIdState__INTERNAL = AtomIO__namespace.atom({
|
|
130
|
+
key: `myId__INTERNAL`,
|
|
131
|
+
default: void 0
|
|
132
|
+
});
|
|
133
|
+
var myIdState = AtomIO__namespace.selector({
|
|
134
|
+
key: `myId`,
|
|
135
|
+
get: ({ get }) => get(myIdState__INTERNAL)
|
|
136
|
+
});
|
|
137
|
+
var optimisticUpdateQueueState = AtomIO__namespace.atom({
|
|
138
|
+
key: `updateQueue`,
|
|
139
|
+
default: []
|
|
140
|
+
});
|
|
141
|
+
var confirmedUpdateQueueState = AtomIO__namespace.atom({
|
|
142
|
+
key: `serverConfirmedUpdateQueue`,
|
|
143
|
+
default: []
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
// internal/src/transaction/is-root-store.ts
|
|
147
|
+
function isRootStore(store) {
|
|
148
|
+
return `epoch` in store.transactionMeta;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// realtime-client/src/sync-server-action.ts
|
|
152
|
+
function syncAction(token, socket, store) {
|
|
153
|
+
const optimisticQueue = Internal3__namespace.getFromStore(
|
|
154
|
+
optimisticUpdateQueueState,
|
|
155
|
+
store
|
|
156
|
+
);
|
|
157
|
+
const confirmedQueue = Internal3__namespace.getFromStore(confirmedUpdateQueueState, store);
|
|
142
158
|
const unsubscribeFromLocalUpdates = Internal3__namespace.subscribeToTransaction(
|
|
143
159
|
token,
|
|
144
160
|
(clientUpdate) => {
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
161
|
+
const optimisticUpdateQueueIndex = optimisticQueue.findIndex(
|
|
162
|
+
(update) => update.id === clientUpdate.id
|
|
163
|
+
);
|
|
164
|
+
if (optimisticUpdateQueueIndex === -1) {
|
|
165
|
+
Internal3__namespace.setIntoStore(
|
|
166
|
+
optimisticUpdateQueueState,
|
|
167
|
+
(queue) => {
|
|
168
|
+
queue.push(clientUpdate);
|
|
169
|
+
queue.sort((a, b) => a.epoch - b.epoch);
|
|
170
|
+
return queue;
|
|
171
|
+
},
|
|
172
|
+
store
|
|
173
|
+
);
|
|
174
|
+
socket.emit(`tx-run:${token.key}`, clientUpdate);
|
|
175
|
+
} else {
|
|
176
|
+
Internal3__namespace.setIntoStore(
|
|
177
|
+
optimisticUpdateQueueState,
|
|
178
|
+
(queue) => {
|
|
179
|
+
queue[optimisticUpdateQueueIndex] = clientUpdate;
|
|
180
|
+
return queue;
|
|
181
|
+
},
|
|
182
|
+
store
|
|
183
|
+
);
|
|
184
|
+
socket.emit(`tx-run:${token.key}`, clientUpdate);
|
|
185
|
+
}
|
|
150
186
|
},
|
|
151
|
-
`tx-run:${token.key}
|
|
187
|
+
`tx-run:${token.key}`,
|
|
152
188
|
store
|
|
153
189
|
);
|
|
154
|
-
const
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
store.logger.error(
|
|
170
|
-
`\u274C`,
|
|
190
|
+
const reconcileUpdates = (optimisticUpdate, confirmedUpdate) => {
|
|
191
|
+
Internal3__namespace.setIntoStore(
|
|
192
|
+
optimisticUpdateQueueState,
|
|
193
|
+
(queue) => {
|
|
194
|
+
queue.shift();
|
|
195
|
+
return queue;
|
|
196
|
+
},
|
|
197
|
+
store
|
|
198
|
+
);
|
|
199
|
+
if (optimisticUpdate.id === confirmedUpdate.id) {
|
|
200
|
+
const clientResult = JSON.stringify(optimisticUpdate.updates);
|
|
201
|
+
const serverResult = JSON.stringify(confirmedUpdate.updates);
|
|
202
|
+
if (clientResult === serverResult) {
|
|
203
|
+
store.logger.info(
|
|
204
|
+
`\u2705`,
|
|
171
205
|
`transaction`,
|
|
172
206
|
token.key,
|
|
173
|
-
`results
|
|
174
|
-
{ clientResult, serverResult }
|
|
207
|
+
`results for ${optimisticUpdate.id} match between client and server`
|
|
175
208
|
);
|
|
176
|
-
|
|
209
|
+
socket.emit(`tx-ack:${token.key}`, confirmedUpdate.epoch);
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
} else {
|
|
213
|
+
store.logger.info(
|
|
214
|
+
`\u274C`,
|
|
215
|
+
`transaction`,
|
|
216
|
+
token.key,
|
|
217
|
+
`${store.config.name} thought update #${confirmedUpdate.epoch} was ${optimisticUpdate.key}:${optimisticUpdate.id}, but it was actually ${confirmedUpdate.key}:${confirmedUpdate.id}`
|
|
218
|
+
);
|
|
219
|
+
}
|
|
220
|
+
for (const subsequentOptimistic of optimisticQueue.toReversed()) {
|
|
221
|
+
Internal3__namespace.ingestTransactionUpdate(`oldValue`, subsequentOptimistic, store);
|
|
222
|
+
}
|
|
223
|
+
Internal3__namespace.ingestTransactionUpdate(`oldValue`, optimisticUpdate, store);
|
|
224
|
+
Internal3__namespace.ingestTransactionUpdate(`newValue`, confirmedUpdate, store);
|
|
225
|
+
socket.emit(`tx-ack:${token.key}`, confirmedUpdate.epoch);
|
|
226
|
+
for (const subsequentOptimistic of optimisticQueue) {
|
|
227
|
+
const token2 = Object.assign(
|
|
228
|
+
{ type: `transaction` },
|
|
229
|
+
subsequentOptimistic
|
|
230
|
+
);
|
|
231
|
+
const { id, params } = subsequentOptimistic;
|
|
232
|
+
AtomIO__namespace.runTransaction(token2, id, store)(...params);
|
|
233
|
+
}
|
|
234
|
+
};
|
|
235
|
+
const registerAndAttemptConfirmedUpdate = (confirmedUpdate) => {
|
|
236
|
+
const zerothOptimisticUpdate = optimisticQueue[0];
|
|
237
|
+
if (zerothOptimisticUpdate) {
|
|
238
|
+
if (zerothOptimisticUpdate.epoch === confirmedUpdate.epoch) {
|
|
239
|
+
reconcileUpdates(zerothOptimisticUpdate, confirmedUpdate);
|
|
240
|
+
for (const nextConfirmed of confirmedQueue) {
|
|
241
|
+
const nextOptimistic = optimisticQueue[0];
|
|
242
|
+
if (nextConfirmed.epoch === nextOptimistic.epoch) {
|
|
243
|
+
reconcileUpdates(nextOptimistic, nextConfirmed);
|
|
244
|
+
} else {
|
|
245
|
+
break;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
177
248
|
} else {
|
|
249
|
+
const hasEnqueuedOptimisticUpdate = optimisticQueue.some(
|
|
250
|
+
(update) => update.epoch === confirmedUpdate.epoch
|
|
251
|
+
);
|
|
252
|
+
if (hasEnqueuedOptimisticUpdate) {
|
|
253
|
+
Internal3__namespace.setIntoStore(
|
|
254
|
+
confirmedUpdateQueueState,
|
|
255
|
+
(queue) => {
|
|
256
|
+
queue.push(confirmedUpdate);
|
|
257
|
+
queue.sort((a, b) => a.epoch - b.epoch);
|
|
258
|
+
return queue;
|
|
259
|
+
},
|
|
260
|
+
store
|
|
261
|
+
);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
} else {
|
|
265
|
+
if (isRootStore(store) && store.transactionMeta.epoch === confirmedUpdate.epoch - 1) {
|
|
266
|
+
Internal3__namespace.ingestTransactionUpdate(`newValue`, confirmedUpdate, store);
|
|
267
|
+
socket.emit(`tx-ack:${token.key}`, confirmedUpdate.epoch);
|
|
268
|
+
store.transactionMeta.epoch = confirmedUpdate.epoch;
|
|
269
|
+
} else if (isRootStore(store)) {
|
|
178
270
|
store.logger.info(
|
|
179
|
-
`\
|
|
271
|
+
`\u274C`,
|
|
180
272
|
`transaction`,
|
|
181
273
|
token.key,
|
|
182
|
-
`
|
|
274
|
+
`received out-of-order update from server`,
|
|
275
|
+
{
|
|
276
|
+
clientEpoch: store.transactionMeta.epoch,
|
|
277
|
+
serverEpoch: confirmedUpdate.epoch
|
|
278
|
+
}
|
|
183
279
|
);
|
|
184
280
|
}
|
|
185
|
-
AtomIO__namespace.setState(updateQueueState, (queue) => {
|
|
186
|
-
queue.shift();
|
|
187
|
-
return queue;
|
|
188
|
-
});
|
|
189
|
-
return;
|
|
190
281
|
}
|
|
191
|
-
Internal3__namespace.ingestTransactionUpdate(`newValue`, serverUpdate, store);
|
|
192
282
|
};
|
|
193
|
-
socket.
|
|
283
|
+
socket.off(`tx-new:${token.key}`, registerAndAttemptConfirmedUpdate);
|
|
284
|
+
socket.on(`tx-new:${token.key}`, registerAndAttemptConfirmedUpdate);
|
|
194
285
|
socket.emit(`tx-sub:${token.key}`);
|
|
195
286
|
const unsubscribeFromIncomingUpdates = () => {
|
|
196
|
-
socket.off(`tx-new:${token.key}`,
|
|
287
|
+
socket.off(`tx-new:${token.key}`, registerAndAttemptConfirmedUpdate);
|
|
197
288
|
socket.emit(`tx-unsub:${token.key}`);
|
|
198
289
|
};
|
|
199
290
|
return () => {
|
|
@@ -201,9 +292,21 @@ function syncAction(token, socket, updateQueue, store) {
|
|
|
201
292
|
unsubscribeFromIncomingUpdates();
|
|
202
293
|
};
|
|
203
294
|
}
|
|
295
|
+
function syncState(token, socket, store) {
|
|
296
|
+
const setServedValue = (data) => {
|
|
297
|
+
Internal3.setIntoStore(token, data, store);
|
|
298
|
+
};
|
|
299
|
+
socket.on(`value:${token.key}`, setServedValue);
|
|
300
|
+
socket.emit(`get:${token.key}`);
|
|
301
|
+
return () => {
|
|
302
|
+
socket.off(`value:${token.key}`, setServedValue);
|
|
303
|
+
};
|
|
304
|
+
}
|
|
204
305
|
|
|
306
|
+
exports.confirmedUpdateQueueState = confirmedUpdateQueueState;
|
|
205
307
|
exports.myIdState = myIdState;
|
|
206
308
|
exports.myIdState__INTERNAL = myIdState__INTERNAL;
|
|
309
|
+
exports.optimisticUpdateQueueState = optimisticUpdateQueueState;
|
|
207
310
|
exports.pullFamilyMember = pullFamilyMember;
|
|
208
311
|
exports.pullMutableFamilyMember = pullMutableFamilyMember;
|
|
209
312
|
exports.pullMutableState = pullMutableState;
|
|
@@ -211,6 +314,6 @@ exports.pullState = pullState;
|
|
|
211
314
|
exports.pushState = pushState;
|
|
212
315
|
exports.serverAction = serverAction;
|
|
213
316
|
exports.syncAction = syncAction;
|
|
214
|
-
exports.
|
|
317
|
+
exports.syncState = syncState;
|
|
215
318
|
//# sourceMappingURL=out.js.map
|
|
216
319
|
//# sourceMappingURL=index.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/realtime-client-store.ts","../src/pull-state.ts","../src/pull-family-member.ts","../src/pull-mutable.ts","../src/pull-mutable-family-member.ts","../src/push-state.ts","../src/server-action.ts","../src/sync-server-action.ts"],"names":["AtomIO","getJsonToken","getUpdateToken","parseJson","Internal"],"mappings":"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","sourcesContent":["import * as AtomIO from \"atom.io\"\n\nexport const myIdState__INTERNAL = AtomIO.atom<string | undefined>({\n\tkey: `myId__INTERNAL`,\n\tdefault: undefined,\n})\nexport const myIdState = AtomIO.selector<string | undefined>({\n\tkey: `myId`,\n\tget: ({ get }) => get(myIdState__INTERNAL),\n})\n\nexport const updateQueueAtoms = AtomIO.atomFamily<\n\tAtomIO.TransactionUpdate<any>[],\n\tAtomIO.TransactionToken<any>\n>({\n\tkey: `updateQueue`,\n\tdefault: [],\n})\n","import * as AtomIO from \"atom.io\"\nimport type { Store } from \"atom.io/internal\"\nimport type { Json } from \"atom.io/json\"\nimport type { Socket } from \"socket.io-client\"\n\nexport function pullState<J extends Json.Serializable>(\n\ttoken: AtomIO.WritableToken<J>,\n\tsocket: Socket,\n\tstore: Store,\n): () => void {\n\tsocket.on(`serve:${token.key}`, (data) => {\n\t\tAtomIO.setState(token, data, store)\n\t})\n\tsocket.emit(`sub:${token.key}`)\n\treturn () => {\n\t\tsocket.off(`serve:${token.key}`)\n\t\tsocket.emit(`unsub:${token.key}`)\n\t}\n}\n","import * as AtomIO from \"atom.io\"\nimport type { Store } from \"atom.io/internal\"\nimport type { Json } from \"atom.io/json\"\nimport { parseJson } from \"atom.io/json\"\nimport type { Socket } from \"socket.io-client\"\n\nexport function pullFamilyMember<J extends Json.Serializable>(\n\ttoken: AtomIO.WritableToken<J>,\n\tsocket: Socket,\n\tstore: Store,\n): () => void {\n\tif (!(`family` in token)) {\n\t\tconsole.error(`Token is not a family member:`, token)\n\t\treturn () => {}\n\t}\n\tconst { key: familyKey, subKey: serializedSubKey } = token.family\n\tconst subKey = parseJson(serializedSubKey)\n\tsocket?.on(`serve:${token.key}`, (data: J) => {\n\t\tAtomIO.setState(token, data, store)\n\t})\n\tsocket?.emit(`sub:${familyKey}`, subKey)\n\treturn () => {\n\t\tsocket?.off(`serve:${token.key}`)\n\t\tsocket?.emit(`unsub:${token.key}`)\n\t}\n}\n","import * as AtomIO from \"atom.io\"\nimport type { Store, Transceiver } from \"atom.io/internal\"\nimport { getJsonToken, getUpdateToken } from \"atom.io/internal\"\nimport type { Json } from \"atom.io/json\"\nimport type { Socket } from \"socket.io-client\"\n\nexport function pullMutableState<\n\tT extends Transceiver<any>,\n\tJ extends Json.Serializable,\n>(\n\ttoken: AtomIO.MutableAtomToken<T, J>,\n\tsocket: Socket,\n\tstore: Store,\n): () => void {\n\tconst jsonToken = getJsonToken(token)\n\tconst updateToken = getUpdateToken(token)\n\tsocket.on(`init:${token.key}`, (data: J) => {\n\t\tAtomIO.setState(jsonToken, data, store)\n\t})\n\tsocket.on(\n\t\t`next:${token.key}`,\n\t\t(data: T extends Transceiver<infer Update> ? Update : never) => {\n\t\t\tAtomIO.setState(updateToken, data, store)\n\t\t},\n\t)\n\tsocket.emit(`sub:${token.key}`)\n\treturn () => {\n\t\tsocket.off(`init:${token.key}`)\n\t\tsocket.off(`next:${token.key}`)\n\t\tsocket.emit(`unsub:${token.key}`)\n\t}\n}\n","import * as AtomIO from \"atom.io\"\nimport { getJsonToken, getUpdateToken } from \"atom.io/internal\"\nimport type { Store, Transceiver } from \"atom.io/internal\"\nimport { parseJson } from \"atom.io/json\"\nimport type { Json } from \"atom.io/json\"\nimport type { Socket } from \"socket.io-client\"\n\nexport function pullMutableFamilyMember<\n\tT extends Transceiver<any>,\n\tJ extends Json.Serializable,\n>(\n\ttoken: AtomIO.MutableAtomToken<T, J>,\n\tsocket: Socket,\n\tstore: Store,\n): () => void {\n\tif (!(`family` in token)) {\n\t\tconsole.error(`Token is not a family member:`, token)\n\t\treturn () => {}\n\t}\n\tconst { key: familyKey, subKey: serializedSubKey } = token.family\n\tconst subKey = parseJson(serializedSubKey)\n\tsocket?.on(`init:${token.key}`, (data: J) => {\n\t\tconst jsonToken = getJsonToken(token)\n\t\tAtomIO.setState(jsonToken, data, store)\n\t})\n\tsocket?.on(\n\t\t`next:${token.key}`,\n\t\t(data: T extends Transceiver<infer Signal> ? Signal : never) => {\n\t\t\tconst trackerToken = getUpdateToken(token)\n\t\t\tAtomIO.setState(trackerToken, data, store)\n\t\t},\n\t)\n\tsocket?.emit(`sub:${familyKey}`, subKey)\n\treturn () => {\n\t\tsocket?.off(`serve:${token.key}`)\n\t\tsocket?.emit(`unsub:${token.key}`)\n\t}\n}\n","import type * as AtomIO from \"atom.io\"\nimport * as Internal from \"atom.io/internal\"\nimport type { Json } from \"atom.io/json\"\nimport type { Socket } from \"socket.io-client\"\n\nexport function pushState<J extends Json.Serializable>(\n\ttoken: AtomIO.WritableToken<J>,\n\tsocket: Socket,\n\tstore: Internal.Store,\n): () => void {\n\tsocket.emit(`claim:${token.key}`)\n\tInternal.subscribeToState(\n\t\ttoken,\n\t\t({ newValue }) => {\n\t\t\tsocket.emit(`pub:${token.key}`, newValue)\n\t\t},\n\t\t`push`,\n\t\tstore,\n\t)\n\treturn () => {\n\t\tsocket.off(`pub:${token.key}`)\n\t\tsocket.emit(`unclaim:${token.key}`)\n\t}\n}\n","import type * as AtomIO from \"atom.io\"\nimport * as Internal from \"atom.io/internal\"\nimport type { Socket } from \"socket.io-client\"\n\nexport function serverAction<ƒ extends AtomIO.ƒn>(\n\ttoken: AtomIO.TransactionToken<ƒ>,\n\tsocket: Socket,\n\tstore: Internal.Store,\n): () => void {\n\tconst unsubscribeFromLocalUpdates = Internal.subscribeToTransaction(\n\t\ttoken,\n\t\t(clientUpdate) => {\n\t\t\tsocket.emit(`tx-run:${token.key}`, clientUpdate)\n\t\t},\n\t\t`tx-run:${token.key}:${socket.id}`,\n\t\tstore,\n\t)\n\n\treturn () => {\n\t\tunsubscribeFromLocalUpdates()\n\t}\n}\n","import * as AtomIO from \"atom.io\"\nimport * as Internal from \"atom.io/internal\"\nimport type { Socket } from \"socket.io-client\"\nimport { updateQueueAtoms } from \"./realtime-client-store\"\n\nexport function syncAction<ƒ extends AtomIO.ƒn>(\n\ttoken: AtomIO.TransactionToken<ƒ>,\n\tsocket: Socket,\n\tupdateQueue: AtomIO.TransactionUpdate<any>[],\n\tstore: Internal.Store,\n): () => void {\n\tconst updateQueueState = AtomIO.findState(updateQueueAtoms, token)\n\n\tconst unsubscribeFromLocalUpdates = Internal.subscribeToTransaction(\n\t\ttoken,\n\t\t(clientUpdate) => {\n\t\t\tAtomIO.setState(updateQueueState, (queue) => {\n\t\t\t\tqueue.push(clientUpdate)\n\t\t\t\treturn queue\n\t\t\t})\n\t\t\tsocket.emit(`tx-run:${token.key}`, clientUpdate)\n\t\t},\n\t\t`tx-run:${token.key}:${socket.id}`,\n\t\tstore,\n\t)\n\n\tconst applyIncomingUpdate = (serverUpdate: AtomIO.TransactionUpdate<ƒ>) => {\n\t\tconst clientUpdate = updateQueue[0]\n\t\tif (clientUpdate) {\n\t\t\tif (clientUpdate.id !== serverUpdate.id) {\n\t\t\t\tstore.logger.error(\n\t\t\t\t\t`❌`,\n\t\t\t\t\t`transaction`,\n\t\t\t\t\tserverUpdate.key,\n\t\t\t\t\t`did not match position 0 in queue of updates awaiting sync:`,\n\t\t\t\t\tupdateQueue,\n\t\t\t\t)\n\t\t\t}\n\t\t\tconst clientResult = JSON.stringify(clientUpdate)\n\t\t\tconst serverResult = JSON.stringify(serverUpdate)\n\t\t\tif (clientResult !== serverResult) {\n\t\t\t\tstore.logger.error(\n\t\t\t\t\t`❌`,\n\t\t\t\t\t`transaction`,\n\t\t\t\t\ttoken.key,\n\t\t\t\t\t`results do not match between client and server:`,\n\t\t\t\t\t{ clientResult, serverResult },\n\t\t\t\t)\n\t\t\t\tInternal.ingestTransactionUpdate(`oldValue`, clientUpdate, store)\n\t\t\t} else {\n\t\t\t\tstore.logger.info(\n\t\t\t\t\t`✅`,\n\t\t\t\t\t`transaction`,\n\t\t\t\t\ttoken.key,\n\t\t\t\t\t`results match between client and server`,\n\t\t\t\t)\n\t\t\t}\n\t\t\tAtomIO.setState(updateQueueState, (queue) => {\n\t\t\t\tqueue.shift()\n\t\t\t\treturn queue\n\t\t\t})\n\t\t\treturn\n\t\t}\n\t\tInternal.ingestTransactionUpdate(`newValue`, serverUpdate, store)\n\t}\n\tsocket.on(`tx-new:${token.key}`, applyIncomingUpdate)\n\tsocket.emit(`tx-sub:${token.key}`)\n\tconst unsubscribeFromIncomingUpdates = () => {\n\t\tsocket.off(`tx-new:${token.key}`, applyIncomingUpdate)\n\t\tsocket.emit(`tx-unsub:${token.key}`)\n\t}\n\treturn () => {\n\t\tunsubscribeFromLocalUpdates()\n\t\tunsubscribeFromIncomingUpdates()\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/pull-state.ts","../src/pull-family-member.ts","../src/pull-mutable.ts","../src/pull-mutable-family-member.ts","../src/push-state.ts","../src/server-action.ts","../src/realtime-client-stores/client-main-store.ts","../src/realtime-client-stores/client-sync-store.ts","../src/sync-server-action.ts","../../internal/src/transaction/is-root-store.ts","../src/sync-state.ts"],"names":["setIntoStore","getJsonToken","getUpdateToken","parseJson","Internal","AtomIO","token"],"mappings":"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","sourcesContent":["import type * as AtomIO from \"atom.io\"\nimport { type Store, setIntoStore } from \"atom.io/internal\"\nimport type { Json } from \"atom.io/json\"\nimport type { Socket } from \"socket.io-client\"\n\nexport function pullState<J extends Json.Serializable>(\n\ttoken: AtomIO.WritableToken<J>,\n\tsocket: Socket,\n\tstore: Store,\n): () => void {\n\tconst setServedValue = (data: J) => {\n\t\tsetIntoStore(token, data, store)\n\t}\n\tsocket.on(`serve:${token.key}`, setServedValue)\n\tsocket.emit(`sub:${token.key}`)\n\treturn () => {\n\t\tsocket.off(`serve:${token.key}`, setServedValue)\n\t\tsocket.emit(`unsub:${token.key}`)\n\t}\n}\n","import type * as AtomIO from \"atom.io\"\nimport { type Store, setIntoStore } from \"atom.io/internal\"\nimport type { Json } from \"atom.io/json\"\nimport { parseJson } from \"atom.io/json\"\nimport type { Socket } from \"socket.io-client\"\n\nexport function pullFamilyMember<J extends Json.Serializable>(\n\ttoken: AtomIO.WritableToken<J>,\n\tsocket: Socket,\n\tstore: Store,\n): () => void {\n\tif (!(`family` in token)) {\n\t\tconsole.error(`Token is not a family member:`, token)\n\t\treturn () => {}\n\t}\n\tconst { key: familyKey, subKey: serializedSubKey } = token.family\n\tconst subKey = parseJson(serializedSubKey)\n\tsocket?.on(`serve:${token.key}`, (data: J) => {\n\t\tsetIntoStore(token, data, store)\n\t})\n\tsocket?.emit(`sub:${familyKey}`, subKey)\n\treturn () => {\n\t\tsocket?.off(`serve:${token.key}`)\n\t\tsocket?.emit(`unsub:${token.key}`)\n\t}\n}\n","import type * as AtomIO from \"atom.io\"\nimport type { Store, Transceiver } from \"atom.io/internal\"\nimport { getJsonToken, getUpdateToken, setIntoStore } from \"atom.io/internal\"\nimport type { Json } from \"atom.io/json\"\nimport type { Socket } from \"socket.io-client\"\n\nexport function pullMutableState<\n\tT extends Transceiver<any>,\n\tJ extends Json.Serializable,\n>(\n\ttoken: AtomIO.MutableAtomToken<T, J>,\n\tsocket: Socket,\n\tstore: Store,\n): () => void {\n\tconst jsonToken = getJsonToken(token)\n\tconst updateToken = getUpdateToken(token)\n\tsocket.on(`init:${token.key}`, (data: J) => {\n\t\tsetIntoStore(jsonToken, data, store)\n\t})\n\tsocket.on(\n\t\t`next:${token.key}`,\n\t\t(data: T extends Transceiver<infer Update> ? Update : never) => {\n\t\t\tsetIntoStore(updateToken, data, store)\n\t\t},\n\t)\n\tsocket.emit(`sub:${token.key}`)\n\treturn () => {\n\t\tsocket.off(`init:${token.key}`)\n\t\tsocket.off(`next:${token.key}`)\n\t\tsocket.emit(`unsub:${token.key}`)\n\t}\n}\n","import type * as AtomIO from \"atom.io\"\nimport { getJsonToken, getUpdateToken, setIntoStore } from \"atom.io/internal\"\nimport type { Store, Transceiver } from \"atom.io/internal\"\nimport { parseJson } from \"atom.io/json\"\nimport type { Json } from \"atom.io/json\"\nimport type { Socket } from \"socket.io-client\"\n\nexport function pullMutableFamilyMember<\n\tT extends Transceiver<any>,\n\tJ extends Json.Serializable,\n>(\n\ttoken: AtomIO.MutableAtomToken<T, J>,\n\tsocket: Socket,\n\tstore: Store,\n): () => void {\n\tif (!(`family` in token)) {\n\t\tconsole.error(`Token is not a family member:`, token)\n\t\treturn () => {}\n\t}\n\tconst { key: familyKey, subKey: serializedSubKey } = token.family\n\tconst subKey = parseJson(serializedSubKey)\n\tsocket?.on(`init:${token.key}`, (data: J) => {\n\t\tconst jsonToken = getJsonToken(token)\n\t\tsetIntoStore(jsonToken, data, store)\n\t})\n\tsocket?.on(\n\t\t`next:${token.key}`,\n\t\t(data: T extends Transceiver<infer Signal> ? Signal : never) => {\n\t\t\tconst trackerToken = getUpdateToken(token)\n\t\t\tsetIntoStore(trackerToken, data, store)\n\t\t},\n\t)\n\tsocket?.emit(`sub:${familyKey}`, subKey)\n\treturn () => {\n\t\tsocket?.off(`serve:${token.key}`)\n\t\tsocket?.emit(`unsub:${token.key}`)\n\t}\n}\n","import type * as AtomIO from \"atom.io\"\nimport * as Internal from \"atom.io/internal\"\nimport type { Json } from \"atom.io/json\"\nimport type { Socket } from \"socket.io-client\"\n\nexport function pushState<J extends Json.Serializable>(\n\ttoken: AtomIO.WritableToken<J>,\n\tsocket: Socket,\n\tstore: Internal.Store,\n): () => void {\n\tsocket.emit(`claim:${token.key}`)\n\tInternal.subscribeToState(\n\t\ttoken,\n\t\t({ newValue }) => {\n\t\t\tsocket.emit(`pub:${token.key}`, newValue)\n\t\t},\n\t\t`push`,\n\t\tstore,\n\t)\n\treturn () => {\n\t\tsocket.off(`pub:${token.key}`)\n\t\tsocket.emit(`unclaim:${token.key}`)\n\t}\n}\n","import type * as AtomIO from \"atom.io\"\nimport * as Internal from \"atom.io/internal\"\nimport type { Socket } from \"socket.io-client\"\n\nexport function serverAction<ƒ extends AtomIO.ƒn>(\n\ttoken: AtomIO.TransactionToken<ƒ>,\n\tsocket: Socket,\n\tstore: Internal.Store,\n): () => void {\n\tconst unsubscribeFromLocalUpdates = Internal.subscribeToTransaction(\n\t\ttoken,\n\t\t(clientUpdate) => {\n\t\t\tsocket.emit(`tx-run:${token.key}`, clientUpdate)\n\t\t},\n\t\t`tx-run:${token.key}:${socket.id}`,\n\t\tstore,\n\t)\n\n\treturn () => {\n\t\tunsubscribeFromLocalUpdates()\n\t}\n}\n","import * as AtomIO from \"atom.io\"\n\nexport const myIdState__INTERNAL = AtomIO.atom<string | undefined>({\n\tkey: `myId__INTERNAL`,\n\tdefault: undefined,\n})\nexport const myIdState = AtomIO.selector<string | undefined>({\n\tkey: `myId`,\n\tget: ({ get }) => get(myIdState__INTERNAL),\n})\n","import * as AtomIO from \"atom.io\"\n\nexport const optimisticUpdateQueueState = AtomIO.atom<\n\tAtomIO.TransactionUpdate<any>[]\n>({\n\tkey: `updateQueue`,\n\tdefault: [],\n})\n\nexport const confirmedUpdateQueueState = AtomIO.atom<\n\tAtomIO.TransactionUpdate<any>[]\n>({\n\tkey: `serverConfirmedUpdateQueue`,\n\tdefault: [],\n})\n","import * as AtomIO from \"atom.io\"\nimport * as Internal from \"atom.io/internal\"\nimport type { Socket } from \"socket.io-client\"\n\nimport { isRootStore } from \"../../internal/src/transaction/is-root-store\"\nimport {\n\tconfirmedUpdateQueueState,\n\toptimisticUpdateQueueState,\n} from \"./realtime-client-stores\"\n\nexport function syncAction<ƒ extends AtomIO.ƒn>(\n\ttoken: AtomIO.TransactionToken<ƒ>,\n\tsocket: Socket,\n\tstore: Internal.Store,\n): () => void {\n\tconst optimisticQueue = Internal.getFromStore(\n\t\toptimisticUpdateQueueState,\n\t\tstore,\n\t)\n\tconst confirmedQueue = Internal.getFromStore(confirmedUpdateQueueState, store)\n\n\tconst unsubscribeFromLocalUpdates = Internal.subscribeToTransaction(\n\t\ttoken,\n\t\t(clientUpdate) => {\n\t\t\tconst optimisticUpdateQueueIndex = optimisticQueue.findIndex(\n\t\t\t\t(update) => update.id === clientUpdate.id,\n\t\t\t)\n\t\t\tif (optimisticUpdateQueueIndex === -1) {\n\t\t\t\tInternal.setIntoStore(\n\t\t\t\t\toptimisticUpdateQueueState,\n\t\t\t\t\t(queue) => {\n\t\t\t\t\t\tqueue.push(clientUpdate)\n\t\t\t\t\t\tqueue.sort((a, b) => a.epoch - b.epoch)\n\t\t\t\t\t\treturn queue\n\t\t\t\t\t},\n\t\t\t\t\tstore,\n\t\t\t\t)\n\t\t\t\tsocket.emit(`tx-run:${token.key}`, clientUpdate)\n\t\t\t} else {\n\t\t\t\tInternal.setIntoStore(\n\t\t\t\t\toptimisticUpdateQueueState,\n\t\t\t\t\t(queue) => {\n\t\t\t\t\t\tqueue[optimisticUpdateQueueIndex] = clientUpdate\n\t\t\t\t\t\treturn queue\n\t\t\t\t\t},\n\t\t\t\t\tstore,\n\t\t\t\t)\n\t\t\t\tsocket.emit(`tx-run:${token.key}`, clientUpdate)\n\t\t\t}\n\t\t},\n\t\t`tx-run:${token.key}`,\n\t\tstore,\n\t)\n\tconst reconcileUpdates = (\n\t\toptimisticUpdate: AtomIO.TransactionUpdate<ƒ>,\n\t\tconfirmedUpdate: AtomIO.TransactionUpdate<ƒ>,\n\t) => {\n\t\tInternal.setIntoStore(\n\t\t\toptimisticUpdateQueueState,\n\t\t\t(queue) => {\n\t\t\t\tqueue.shift()\n\t\t\t\treturn queue\n\t\t\t},\n\t\t\tstore,\n\t\t)\n\t\tif (optimisticUpdate.id === confirmedUpdate.id) {\n\t\t\tconst clientResult = JSON.stringify(optimisticUpdate.updates)\n\t\t\tconst serverResult = JSON.stringify(confirmedUpdate.updates)\n\t\t\tif (clientResult === serverResult) {\n\t\t\t\tstore.logger.info(\n\t\t\t\t\t`✅`,\n\t\t\t\t\t`transaction`,\n\t\t\t\t\ttoken.key,\n\t\t\t\t\t`results for ${optimisticUpdate.id} match between client and server`,\n\t\t\t\t)\n\t\t\t\tsocket.emit(`tx-ack:${token.key}`, confirmedUpdate.epoch)\n\t\t\t\treturn\n\t\t\t}\n\t\t} else {\n\t\t\t// id mismatch\n\t\t\tstore.logger.info(\n\t\t\t\t`❌`,\n\t\t\t\t`transaction`,\n\t\t\t\ttoken.key,\n\t\t\t\t`${store.config.name} thought update #${confirmedUpdate.epoch} was ${optimisticUpdate.key}:${optimisticUpdate.id}, but it was actually ${confirmedUpdate.key}:${confirmedUpdate.id}`,\n\t\t\t)\n\t\t}\n\t\tfor (const subsequentOptimistic of optimisticQueue.toReversed()) {\n\t\t\tInternal.ingestTransactionUpdate(`oldValue`, subsequentOptimistic, store)\n\t\t}\n\t\tInternal.ingestTransactionUpdate(`oldValue`, optimisticUpdate, store)\n\t\tInternal.ingestTransactionUpdate(`newValue`, confirmedUpdate, store)\n\t\tsocket.emit(`tx-ack:${token.key}`, confirmedUpdate.epoch)\n\t\tfor (const subsequentOptimistic of optimisticQueue) {\n\t\t\tconst token = Object.assign(\n\t\t\t\t{ type: `transaction` } as const,\n\t\t\t\tsubsequentOptimistic,\n\t\t\t)\n\t\t\tconst { id, params } = subsequentOptimistic\n\t\t\tAtomIO.runTransaction(token, id, store)(...params)\n\t\t}\n\t}\n\n\tconst registerAndAttemptConfirmedUpdate = (\n\t\tconfirmedUpdate: AtomIO.TransactionUpdate<ƒ>,\n\t) => {\n\t\tconst zerothOptimisticUpdate = optimisticQueue[0]\n\t\tif (zerothOptimisticUpdate) {\n\t\t\tif (zerothOptimisticUpdate.epoch === confirmedUpdate.epoch) {\n\t\t\t\treconcileUpdates(zerothOptimisticUpdate, confirmedUpdate)\n\t\t\t\tfor (const nextConfirmed of confirmedQueue) {\n\t\t\t\t\tconst nextOptimistic = optimisticQueue[0]\n\t\t\t\t\tif (nextConfirmed.epoch === nextOptimistic.epoch) {\n\t\t\t\t\t\treconcileUpdates(nextOptimistic, nextConfirmed)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// epoch mismatch\n\n\t\t\t\tconst hasEnqueuedOptimisticUpdate = optimisticQueue.some(\n\t\t\t\t\t(update) => update.epoch === confirmedUpdate.epoch,\n\t\t\t\t)\n\t\t\t\tif (hasEnqueuedOptimisticUpdate) {\n\t\t\t\t\tInternal.setIntoStore(\n\t\t\t\t\t\tconfirmedUpdateQueueState,\n\t\t\t\t\t\t(queue) => {\n\t\t\t\t\t\t\tqueue.push(confirmedUpdate)\n\t\t\t\t\t\t\tqueue.sort((a, b) => a.epoch - b.epoch)\n\t\t\t\t\t\t\treturn queue\n\t\t\t\t\t\t},\n\t\t\t\t\t\tstore,\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tif (\n\t\t\t\tisRootStore(store) &&\n\t\t\t\tstore.transactionMeta.epoch === confirmedUpdate.epoch - 1\n\t\t\t) {\n\t\t\t\tInternal.ingestTransactionUpdate(`newValue`, confirmedUpdate, store)\n\t\t\t\tsocket.emit(`tx-ack:${token.key}`, confirmedUpdate.epoch)\n\t\t\t\tstore.transactionMeta.epoch = confirmedUpdate.epoch\n\t\t\t} else if (isRootStore(store)) {\n\t\t\t\tstore.logger.info(\n\t\t\t\t\t`❌`,\n\t\t\t\t\t`transaction`,\n\t\t\t\t\ttoken.key,\n\t\t\t\t\t`received out-of-order update from server`,\n\t\t\t\t\t{\n\t\t\t\t\t\tclientEpoch: store.transactionMeta.epoch,\n\t\t\t\t\t\tserverEpoch: confirmedUpdate.epoch,\n\t\t\t\t\t},\n\t\t\t\t)\n\t\t\t}\n\t\t}\n\t}\n\tsocket.off(`tx-new:${token.key}`, registerAndAttemptConfirmedUpdate)\n\tsocket.on(`tx-new:${token.key}`, registerAndAttemptConfirmedUpdate)\n\tsocket.emit(`tx-sub:${token.key}`)\n\tconst unsubscribeFromIncomingUpdates = () => {\n\t\tsocket.off(`tx-new:${token.key}`, registerAndAttemptConfirmedUpdate)\n\t\tsocket.emit(`tx-unsub:${token.key}`)\n\t}\n\treturn () => {\n\t\tunsubscribeFromLocalUpdates()\n\t\tunsubscribeFromIncomingUpdates()\n\t}\n}\n","import type { ƒn } from \"atom.io\"\n\nimport type { TransactionEpoch, TransactionProgress } from \".\"\nimport type { Store } from \"../store\"\n\nexport interface RootStore extends Store {\n\ttransactionMeta: TransactionEpoch\n\tparent: null\n\tchild: ChildStore | null\n}\nexport interface ChildStore extends Store {\n\ttransactionMeta: TransactionProgress<ƒn>\n\tparent: ChildStore | RootStore\n\tchild: ChildStore | null\n}\n\nexport function isRootStore(store: Store): store is RootStore {\n\treturn `epoch` in store.transactionMeta\n}\n\nexport function isChildStore(store: Store): store is ChildStore {\n\treturn `phase` in store.transactionMeta\n}\n","import type * as AtomIO from \"atom.io\"\nimport { type Store, setIntoStore } from \"atom.io/internal\"\nimport type { Json } from \"atom.io/json\"\nimport type { Socket } from \"socket.io-client\"\n\nexport function syncState<J extends Json.Serializable>(\n\ttoken: AtomIO.WritableToken<J>,\n\tsocket: Socket,\n\tstore: Store,\n): () => void {\n\tconst setServedValue = (data: J) => {\n\t\tsetIntoStore(token, data, store)\n\t}\n\tsocket.on(`value:${token.key}`, setServedValue)\n\tsocket.emit(`get:${token.key}`)\n\treturn () => {\n\t\tsocket.off(`value:${token.key}`, setServedValue)\n\t}\n}\n"]}
|
|
@@ -4,10 +4,6 @@ import { Store, Transceiver } from 'atom.io/internal';
|
|
|
4
4
|
import { Json } from 'atom.io/json';
|
|
5
5
|
import { Socket } from 'socket.io-client';
|
|
6
6
|
|
|
7
|
-
declare const myIdState__INTERNAL: AtomIO.RegularAtomToken<string | undefined>;
|
|
8
|
-
declare const myIdState: AtomIO.ReadonlySelectorToken<string | undefined>;
|
|
9
|
-
declare const updateQueueAtoms: AtomIO.RegularAtomFamily<AtomIO.TransactionUpdate<any>[], AtomIO.TransactionToken<any>>;
|
|
10
|
-
|
|
11
7
|
declare function pullState<J extends Json.Serializable>(token: AtomIO.WritableToken<J>, socket: Socket, store: Store): () => void;
|
|
12
8
|
|
|
13
9
|
declare function pullFamilyMember<J extends Json.Serializable>(token: AtomIO.WritableToken<J>, socket: Socket, store: Store): () => void;
|
|
@@ -20,6 +16,14 @@ declare function pushState<J extends Json.Serializable>(token: AtomIO.WritableTo
|
|
|
20
16
|
|
|
21
17
|
declare function serverAction<ƒ extends AtomIO.ƒn>(token: AtomIO.TransactionToken<ƒ>, socket: Socket, store: Internal.Store): () => void;
|
|
22
18
|
|
|
23
|
-
declare
|
|
19
|
+
declare const myIdState__INTERNAL: AtomIO.RegularAtomToken<string | undefined>;
|
|
20
|
+
declare const myIdState: AtomIO.ReadonlySelectorToken<string | undefined>;
|
|
21
|
+
|
|
22
|
+
declare const optimisticUpdateQueueState: AtomIO.RegularAtomToken<AtomIO.TransactionUpdate<any>[]>;
|
|
23
|
+
declare const confirmedUpdateQueueState: AtomIO.RegularAtomToken<AtomIO.TransactionUpdate<any>[]>;
|
|
24
|
+
|
|
25
|
+
declare function syncAction<ƒ extends AtomIO.ƒn>(token: AtomIO.TransactionToken<ƒ>, socket: Socket, store: Internal.Store): () => void;
|
|
26
|
+
|
|
27
|
+
declare function syncState<J extends Json.Serializable>(token: AtomIO.WritableToken<J>, socket: Socket, store: Store): () => void;
|
|
24
28
|
|
|
25
|
-
export { myIdState, myIdState__INTERNAL, pullFamilyMember, pullMutableFamilyMember, pullMutableState, pullState, pushState, serverAction, syncAction,
|
|
29
|
+
export { confirmedUpdateQueueState, myIdState, myIdState__INTERNAL, optimisticUpdateQueueState, pullFamilyMember, pullMutableFamilyMember, pullMutableState, pullState, pushState, serverAction, syncAction, syncState };
|