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

invoke dynamic child machines #182

Closed
sytabaresa opened this issue Aug 10, 2022 · 5 comments
Closed

invoke dynamic child machines #182

sytabaresa opened this issue Aug 10, 2022 · 5 comments

Comments

@sytabaresa
Copy link
Contributor

sytabaresa commented Aug 10, 2022

Hi robot team!

It's posible this dynamic root/child machine implementation?:

import {
    createMachine,
    interpret,
    invoke,
    reduce,
    state,
    transition
} from "robot3";
// import 'robot3/debug';

let poolOfMachines = {
    switch: createMachine({
        inactive: state(
            transition('toggle', 'active')
        ),
        active: state(
            transition('toggle', 'end')
        ),
        end: state(),
    }),
    stoplight: createMachine({
        red: state(
            transition('toggle', 'yellow')
        ),
        yellow: state(
            transition('toggle', 'green')
        ),
        green: state(
            transition('toggle', 'red')
        ),
    })
}

let rootMachine = createMachine({
    step1: state(
        transition('LOAD', 'step1',
            reduce((ctx, ev) => ({
                ...ctx,
                machineName: ev.value
            }))
        ),
        transition('RUN', 'step2')
    ),
    // this dynamic kind of invoke
    step2: invoke((ctx, ev) => poolOfMachines[ev.value ? ev.vale : ctx.machineName],
        transition('done', 'step1')
    ),
    // step2: invoke(poolOfMachines['switch'],
    //     transition('done', 'step1')
    // ),
    end: state()
})

let service = interpret(rootMachine, (service) => {
    console.log(service.machine.current)
    if (service.child)
        console.log(service.child.machine.current)

}) // state: step1
service.send({
    type: 'LOAD',
    value: 'switch'
}) // state: step1
service.send('RUN') // invoke switch machine, state: step2.inactive

// switch child machine
service.child.send('toggle') // state:step3.active
service.child.send('toggle') // state:step3.end -> step1

service.send({
    type: 'RUN',
    value: 'stoplight'
}) // invoke stoplight machine, state: step2.red

// stoplight child machine
service.child.send('toggle') // state:step3.yellow
service.child.send('toggle') // state:step3.green
service.child.send('toggle') // state:step3.red
//...

I am trying to implement a plugin oriented machine system that can change the child machine based on runtime arguments, like a UI interface that have a root controller machine and many child plugin command machines. I know that its possible to interpret the child machine inside a promise invoked in step3 but that approach miss the nested send mechanism and other things.

Thanks for you attention.

@sytabaresa sytabaresa changed the title Create dynamic child machines invoke dynamic child machines Aug 10, 2022
@matthewp
Copy link
Owner

I think this is a valid way to model the behavior yeah. Are you saying it isn't working?

@sytabaresa
Copy link
Contributor Author

I guess that in step2 the invoke form that I use is not valid, because its a function that returns a machine (dynamic machine) instead a promise. I think that could be a good API but in this moment is not supported

@matthewp
Copy link
Owner

Oh right, sorry. We do treat all functions as being promising-returning at the moment. That's an interesting pattern though. Maybe it's something we could support in the future.

@sytabaresa
Copy link
Contributor Author

I made a PR to add support to this, hoping that you can review it 😁

@brandonpittman
Copy link

Since #183 got merged, this issue should be able to be closed.

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

No branches or pull requests

3 participants