atom.io 0.27.4 → 0.28.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 +31 -29
- package/data/dist/index.js +65 -81
- package/data/src/dict.ts +9 -12
- package/data/src/join.ts +30 -33
- package/data/src/struct-family.ts +17 -23
- package/data/src/struct.ts +9 -12
- package/dist/{chunk-JRENM6KL.js → chunk-BX3MTH2Z.js} +482 -385
- package/dist/chunk-D52JNVER.js +721 -0
- package/dist/chunk-EUVKUTW3.js +89 -0
- package/dist/index.d.ts +4 -3
- package/dist/index.js +35 -53
- package/ephemeral/dist/index.js +1 -1
- package/ephemeral/src/find-state.ts +1 -1
- package/immortal/dist/index.js +2 -2
- package/immortal/src/seek-state.ts +2 -2
- package/internal/dist/index.d.ts +141 -87
- package/internal/dist/index.js +1 -1
- package/internal/src/atom/create-regular-atom.ts +3 -3
- package/internal/src/atom/create-standalone-atom.ts +7 -5
- package/internal/src/atom/dispose-atom.ts +2 -9
- package/internal/src/families/create-atom-family.ts +5 -5
- package/internal/src/families/create-readonly-selector-family.ts +20 -9
- package/internal/src/families/create-regular-atom-family.ts +15 -6
- package/internal/src/families/create-selector-family.ts +5 -5
- package/internal/src/families/create-writable-selector-family.ts +20 -10
- package/internal/src/families/dispose-from-store.ts +43 -29
- package/internal/src/families/find-in-store.ts +28 -18
- package/internal/src/families/init-family-member.ts +9 -9
- package/internal/src/families/seek-in-store.ts +10 -10
- package/internal/src/get-state/get-from-store.ts +70 -47
- package/internal/src/ingest-updates/ingest-atom-update.ts +1 -1
- package/internal/src/ingest-updates/ingest-creation-disposal.ts +15 -6
- package/internal/src/molecule/create-molecule-family.ts +1 -1
- package/internal/src/molecule/dispose-molecule.ts +7 -18
- package/internal/src/molecule/grow-molecule-in-store.ts +1 -1
- package/internal/src/molecule/make-molecule-in-store.ts +5 -5
- package/internal/src/mutable/create-mutable-atom-family.ts +15 -6
- package/internal/src/mutable/create-mutable-atom.ts +3 -3
- package/internal/src/mutable/get-json-token.ts +2 -2
- package/internal/src/mutable/tracker-family.ts +3 -3
- package/internal/src/mutable/tracker.ts +14 -18
- package/internal/src/pretty-print.ts +1 -16
- package/internal/src/selector/create-readonly-selector.ts +2 -2
- package/internal/src/selector/create-standalone-selector.ts +5 -5
- package/internal/src/selector/create-writable-selector.ts +2 -2
- package/internal/src/selector/dispose-selector.ts +2 -9
- package/internal/src/selector/register-selector.ts +9 -9
- package/internal/src/set-state/set-into-store.ts +23 -33
- package/internal/src/store/circular-buffer.ts +34 -0
- package/internal/src/store/counterfeit.ts +109 -0
- package/internal/src/store/deposit.ts +67 -13
- package/internal/src/store/index.ts +1 -0
- package/internal/src/store/store.ts +4 -1
- package/internal/src/store/withdraw.ts +15 -10
- package/internal/src/subscribe/index.ts +2 -0
- package/internal/src/subscribe/subscribe-in-store.ts +62 -0
- package/internal/src/timeline/time-travel.ts +1 -1
- package/internal/src/transaction/build-transaction.ts +7 -6
- package/introspection/dist/index.d.ts +84 -4
- package/introspection/dist/index.js +1 -413
- package/introspection/src/attach-atom-index.ts +5 -8
- package/introspection/src/attach-introspection-states.ts +7 -4
- package/introspection/src/attach-selector-index.ts +6 -8
- package/introspection/src/attach-timeline-family.ts +25 -28
- package/introspection/src/attach-timeline-index.ts +5 -8
- package/introspection/src/attach-transaction-index.ts +5 -8
- package/introspection/src/attach-transaction-logs.ts +21 -27
- package/introspection/src/attach-type-selectors.ts +26 -0
- package/introspection/src/differ.ts +167 -0
- package/introspection/src/index.ts +2 -0
- package/introspection/src/refinery.ts +100 -0
- package/json/dist/index.d.ts +31 -30
- package/json/dist/index.js +2 -80
- package/json/src/entries.ts +6 -0
- package/json/src/index.ts +47 -6
- package/json/src/select-json-family.ts +4 -4
- package/json/src/select-json.ts +6 -9
- package/package.json +17 -8
- package/react/dist/index.js +7 -7
- package/react/src/parse-state-overloads.ts +2 -2
- package/react/src/use-i.ts +1 -1
- package/react/src/use-json.ts +2 -2
- package/react/src/use-o.ts +2 -2
- package/react-devtools/dist/index.d.ts +1 -91
- package/react-devtools/dist/index.js +285 -414
- package/react-devtools/src/AtomIODevtools.tsx +2 -2
- package/react-devtools/src/StateEditor.tsx +20 -12
- package/react-devtools/src/StateIndex.tsx +8 -26
- package/react-devtools/src/TimelineIndex.tsx +3 -3
- package/react-devtools/src/TransactionIndex.tsx +6 -6
- package/react-devtools/src/Updates.tsx +1 -4
- package/react-devtools/src/index.ts +0 -71
- package/react-devtools/src/store.ts +51 -0
- package/realtime/dist/index.d.ts +7 -7
- package/realtime/dist/index.js +18 -22
- package/realtime/src/realtime-continuity.ts +27 -35
- package/realtime-client/dist/index.js +59 -65
- package/realtime-client/src/pull-atom-family-member.ts +1 -1
- package/realtime-client/src/pull-atom.ts +1 -1
- package/realtime-client/src/pull-mutable-atom-family-member.ts +3 -3
- package/realtime-client/src/pull-mutable-atom.ts +3 -3
- package/realtime-client/src/realtime-client-stores/client-main-store.ts +6 -6
- package/realtime-client/src/sync-continuity.ts +55 -53
- package/realtime-react/dist/index.js +3 -3
- package/realtime-react/src/use-pull-atom-family-member.ts +1 -1
- package/realtime-react/src/use-pull-mutable-family-member.ts +1 -1
- package/realtime-react/src/use-pull-selector-family-member.ts +1 -1
- package/realtime-server/dist/index.js +72 -36
- package/realtime-server/src/realtime-continuity-synchronizer.ts +57 -93
- package/realtime-server/src/realtime-family-provider.ts +3 -3
- package/realtime-server/src/realtime-mutable-family-provider.ts +5 -5
- package/realtime-server/src/realtime-mutable-provider.ts +2 -2
- package/realtime-server/src/realtime-state-provider.ts +1 -1
- package/realtime-server/src/realtime-state-receiver.ts +1 -1
- package/realtime-testing/dist/index.d.ts +2 -0
- package/realtime-testing/dist/index.js +57 -15
- package/realtime-testing/src/setup-realtime-test.tsx +66 -16
- package/src/atom.ts +2 -2
- package/src/dispose-state.ts +2 -2
- package/src/get-state.ts +9 -13
- package/src/molecule.ts +1 -1
- package/src/selector.ts +2 -2
- package/src/set-state.ts +10 -7
- package/src/silo.ts +29 -55
- package/src/subscribe.ts +3 -23
- package/src/timeline.ts +2 -2
- package/web/dist/index.d.ts +9 -0
- package/{dist/chunk-H6EDLPKH.js → web/dist/index.js} +5 -4
- package/web/package.json +13 -0
- package/web/src/index.ts +1 -0
- package/web/src/persist-sync.ts +25 -0
- package/dist/chunk-AK23DRMD.js +0 -21
- package/dist/chunk-IW6WYRS7.js +0 -140
- package/internal/src/families/throw-in-case-of-conflicting-family.ts +0 -18
|
@@ -484,7 +484,7 @@ function realtimeContinuitySynchronizer({
|
|
|
484
484
|
socket.id,
|
|
485
485
|
store
|
|
486
486
|
).userKeyOfSocket;
|
|
487
|
-
const userKey = getFromStore(
|
|
487
|
+
const userKey = getFromStore(store, userKeyState);
|
|
488
488
|
if (!userKey) {
|
|
489
489
|
store.logger.error(
|
|
490
490
|
`\u274C`,
|
|
@@ -510,36 +510,42 @@ function realtimeContinuitySynchronizer({
|
|
|
510
510
|
`seeing ${userKey} on new socket ${newSocketKey}`
|
|
511
511
|
);
|
|
512
512
|
if (newSocketKey === null) {
|
|
513
|
-
store.logger.
|
|
513
|
+
store.logger.warn(
|
|
514
514
|
`\u274C`,
|
|
515
515
|
`continuity`,
|
|
516
516
|
continuityKey,
|
|
517
|
-
`
|
|
517
|
+
`User (${userKey}) is not connected to a socket, waiting for them to reappear.`
|
|
518
518
|
);
|
|
519
519
|
return;
|
|
520
520
|
}
|
|
521
|
-
const newSocketState = findInStore(socketAtoms, newSocketKey
|
|
522
|
-
const newSocket = getFromStore(
|
|
521
|
+
const newSocketState = findInStore(store, socketAtoms, newSocketKey);
|
|
522
|
+
const newSocket = getFromStore(store, newSocketState);
|
|
523
523
|
socket = newSocket;
|
|
524
|
+
for (const unacknowledgedUpdate of userUnacknowledgedUpdates) {
|
|
525
|
+
socket?.emit(
|
|
526
|
+
`tx-new:${continuityKey}`,
|
|
527
|
+
unacknowledgedUpdate
|
|
528
|
+
);
|
|
529
|
+
}
|
|
524
530
|
},
|
|
525
531
|
`sync-continuity:${continuityKey}:${userKey}`,
|
|
526
532
|
store
|
|
527
533
|
);
|
|
528
534
|
const userUnacknowledgedQueue = findInStore(
|
|
535
|
+
store,
|
|
529
536
|
userUnacknowledgedQueues,
|
|
530
|
-
userKey
|
|
531
|
-
store
|
|
537
|
+
userKey
|
|
532
538
|
);
|
|
533
|
-
getFromStore(
|
|
534
|
-
|
|
535
|
-
|
|
539
|
+
const userUnacknowledgedUpdates = getFromStore(
|
|
540
|
+
store,
|
|
541
|
+
userUnacknowledgedQueue
|
|
536
542
|
);
|
|
537
543
|
const unsubscribeFunctions = [];
|
|
538
544
|
const revealPerspectives = () => {
|
|
539
545
|
const unsubFns = [];
|
|
540
546
|
for (const perspective of continuity.perspectives) {
|
|
541
547
|
const { viewAtoms } = perspective;
|
|
542
|
-
const userViewState = findInStore(viewAtoms, userKey
|
|
548
|
+
const userViewState = findInStore(store, viewAtoms, userKey);
|
|
543
549
|
const unsubscribe = subscribeToState(
|
|
544
550
|
userViewState,
|
|
545
551
|
({ oldValue, newValue }) => {
|
|
@@ -549,8 +555,8 @@ function realtimeContinuitySynchronizer({
|
|
|
549
555
|
(token) => !newKeys.includes(token.key)
|
|
550
556
|
);
|
|
551
557
|
const revealed = newValue.filter((token) => !oldKeys.includes(token.key)).flatMap((token) => {
|
|
552
|
-
const resourceToken = token.type === `mutable_atom` ? getJsonToken(
|
|
553
|
-
const resource = getFromStore(
|
|
558
|
+
const resourceToken = token.type === `mutable_atom` ? getJsonToken(store, token) : token;
|
|
559
|
+
const resource = getFromStore(store, resourceToken);
|
|
554
560
|
return [resourceToken, resource];
|
|
555
561
|
});
|
|
556
562
|
store.logger.info(
|
|
@@ -580,21 +586,22 @@ function realtimeContinuitySynchronizer({
|
|
|
580
586
|
const sendInitialPayload = () => {
|
|
581
587
|
const initialPayload = [];
|
|
582
588
|
for (const atom2 of continuity.globals) {
|
|
583
|
-
const resourceToken = atom2.type === `mutable_atom` ? getJsonToken(
|
|
584
|
-
|
|
589
|
+
const resourceToken = atom2.type === `mutable_atom` ? getJsonToken(store, atom2) : atom2;
|
|
590
|
+
const resource = getFromStore(store, resourceToken);
|
|
591
|
+
initialPayload.push(resourceToken, resource);
|
|
585
592
|
}
|
|
586
593
|
for (const perspective of continuity.perspectives) {
|
|
587
594
|
const { viewAtoms, resourceAtoms } = perspective;
|
|
588
|
-
const userViewState = findInStore(viewAtoms, userKey
|
|
589
|
-
const userView = getFromStore(
|
|
595
|
+
const userViewState = findInStore(store, viewAtoms, userKey);
|
|
596
|
+
const userView = getFromStore(store, userViewState);
|
|
590
597
|
store.logger.info(`\u{1F441}`, `atom`, resourceAtoms.key, `${userKey} can see`, {
|
|
591
598
|
viewAtoms,
|
|
592
599
|
resourceAtoms,
|
|
593
600
|
userView
|
|
594
601
|
});
|
|
595
602
|
for (const visibleToken of userView) {
|
|
596
|
-
const resourceToken = visibleToken.type === `mutable_atom` ? getJsonToken(
|
|
597
|
-
const resource = getFromStore(
|
|
603
|
+
const resourceToken = visibleToken.type === `mutable_atom` ? getJsonToken(store, visibleToken) : visibleToken;
|
|
604
|
+
const resource = getFromStore(store, resourceToken);
|
|
598
605
|
initialPayload.push(resourceToken, resource);
|
|
599
606
|
}
|
|
600
607
|
}
|
|
@@ -605,17 +612,22 @@ function realtimeContinuitySynchronizer({
|
|
|
605
612
|
transaction2,
|
|
606
613
|
(update) => {
|
|
607
614
|
try {
|
|
608
|
-
const visibleKeys = continuity.globals.map((atom2) =>
|
|
615
|
+
const visibleKeys = continuity.globals.map((atom2) => {
|
|
616
|
+
if (atom2.type === `atom`) {
|
|
617
|
+
return atom2.key;
|
|
618
|
+
}
|
|
619
|
+
return getUpdateToken(atom2).key;
|
|
620
|
+
}).concat(
|
|
609
621
|
continuity.perspectives.flatMap((perspective) => {
|
|
610
622
|
const { viewAtoms } = perspective;
|
|
611
623
|
const userPerspectiveTokenState = findInStore(
|
|
624
|
+
store,
|
|
612
625
|
viewAtoms,
|
|
613
|
-
userKey
|
|
614
|
-
store
|
|
626
|
+
userKey
|
|
615
627
|
);
|
|
616
628
|
const visibleTokens = getFromStore(
|
|
617
|
-
|
|
618
|
-
|
|
629
|
+
store,
|
|
630
|
+
userPerspectiveTokenState
|
|
619
631
|
);
|
|
620
632
|
return visibleTokens.map((token) => {
|
|
621
633
|
const key = token.type === `mutable_atom` ? `*` + token.key : token.key;
|
|
@@ -631,6 +643,13 @@ function realtimeContinuitySynchronizer({
|
|
|
631
643
|
...update,
|
|
632
644
|
updates: redactedUpdates
|
|
633
645
|
};
|
|
646
|
+
setIntoStore(store, userUnacknowledgedQueue, (updates) => {
|
|
647
|
+
if (redactedUpdate) {
|
|
648
|
+
updates.push(redactedUpdate);
|
|
649
|
+
updates.sort((a, b) => a.epoch - b.epoch);
|
|
650
|
+
}
|
|
651
|
+
return updates;
|
|
652
|
+
});
|
|
634
653
|
socket?.emit(
|
|
635
654
|
`tx-new:${continuityKey}`,
|
|
636
655
|
redactedUpdate
|
|
@@ -710,8 +729,25 @@ function realtimeContinuitySynchronizer({
|
|
|
710
729
|
};
|
|
711
730
|
socket.off(`tx-run:${continuityKey}`, fillTransactionRequest);
|
|
712
731
|
socket.on(`tx-run:${continuityKey}`, fillTransactionRequest);
|
|
732
|
+
const trackClientAcknowledgement = (epoch) => {
|
|
733
|
+
store.logger.info(
|
|
734
|
+
`\u{1F44D}`,
|
|
735
|
+
`continuity`,
|
|
736
|
+
continuityKey,
|
|
737
|
+
`${userKey} acknowledged epoch ${epoch}`
|
|
738
|
+
);
|
|
739
|
+
const isUnacknowledged = userUnacknowledgedUpdates[0]?.epoch === epoch;
|
|
740
|
+
if (isUnacknowledged) {
|
|
741
|
+
setIntoStore(store, userUnacknowledgedQueue, (updates) => {
|
|
742
|
+
updates.shift();
|
|
743
|
+
return updates;
|
|
744
|
+
});
|
|
745
|
+
}
|
|
746
|
+
};
|
|
747
|
+
socket?.on(`ack:${continuityKey}`, trackClientAcknowledgement);
|
|
713
748
|
return () => {
|
|
714
749
|
for (const unsubscribe of unsubscribeFunctions) unsubscribe();
|
|
750
|
+
socket?.off(`ack:${continuityKey}`, trackClientAcknowledgement);
|
|
715
751
|
unsubscribeFromPerspectives();
|
|
716
752
|
socket?.off(`get:${continuityKey}`, sendInitialPayload);
|
|
717
753
|
socket?.off(`tx-run:${continuityKey}`, fillTransactionRequest);
|
|
@@ -733,11 +769,11 @@ function realtimeAtomFamilyProvider({
|
|
|
733
769
|
}
|
|
734
770
|
};
|
|
735
771
|
const fillSubRequest = (subKey) => {
|
|
736
|
-
const exposedSubKeys = getFromStore(
|
|
772
|
+
const exposedSubKeys = getFromStore(store, index);
|
|
737
773
|
for (const exposedSubKey of exposedSubKeys) {
|
|
738
774
|
if (stringifyJson(exposedSubKey) === stringifyJson(subKey)) {
|
|
739
|
-
const token = findInStore(family, subKey
|
|
740
|
-
socket.emit(`serve:${token.key}`, getFromStore(
|
|
775
|
+
const token = findInStore(store, family, subKey);
|
|
776
|
+
socket.emit(`serve:${token.key}`, getFromStore(store, token));
|
|
741
777
|
const unsubscribe = subscribeToState(
|
|
742
778
|
token,
|
|
743
779
|
({ newValue }) => {
|
|
@@ -779,14 +815,14 @@ function realtimeMutableFamilyProvider({
|
|
|
779
815
|
}
|
|
780
816
|
};
|
|
781
817
|
const fillSubRequest = (subKey) => {
|
|
782
|
-
const exposedSubKeys = getFromStore(
|
|
818
|
+
const exposedSubKeys = getFromStore(store, index);
|
|
783
819
|
for (const exposedSubKey of exposedSubKeys) {
|
|
784
820
|
if (stringifyJson(exposedSubKey) === stringifyJson(subKey)) {
|
|
785
|
-
const token = findInStore(family, subKey
|
|
786
|
-
getFromStore(
|
|
787
|
-
const jsonToken = getJsonToken(
|
|
821
|
+
const token = findInStore(store, family, subKey);
|
|
822
|
+
getFromStore(store, token);
|
|
823
|
+
const jsonToken = getJsonToken(store, token);
|
|
788
824
|
const updateToken = getUpdateToken(token);
|
|
789
|
-
socket.emit(`init:${token.key}`, getFromStore(
|
|
825
|
+
socket.emit(`init:${token.key}`, getFromStore(store, jsonToken));
|
|
790
826
|
const unsubscribe = subscribeToState(
|
|
791
827
|
updateToken,
|
|
792
828
|
({ newValue }) => {
|
|
@@ -819,7 +855,7 @@ function realtimeMutableProvider({
|
|
|
819
855
|
}) {
|
|
820
856
|
return function mutableProvider(token) {
|
|
821
857
|
let unsubscribeFromStateUpdates = null;
|
|
822
|
-
const jsonToken = getJsonToken(
|
|
858
|
+
const jsonToken = getJsonToken(store, token);
|
|
823
859
|
const trackerToken = getUpdateToken(token);
|
|
824
860
|
const fillUnsubRequest = () => {
|
|
825
861
|
socket.off(`unsub:${token.key}`, fillUnsubRequest);
|
|
@@ -827,7 +863,7 @@ function realtimeMutableProvider({
|
|
|
827
863
|
unsubscribeFromStateUpdates = null;
|
|
828
864
|
};
|
|
829
865
|
const fillSubRequest = () => {
|
|
830
|
-
socket.emit(`init:${token.key}`, getFromStore(
|
|
866
|
+
socket.emit(`init:${token.key}`, getFromStore(store, jsonToken));
|
|
831
867
|
unsubscribeFromStateUpdates = subscribeToState(
|
|
832
868
|
trackerToken,
|
|
833
869
|
({ newValue }) => {
|
|
@@ -852,7 +888,7 @@ function realtimeStateProvider({
|
|
|
852
888
|
return function stateProvider(token) {
|
|
853
889
|
let unsubscribeFromStateUpdates;
|
|
854
890
|
const fillSubRequest = () => {
|
|
855
|
-
socket.emit(`serve:${token.key}`, getFromStore(
|
|
891
|
+
socket.emit(`serve:${token.key}`, getFromStore(store, token));
|
|
856
892
|
unsubscribeFromStateUpdates = subscribeToState(
|
|
857
893
|
token,
|
|
858
894
|
({ newValue }) => {
|
|
@@ -886,7 +922,7 @@ function realtimeStateReceiver({
|
|
|
886
922
|
}) {
|
|
887
923
|
return function stateReceiver(token) {
|
|
888
924
|
const publish = (newValue) => {
|
|
889
|
-
setIntoStore(token, newValue
|
|
925
|
+
setIntoStore(store, token, newValue);
|
|
890
926
|
};
|
|
891
927
|
const fillPubUnclaim = () => {
|
|
892
928
|
socket.off(`pub:${token.key}`, publish);
|
|
@@ -5,8 +5,10 @@ import {
|
|
|
5
5
|
findInStore,
|
|
6
6
|
getFromStore,
|
|
7
7
|
getJsonToken,
|
|
8
|
+
getUpdateToken,
|
|
8
9
|
IMPLICIT,
|
|
9
10
|
isRootStore,
|
|
11
|
+
setIntoStore,
|
|
10
12
|
subscribeToState,
|
|
11
13
|
subscribeToTransaction,
|
|
12
14
|
} from "atom.io/internal"
|
|
@@ -36,7 +38,7 @@ export function realtimeContinuitySynchronizer({
|
|
|
36
38
|
socket.id,
|
|
37
39
|
store,
|
|
38
40
|
).userKeyOfSocket
|
|
39
|
-
const userKey = getFromStore(
|
|
41
|
+
const userKey = getFromStore(store, userKeyState)
|
|
40
42
|
if (!userKey) {
|
|
41
43
|
store.logger.error(
|
|
42
44
|
`❌`,
|
|
@@ -62,30 +64,36 @@ export function realtimeContinuitySynchronizer({
|
|
|
62
64
|
`seeing ${userKey} on new socket ${newSocketKey}`,
|
|
63
65
|
)
|
|
64
66
|
if (newSocketKey === null) {
|
|
65
|
-
store.logger.
|
|
67
|
+
store.logger.warn(
|
|
66
68
|
`❌`,
|
|
67
69
|
`continuity`,
|
|
68
70
|
continuityKey,
|
|
69
|
-
`
|
|
71
|
+
`User (${userKey}) is not connected to a socket, waiting for them to reappear.`,
|
|
70
72
|
)
|
|
71
73
|
return
|
|
72
74
|
}
|
|
73
|
-
const newSocketState = findInStore(socketAtoms, newSocketKey
|
|
74
|
-
const newSocket = getFromStore(
|
|
75
|
+
const newSocketState = findInStore(store, socketAtoms, newSocketKey)
|
|
76
|
+
const newSocket = getFromStore(store, newSocketState)
|
|
75
77
|
socket = newSocket
|
|
78
|
+
for (const unacknowledgedUpdate of userUnacknowledgedUpdates) {
|
|
79
|
+
socket?.emit(
|
|
80
|
+
`tx-new:${continuityKey}`,
|
|
81
|
+
unacknowledgedUpdate as Json.Serializable,
|
|
82
|
+
)
|
|
83
|
+
}
|
|
76
84
|
},
|
|
77
85
|
`sync-continuity:${continuityKey}:${userKey}`,
|
|
78
86
|
store,
|
|
79
87
|
)
|
|
80
88
|
|
|
81
89
|
const userUnacknowledgedQueue = findInStore(
|
|
90
|
+
store,
|
|
82
91
|
userUnacknowledgedQueues,
|
|
83
92
|
userKey,
|
|
84
|
-
store,
|
|
85
93
|
)
|
|
86
94
|
const userUnacknowledgedUpdates = getFromStore(
|
|
87
|
-
userUnacknowledgedQueue,
|
|
88
95
|
store,
|
|
96
|
+
userUnacknowledgedQueue,
|
|
89
97
|
)
|
|
90
98
|
const unsubscribeFunctions: (() => void)[] = []
|
|
91
99
|
|
|
@@ -93,7 +101,7 @@ export function realtimeContinuitySynchronizer({
|
|
|
93
101
|
const unsubFns: (() => void)[] = []
|
|
94
102
|
for (const perspective of continuity.perspectives) {
|
|
95
103
|
const { viewAtoms } = perspective
|
|
96
|
-
const userViewState = findInStore(viewAtoms, userKey
|
|
104
|
+
const userViewState = findInStore(store, viewAtoms, userKey)
|
|
97
105
|
const unsubscribe = subscribeToState(
|
|
98
106
|
userViewState,
|
|
99
107
|
({ oldValue, newValue }) => {
|
|
@@ -107,9 +115,9 @@ export function realtimeContinuitySynchronizer({
|
|
|
107
115
|
.flatMap((token) => {
|
|
108
116
|
const resourceToken =
|
|
109
117
|
token.type === `mutable_atom`
|
|
110
|
-
? getJsonToken(
|
|
118
|
+
? getJsonToken(store, token)
|
|
111
119
|
: token
|
|
112
|
-
const resource = getFromStore(
|
|
120
|
+
const resource = getFromStore(store, resourceToken)
|
|
113
121
|
return [resourceToken, resource]
|
|
114
122
|
})
|
|
115
123
|
store.logger.info(
|
|
@@ -141,13 +149,14 @@ export function realtimeContinuitySynchronizer({
|
|
|
141
149
|
const initialPayload: Json.Serializable[] = []
|
|
142
150
|
for (const atom of continuity.globals) {
|
|
143
151
|
const resourceToken =
|
|
144
|
-
atom.type === `mutable_atom` ? getJsonToken(
|
|
145
|
-
|
|
152
|
+
atom.type === `mutable_atom` ? getJsonToken(store, atom) : atom
|
|
153
|
+
const resource = getFromStore(store, resourceToken)
|
|
154
|
+
initialPayload.push(resourceToken, resource)
|
|
146
155
|
}
|
|
147
156
|
for (const perspective of continuity.perspectives) {
|
|
148
157
|
const { viewAtoms, resourceAtoms } = perspective
|
|
149
|
-
const userViewState = findInStore(viewAtoms, userKey
|
|
150
|
-
const userView = getFromStore(
|
|
158
|
+
const userViewState = findInStore(store, viewAtoms, userKey)
|
|
159
|
+
const userView = getFromStore(store, userViewState)
|
|
151
160
|
store.logger.info(`👁`, `atom`, resourceAtoms.key, `${userKey} can see`, {
|
|
152
161
|
viewAtoms,
|
|
153
162
|
resourceAtoms,
|
|
@@ -156,9 +165,9 @@ export function realtimeContinuitySynchronizer({
|
|
|
156
165
|
for (const visibleToken of userView) {
|
|
157
166
|
const resourceToken =
|
|
158
167
|
visibleToken.type === `mutable_atom`
|
|
159
|
-
? getJsonToken(
|
|
168
|
+
? getJsonToken(store, visibleToken)
|
|
160
169
|
: visibleToken
|
|
161
|
-
const resource = getFromStore(
|
|
170
|
+
const resource = getFromStore(store, resourceToken)
|
|
162
171
|
|
|
163
172
|
initialPayload.push(resourceToken, resource)
|
|
164
173
|
}
|
|
@@ -176,18 +185,23 @@ export function realtimeContinuitySynchronizer({
|
|
|
176
185
|
(update) => {
|
|
177
186
|
try {
|
|
178
187
|
const visibleKeys = continuity.globals
|
|
179
|
-
.map((atom) =>
|
|
188
|
+
.map((atom) => {
|
|
189
|
+
if (atom.type === `atom`) {
|
|
190
|
+
return atom.key
|
|
191
|
+
}
|
|
192
|
+
return getUpdateToken(atom).key
|
|
193
|
+
})
|
|
180
194
|
.concat(
|
|
181
195
|
continuity.perspectives.flatMap((perspective) => {
|
|
182
196
|
const { viewAtoms } = perspective
|
|
183
197
|
const userPerspectiveTokenState = findInStore(
|
|
198
|
+
store,
|
|
184
199
|
viewAtoms,
|
|
185
200
|
userKey,
|
|
186
|
-
store,
|
|
187
201
|
)
|
|
188
202
|
const visibleTokens = getFromStore(
|
|
189
|
-
userPerspectiveTokenState,
|
|
190
203
|
store,
|
|
204
|
+
userPerspectiveTokenState,
|
|
191
205
|
)
|
|
192
206
|
return visibleTokens.map((token) => {
|
|
193
207
|
const key =
|
|
@@ -206,17 +220,13 @@ export function realtimeContinuitySynchronizer({
|
|
|
206
220
|
...update,
|
|
207
221
|
updates: redactedUpdates,
|
|
208
222
|
}
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
// return updates
|
|
217
|
-
// },
|
|
218
|
-
// store,
|
|
219
|
-
// )
|
|
223
|
+
setIntoStore(store, userUnacknowledgedQueue, (updates) => {
|
|
224
|
+
if (redactedUpdate) {
|
|
225
|
+
updates.push(redactedUpdate)
|
|
226
|
+
updates.sort((a, b) => a.epoch - b.epoch)
|
|
227
|
+
}
|
|
228
|
+
return updates
|
|
229
|
+
})
|
|
220
230
|
|
|
221
231
|
socket?.emit(
|
|
222
232
|
`tx-new:${continuityKey}`,
|
|
@@ -304,73 +314,27 @@ export function realtimeContinuitySynchronizer({
|
|
|
304
314
|
socket.off(`tx-run:${continuityKey}`, fillTransactionRequest)
|
|
305
315
|
socket.on(`tx-run:${continuityKey}`, fillTransactionRequest)
|
|
306
316
|
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
// return updates
|
|
324
|
-
// },
|
|
325
|
-
// store,
|
|
326
|
-
// )
|
|
327
|
-
// }
|
|
328
|
-
// }
|
|
329
|
-
// subscribeToState(
|
|
330
|
-
// userUnacknowledgedQueue,
|
|
331
|
-
// ({ newValue }) => {
|
|
332
|
-
// if (newValue.length === 0) {
|
|
333
|
-
// clearInterval(retryTimeout)
|
|
334
|
-
// socket?.off(`ack:${continuityKey}`, trackClientAcknowledgement)
|
|
335
|
-
// retryTimeout = undefined
|
|
336
|
-
// }
|
|
337
|
-
// if (newValue.length > 0) {
|
|
338
|
-
// if (retryTimeout) {
|
|
339
|
-
// return
|
|
340
|
-
// }
|
|
341
|
-
|
|
342
|
-
// socket?.on(`ack:${continuityKey}`, trackClientAcknowledgement)
|
|
343
|
-
|
|
344
|
-
// retryTimeout = setInterval(() => {
|
|
345
|
-
// i++
|
|
346
|
-
// if (i === n) {
|
|
347
|
-
// n += i
|
|
348
|
-
// const toEmit = newValue[0]
|
|
349
|
-
// if (!toEmit) return
|
|
350
|
-
// store.logger.info(
|
|
351
|
-
// `🔄`,
|
|
352
|
-
// `continuity`,
|
|
353
|
-
// continuityKey,
|
|
354
|
-
// `${store.config.name} retrying ${userKey}`,
|
|
355
|
-
// socket?.id,
|
|
356
|
-
// newValue,
|
|
357
|
-
// )
|
|
358
|
-
// socket?.emit(
|
|
359
|
-
// `tx-new:${continuityKey}`,
|
|
360
|
-
// toEmit as Json.Serializable,
|
|
361
|
-
// )
|
|
362
|
-
// }
|
|
363
|
-
// }, 250)
|
|
364
|
-
// }
|
|
365
|
-
// },
|
|
366
|
-
// `sync-continuity:${continuityKey}:${userKey}`,
|
|
367
|
-
// store,
|
|
368
|
-
// )
|
|
317
|
+
const trackClientAcknowledgement = (epoch: number) => {
|
|
318
|
+
store.logger.info(
|
|
319
|
+
`👍`,
|
|
320
|
+
`continuity`,
|
|
321
|
+
continuityKey,
|
|
322
|
+
`${userKey} acknowledged epoch ${epoch}`,
|
|
323
|
+
)
|
|
324
|
+
const isUnacknowledged = userUnacknowledgedUpdates[0]?.epoch === epoch
|
|
325
|
+
if (isUnacknowledged) {
|
|
326
|
+
setIntoStore(store, userUnacknowledgedQueue, (updates) => {
|
|
327
|
+
updates.shift()
|
|
328
|
+
return updates
|
|
329
|
+
})
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
socket?.on(`ack:${continuityKey}`, trackClientAcknowledgement)
|
|
369
333
|
|
|
370
334
|
return () => {
|
|
371
335
|
// clearInterval(retryTimeout)
|
|
372
336
|
for (const unsubscribe of unsubscribeFunctions) unsubscribe()
|
|
373
|
-
|
|
337
|
+
socket?.off(`ack:${continuityKey}`, trackClientAcknowledgement)
|
|
374
338
|
unsubscribeFromPerspectives()
|
|
375
339
|
socket?.off(`get:${continuityKey}`, sendInitialPayload)
|
|
376
340
|
socket?.off(`tx-run:${continuityKey}`, fillTransactionRequest)
|
|
@@ -34,11 +34,11 @@ export function realtimeAtomFamilyProvider({
|
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
const fillSubRequest = (subKey: K) => {
|
|
37
|
-
const exposedSubKeys = getFromStore(
|
|
37
|
+
const exposedSubKeys = getFromStore(store, index)
|
|
38
38
|
for (const exposedSubKey of exposedSubKeys) {
|
|
39
39
|
if (stringifyJson(exposedSubKey) === stringifyJson(subKey)) {
|
|
40
|
-
const token = findInStore(family, subKey
|
|
41
|
-
socket.emit(`serve:${token.key}`, getFromStore(
|
|
40
|
+
const token = findInStore(store, family, subKey)
|
|
41
|
+
socket.emit(`serve:${token.key}`, getFromStore(store, token))
|
|
42
42
|
const unsubscribe = subscribeToState(
|
|
43
43
|
token,
|
|
44
44
|
({ newValue }) => {
|
|
@@ -40,14 +40,14 @@ export function realtimeMutableFamilyProvider({
|
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
const fillSubRequest = (subKey: K) => {
|
|
43
|
-
const exposedSubKeys = getFromStore(
|
|
43
|
+
const exposedSubKeys = getFromStore(store, index)
|
|
44
44
|
for (const exposedSubKey of exposedSubKeys) {
|
|
45
45
|
if (stringifyJson(exposedSubKey) === stringifyJson(subKey)) {
|
|
46
|
-
const token = findInStore(family, subKey
|
|
47
|
-
getFromStore(
|
|
48
|
-
const jsonToken = getJsonToken(
|
|
46
|
+
const token = findInStore(store, family, subKey)
|
|
47
|
+
getFromStore(store, token)
|
|
48
|
+
const jsonToken = getJsonToken(store, token)
|
|
49
49
|
const updateToken = getUpdateToken(token)
|
|
50
|
-
socket.emit(`init:${token.key}`, getFromStore(
|
|
50
|
+
socket.emit(`init:${token.key}`, getFromStore(store, jsonToken))
|
|
51
51
|
const unsubscribe = subscribeToState(
|
|
52
52
|
updateToken,
|
|
53
53
|
({ newValue }) => {
|
|
@@ -22,7 +22,7 @@ export function realtimeMutableProvider({
|
|
|
22
22
|
>(token: AtomIO.MutableAtomToken<Core, SerializableCore>): () => void {
|
|
23
23
|
let unsubscribeFromStateUpdates: (() => void) | null = null
|
|
24
24
|
|
|
25
|
-
const jsonToken = getJsonToken(
|
|
25
|
+
const jsonToken = getJsonToken(store, token)
|
|
26
26
|
const trackerToken = getUpdateToken(token)
|
|
27
27
|
|
|
28
28
|
const fillUnsubRequest = () => {
|
|
@@ -32,7 +32,7 @@ export function realtimeMutableProvider({
|
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
const fillSubRequest = () => {
|
|
35
|
-
socket.emit(`init:${token.key}`, getFromStore(
|
|
35
|
+
socket.emit(`init:${token.key}`, getFromStore(store, jsonToken))
|
|
36
36
|
unsubscribeFromStateUpdates = subscribeToState(
|
|
37
37
|
trackerToken,
|
|
38
38
|
({ newValue }) => {
|
|
@@ -15,7 +15,7 @@ export function realtimeStateProvider({
|
|
|
15
15
|
let unsubscribeFromStateUpdates: (() => void) | undefined
|
|
16
16
|
|
|
17
17
|
const fillSubRequest = () => {
|
|
18
|
-
socket.emit(`serve:${token.key}`, getFromStore(
|
|
18
|
+
socket.emit(`serve:${token.key}`, getFromStore(store, token))
|
|
19
19
|
|
|
20
20
|
unsubscribeFromStateUpdates = subscribeToState(
|
|
21
21
|
token,
|
|
@@ -9,6 +9,7 @@ type TestSetupOptions = {
|
|
|
9
9
|
server: (tools: {
|
|
10
10
|
socket: SocketIO.Socket;
|
|
11
11
|
silo: AtomIO.Silo;
|
|
12
|
+
enableLogging: () => void;
|
|
12
13
|
}) => void;
|
|
13
14
|
};
|
|
14
15
|
type TestSetupOptions__SingleClient = TestSetupOptions & {
|
|
@@ -26,6 +27,7 @@ type RealtimeTestTools = {
|
|
|
26
27
|
type RealtimeTestClient = RealtimeTestTools & {
|
|
27
28
|
renderResult: RenderResult;
|
|
28
29
|
prettyPrint: () => void;
|
|
30
|
+
enableLogging: () => void;
|
|
29
31
|
socket: Socket;
|
|
30
32
|
};
|
|
31
33
|
type RealtimeTestClientBuilder = {
|