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

Multiple callbacks active at the same time #30

Closed
bit-pirate opened this issue Aug 18, 2015 · 5 comments
Closed

Multiple callbacks active at the same time #30

bit-pirate opened this issue Aug 18, 2015 · 5 comments
Labels

Comments

@bit-pirate
Copy link
Contributor

Currently most of my state logic is contained in on_enter callbacks. Since in some states I have to periodical checks, these callbacks run until the sate finishes.

Now I just noticed that it is possible that the on_enter CB of the following state is activated, while the old callback hasn't finished yet. Is this behaviour desired?

In my case I probably will have to start using mutexes ... 😖

@tyarkoni
Copy link
Member

Callbacks are called sequentially (callback C2 shouldn't run until C1 returns), so in general, there shouldn't be multiple callbacks running at the same time unless you're launching new threads within one or more callbacks--in which case all bets are off. That said, one exception is that if you have a callback that itself triggers a state change, then yes, you could very well end up in a situation where the on_enter callback of a new state is activated before the last state's on_enter has finished.

I agree that this is not really desirable behavior, but I think it would be very complicated to solve this problem in a general way, and I want to avoid adding a lot of additional logic for what is probably a fairly uncommon use case. But if you have ideas for a relatively simple fix, I'd be happy to consider it.

@bit-pirate
Copy link
Contributor Author

unless you're launching new threads

No threads, but

one exception is that if you have a callback that itself triggers a state change

I'm guilty of this one. So, I'm a misusing the callbacks here?

In my case I like the states to do some work (if in state A do this, in B do that). Where would I hook this kind of behaviour in? So far I'm putting this in the on_enter callbacks and some of them are triggering the state change.

@bit-pirate
Copy link
Contributor Author

Have been pondering about my implementation a bit.

So, if I would move the trigger call out of the callback, then I would need to create separate worker methods. Those would do the actual work and when finished trigger the transition to the next state.

Now looking at implementing this, I cannot see another straight-forward approach apart from the "if state A do this, if state B do that", which you have mentioned in your blog post:

if state == 'consent' and user_response == 'Agree':
    state = 'demographics'
elif state == 'demographics' and validate_demographics(data):
    save_demographics()
    state = 'personality'
...

But then again, I started using this package in order to avoid this approach.

Am I missing something here? Do you have more advanced sample code some where?

In my case there are several states with while loops in which another process is polled for information to decide on state transitions depending on the retrieved data.

@tyarkoni
Copy link
Member

I don't think you're doing anything wrong; ideally the package would support asynchronous and/or appropriately prioritized callbacks. It's just that the original goal was to build something very lightweight that met my own needs, which are mostly centered around web applications where transitions are usually triggered by discrete requests from a user and states and associated data are quickly serialized to the DB after each request. Building something that can handle prioritization and async calls starts to get away from that. (For what it's worth, virtually all of the other Python/Ruby FSM implementations I've seen would have the same issue.)

In any case, I'll think some more about potential ways to implement a solution to your problem that wouldn't require a lot of new code. Right now everything I can think of seems pretty convoluted. Would love to hear suggestions if anyone else has any.

@tyarkoni
Copy link
Member

Closing this and labeling wontfix for now. Still open to ideas though.

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