Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug: system.get(id) not working after restoring a snapshot #4873

Open
al66 opened this issue Apr 27, 2024 · 2 comments
Open

Bug: system.get(id) not working after restoring a snapshot #4873

al66 opened this issue Apr 27, 2024 · 2 comments
Labels

Comments

@al66
Copy link

al66 commented Apr 27, 2024

XState version

XState version 5

Description

After restoring the snapshot an error appears, when using actor.send with the reference determined by system.get(id).

TypeError: this.logic.transition is not a function

This error appaers only after serializing the snapshot!

The code for the test program is:

"use strict";

const { createMachine, createActor } = require('xstate');
const { v4: uuid } = require("uuid");

const { ParentMachine } = require("./parent");

const parentMachine = createMachine(ParentMachine);
const parent = createActor(parentMachine, { id: "parent", systemId: "parent" });
const childId = uuid();

console.log("Child Id", childId);
parent.start();
parent.send({ type: "start", childId });
parent.send({ type: "tick", id: childId });
const snapshot = parent.getPersistedSnapshot();
parent.stop();

console.log("Snapshot", snapshot);
const restored = JSON.parse(JSON.stringify(snapshot));
console.log("Snapshot", restored);

const parentRestored = createActor(parentMachine, { id: "parent", systemId: "parent", snapshot: restored });
parentRestored.start();
parentRestored.send({ type: "tick", id: childId });
parentRestored.send({ type: "stop" });

The machine defintion of the parent machine:

"use strict";

const { createMachine, assign } = require('xstate');

const { ChildMachine } = require("./child");

const ParentMachine = {
    id: "parent",
    initial: "idle",
    context: {
        count: 0,
        child: null
    },
    entry: [
        ({ context }) => console.log("ParentMachine created", context)
    ],
    states: {
        idle: {
            on: {
                start: {
                    target: "running",
                    actions: [
                        assign(({ spawn, event }) => { 
                            const machine = createMachine(ChildMachine);
                            const id = event.childId;
                            const child = spawn(machine, { id, systemId: id });                            
                            return { child };
                        })
                    ]
                }
            }
        },
        running: {
            on: {
                tick: {
                    actions: [
                        assign({ count: ctx => ctx.count + 1 }),
                        ({ system, event }) => {
                            console.log("ParentMachine tick", { event });
                            const child = system.get(event.id);
                            if (child) child.send(event);
                       }
                    ]
                },
                stop: {
                    target: "final"
                }
            }
        },
        final: {
            type: "final"
        }
    }
};

module.exports = {
    ParentMachine
};

The machine definition of the child machine:

"use strict";

const { assign } = require('xstate');

const ChildMachine = {
    initial: "running",
    context: {
        count: 0
    },
    entry: [
        ({ context }) => console.log("ChildMachine created", context)
    ],
    states: {
        running: {
            on: {
                tick: {
                    actions: [
                        assign({ count: ({ context }) => (context.count + 1) }),
                        ({ event }) => console.log("ChildMachine tick", event)
                    ]
                },
                stop: {
                    target: "final"
                }
            }
        },
        final: {
            type: "final"
        }
    }
};

module.exports = {
    ChildMachine
};

Expected result

The spawned actor should be also reachable by systemId after restoring a serialized snapshot.

Actual result

After restoring the snapshot an error appears, when using actor.send with the reference determined by system.get(id).

TypeError: this.logic.transition is not a function
    at Actor._process (C:\Daten\node\modules\imicros-core\node_modules\xstate\dist\raise-40b1a1f5.cjs.js:814:30)
    at Mailbox.flush (C:\Daten\node\modules\imicros-core\node_modules\xstate\dist\raise-40b1a1f5.cjs.js:45:12)
    at Mailbox.enqueue (C:\Daten\node\modules\imicros-core\node_modules\xstate\dist\raise-40b1a1f5.cjs.js:37:12)
    at Actor._send (C:\Daten\node\modules\imicros-core\node_modules\xstate\dist\raise-40b1a1f5.cjs.js:935:18)
    at Object._relay (C:\Daten\node\modules\imicros-core\node_modules\xstate\dist\raise-40b1a1f5.cjs.js:229:14)
    at Actor.send (C:\Daten\node\modules\imicros-core\node_modules\xstate\dist\raise-40b1a1f5.cjs.js:944:17)
    at ParentMachine.states.running.on.tick.actions (C:\Daten\node\modules\imicros-core\dev\flow\parent.js:42:46)
    at executeAction (C:\Daten\node\modules\imicros-core\node_modules\xstate\dist\raise-40b1a1f5.cjs.js:2233:7)
    at resolveAndExecuteActionsWithContext (C:\Daten\node\modules\imicros-core\node_modules\xstate\dist\raise-40b1a1f5.cjs.js:2237:9)
    at resolveActionsAndContext (C:\Daten\node\modules\imicros-core\node_modules\xstate\dist\raise-40b1a1f5.cjs.js:2268:21)

Reproduction

see provided code above...

Additional context

No response

@al66 al66 added the bug label Apr 27, 2024
@davidkpiano
Copy link
Member

Can you please put the code in a repo or on StackBlitz? Would make it easier to debug.

@al66
Copy link
Author

al66 commented May 6, 2024

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants