You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
In our Mailbox actor protocol, the target machine must send CHILD_IDLE to Mailbox for reporting it's in idle state.
However, there has a situation that, the target machine is in state idle, but the Mailbox think it's not in idle:
The target machine received a new message when it's idle, the Mailbox set it as busy
The target has a state with always: States.idle transition back to idle, with its entry use Mailbox.Actions.reply() (it's just a sendParent wrapper) to send a message to the original message sender (actor)
If that message received by the origin message sender(actor), triggered another message sent as a reply to the Mailbox, then this race condition will happen:
The target machine is in idle state, but the Mailbox.Actions.idle() in the entry of the idle state (a wrapper of sendParent('CHILD_IDLE')) has not been executed yet: it's in the actions list and wait for the return of the previous Mailbox.Actions.reply() to return
The mailbox has not received the CHILD_IDLE so it thinks the target is in the busy state
The target actually can receive the new message, which makes this new message pass-through the mailbox, without setting the current message origin, which means this message can not be replied to in the future.
If the target machine replies to this new message, then the reply message will be sent to the previous message, which is not right.
This is a 4+ hours debugging journey.
Workaround 1
Use after with a timeout of 0 (like setImmediate) to put the future tasks at the end of the event queue, so that the Mailbox.Actions.idle()(wrapper of actions.sendParent('CHILD_IDLE')) can be executed before it.
In our Mailbox actor protocol, the target machine must send
CHILD_IDLE
to Mailbox for reporting it's inidle
state.However, there has a situation that, the target machine is in state idle, but the Mailbox think it's not in
idle
:idle
, the Mailbox set it asbusy
always: States.idle
transition back to idle, with its entry useMailbox.Actions.reply()
(it's just asendParent
wrapper) to send a message to the original message sender (actor)target
machine is inidle
state, but theMailbox.Actions.idle()
in the entry of the idle state (a wrapper ofsendParent('CHILD_IDLE')
) has not been executed yet: it's in the actions list and wait for the return of the previousMailbox.Actions.reply()
to returnCHILD_IDLE
so it thinks the target is in the busy statepass-through
the mailbox, without setting the current message origin, which means this message can not be replied to in the future.This is a 4+ hours debugging journey.
Workaround 1
Use
after
with a timeout of 0 (likesetImmediate
) to put the future tasks at the end of the event queue, so that theMailbox.Actions.idle()
(wrapper ofactions.sendParent('CHILD_IDLE')
) can be executed before it.Workaround 2
Use
delay
options when sending reply events inMailbox.Actions.reply
to put the action as a task in the future event loop:Related discussion
The text was updated successfully, but these errors were encountered: