Merge pull request #19618 from ElectronicBlueberry/fix-dangling-store-references

[24.2] Fix dangling workflow store references
This commit is contained in:
Marius van den Beek
2025-02-14 17:33:36 +01:00
committed by GitHub
2 changed files with 45 additions and 6 deletions
@@ -0,0 +1,30 @@
import type { Store } from "pinia";
const referenceCountByStore = new WeakMap<Store, number>();
/**
* Reference counts a store, and provides a function to safely dispose it after a timeout.
* @param store store to reference count and dispose
* @param timeout how long to wait before reference counting and attempting a dispose.
* @returns dispose function
*/
export function useTimeoutStoreDispose(store: Store, timeout = 1000) {
const currentReferenceCount = referenceCountByStore.get(store) ?? 0;
referenceCountByStore.set(store, currentReferenceCount + 1);
const disposeIfReferenceFree = () => {
const referenceCount = referenceCountByStore.get(store) ?? 0;
if (referenceCount <= 0) {
store.$dispose();
}
};
const dispose = () => {
const referenceCount = referenceCountByStore.get(store) ?? 1;
referenceCountByStore.set(store, referenceCount - 1);
setTimeout(disposeIfReferenceFree, timeout);
};
return dispose;
}
+15 -6
View File
@@ -7,6 +7,8 @@ import { useWorkflowStateStore } from "@/stores/workflowEditorStateStore";
import { useWorkflowEditorToolbarStore } from "@/stores/workflowEditorToolbarStore";
import { useWorkflowStepStore } from "@/stores/workflowStepStore";
import { useTimeoutStoreDispose } from "./timeoutStoreDispose";
/**
* Creates stores scoped to a specific workflowId, and manages their lifetime.
* In child components, use `useWorkflowStores` instead.
@@ -30,13 +32,20 @@ export function provideScopedWorkflowStores(workflowId: Ref<string> | string) {
const toolbarStore = useWorkflowEditorToolbarStore(workflowId.value);
const undoRedoStore = useUndoRedoStore(workflowId.value);
const disposeConnectionStore = useTimeoutStoreDispose(connectionStore);
const disposeStateStore = useTimeoutStoreDispose(stateStore);
const disposeStepStore = useTimeoutStoreDispose(stepStore);
const disposeCommentStore = useTimeoutStoreDispose(commentStore);
const disposeToolbarStore = useTimeoutStoreDispose(toolbarStore);
const disposeUndoRedoStore = useTimeoutStoreDispose(undoRedoStore);
onScopeDispose(() => {
connectionStore.$dispose();
stateStore.$dispose();
stepStore.$dispose();
commentStore.$dispose();
toolbarStore.$dispose();
undoRedoStore.$dispose();
disposeConnectionStore();
disposeStateStore();
disposeStepStore();
disposeCommentStore();
disposeToolbarStore();
disposeUndoRedoStore();
});
return {