Skip to content

Commit 4d76e5b

Browse files
authored
fix(subscription): gracefully handle in-flight updates for cancelled subscriptions (#379)
* Default to last visited replica * fix(subscription): gracefully handle in-flight updates for cancelled subscriptions Previously, integrate() would throw an error ("Subscription is cancelled") if an update arrived after the subscription had been cancelled. This happened due to a race condition where in-flight updates were still delivered even after the subscription was removed from active subscriber lists. Now, integrate() checks if the subscription’s controller is missing and logs a warning while ignoring the update, rather than throwing an error. This ensures that cancelled subscriptions do not cause fatal errors while preventing memory leaks by properly unwatching and clearing subscriber channels. fixes #378
1 parent 3cf15ef commit 4d76e5b

File tree

2 files changed

+12
-2
lines changed

2 files changed

+12
-2
lines changed

typescript/packages/common-memory/subscription.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ export const integrate = (session: Session, change: In<State>) => {
7878
if (session.controller) {
7979
session.controller.enqueue(change);
8080
} else {
81-
throw new Error("Subscription is cancelled");
81+
console.warn("Subscription is cancelled, not integrating change", change);
8282
}
8383
};
8484

typescript/packages/jumble/src/contexts/CharmManagerContext.tsx

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,17 @@ const CharmManagerContext = createContext<CharmManagerContextType>(null!);
1111

1212
export const CharmsManagerProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
1313
const { replicaName } = useParams<{ replicaName: string }>();
14-
const effectiveReplica = replicaName || "common-knowledge";
14+
15+
let effectiveReplica: string;
16+
if (replicaName) {
17+
// When a replica is provided in the URL, use it and save it as the last visited
18+
effectiveReplica = replicaName;
19+
localStorage.setItem("lastReplica", replicaName);
20+
} else {
21+
// Otherwise, pull the last visited replica from local storage.
22+
// Falling back to "common-knowledge" if nothing was stored.
23+
effectiveReplica = localStorage.getItem("lastReplica") || "common-knowledge";
24+
}
1525

1626
const charmManager = useMemo(() => {
1727
const storageType = (import.meta as any).env.VITE_STORAGE_TYPE ?? "remote";

0 commit comments

Comments
 (0)