Unverified Commit 120d4fca authored by Marius van den Beek's avatar Marius van den Beek Committed by GitHub
Browse files

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

[24.2] Fix dangling workflow store references
parents 82c428d3 b91415dd
Loading
Loading
Loading
Loading
+30 −0
Original line number Diff line number Diff line
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
Original line number Diff line number Diff line
@@ -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 {