Futurescale, Inc. PureMVC Home

The PureMVC Framework Code at the Speed of Thought


Over 10 years of community discussion and knowledge are maintained here as a read-only archive.

New discussions should be taken up in issues on the appropriate projects at https://github.com/PureMVC

Pages: [1]
Print
Author Topic: Needed(?): ICommand to receive Notification events  (Read 13233 times)
mbiggerstaff
Newbie
*
Posts: 4


View Profile Email
« on: July 02, 2009, 05:17:43 »

Greetings.

Hello. I am relatively new to PureMVC.  I have some questions about ICommand, AsyncCommand and related elements.  I'm sorry this post is so long. I wanted to make certain I gave a full accounting of the notification issue I asking for suggestions about.

I have worked through the Sequential demo and understand how it works.  No questions about it.  My questions are more about error detection and process control during success/fail states for asynchronous command events.

My goal: I need "transactionable" AsyncCommands which can detect successful and unsuccessful results of the execution of asynchronous mediator function calls.  This means (or seems to mean) I need a ICommand class/solution that executes a asynchronous function on a mediator and waits for the asynchronous results of that mediator action to be delivered to the Command in an asynchronous manner.

Background: I have a series of commands that will be executed in an AsyncMacroCommand derivation. If one AsyncCommand registers failure, I need to detect this and (potentially) abort the entire series of commands, retry the failed command and/or ignore the error entirely and continue executing steps.  The success use case is already working.

Pseudo Call Diagram:

   MyAsyncCommand.execute()
    +--(calls)--> MyMediator's function1()
                  {
                     // async method invoked
                     executes/starts a non-PureMVC asynchronous task
                  }

                  MyMediator's function2( some event )
                  {
                     // async method results delivered here

                     // Success/fail of asynch. MyMediator.function1() execution.
                     // Set some state so MyAsyncCommand knows the status
                     //    but how ???
                              /
                  }          /
                            /
... Magic occurs here ...  /
                          /
  MyAsyncCommand.resultsFunction( some event )
  {
     if ( some event == success )
        sendNotificiation( MyAsyncCommand.success )
     else
        sendNotificiation( MyAsyncCommand.failed )

     commandComplete();
  }


My specific question:  how can I get a ICommand/AsyncCommand to confirm that an asynchronous action, performed by a Mediator, was completed un/successfully?

Workaround/"Bad Idea" #1: I could setup the AsyncCommand on a timer and keep asking the mediator for status.  I would really rather not that this direction.

While ICommand can send notification events, it can not receive notification events.  In the problem I am trying to solve, I have asynchronous actions which are invoked from a mediator because of an AsyncCommmand.  However, I need for the AsyncCommmand to only finish execution (ie. call commandComplete()) when it has confirmed the mediator's asynchronous task has completed successfully or unsuccessfully.

If a ICommand supported the handleNotification() method, then I'd be able to listen of status notifications from the Mediator this way.

Workaround/"Bad Idea" #2: create a hybrid IMediator/ICommand that can execute behaviors and listen for the results.  I'd rather not reinvent this complicated wheel if don't have to.

What's the correct approach here?

Mike B.

PS I have working code for all but the success/failure notification from the Mediator to a AsyncCommand.  Just need a (correct) "pattern" for this problem set to integrate.
Logged
puremvc
Global Moderator
Hero Member
*****
Posts: 2871



View Profile WWW Email
« Reply #1 on: July 02, 2009, 03:30:15 »

In the time since this utility was released, it has been shown that the thread of execution does not stop during the execution of a single AsyncCommand.

Therefore I personally suggest dropping them altogether and using the StateMachine utility instead. It will guarantee that you can perform async actions and not move to the next state until the action is complete and the StateMachine notified. Also, defining discrete states for your app is a really excellent way to describe and understand its behavior.

Have a listen to the StateMachine Overview http://puremvc.tv/#P003/

-=Cliff>
Logged
mbiggerstaff
Newbie
*
Posts: 4


View Profile Email
« Reply #2 on: July 03, 2009, 12:39:38 »

Thanks Cliff.  I've looked over the state machine video and started on the stopwatch demo. I suspect you are correct that the state machine is what I actually need.

Thanks again.
Mike


Logged
mbiggerstaff
Newbie
*
Posts: 4


View Profile Email
« Reply #3 on: July 03, 2009, 05:08:26 »

CLiff and all,

After reviewing the StateMachine doc.s, code and demo, I'm looking for a good place to put in my "rollback" code for when a transition is canceled.

  • Is a "silent abort" the only option for canceled/aborted operations?
   
From what I read and what I see in the StateMachine code, reception of a StateMachine.CANCEL message in StateMachine.transitionTo(..) causes a "silent abort" of the chain of transitions.  Thus, we have to know if the process is going to fail before we move to the next transition and do clean up before we are canceled (?)

Why does state transition object not have a canceled action?  We have the two transition guards entering and exiting on the State object and a declared action for a transaction state.  Seems only natural (to me) to have an optional canceled action on transition elements.  I would not expect the canceled/"rollback" command to have all the state-restricted behaviors at this point since we're already in a potential error state. 

Unless I am missing something critical, this should not be difficult to implement in the StateMachine code. With this additional feature, "Abort, Retry, Ignore" behaviors can be added easily.

FMS XML Example:
   <fsm initial="CLOSED">
      <state name="OPENED" entering="openingNote" exiting="aboutToCloseNote">
         <transition action="CLOSE" target="CLOSED" canceled="CLEAR_DOOR_PERIMETER"/>
      </state>
      <state name="CLOSED" entering="closingNote">
         <transition action="OPEN" target="OPENED" canceled="CLEAR_DOOR_PERIMETER"/>
         <transition action="LOCK" target="UNLOCKED" canceled="RESET_DOOR_ALIGNMENT"/>
      </state>
      <state name="LOCKED" entering="lockingNote">
         <transition action="UNLOCK" target="CLOSED" canceled="RESET_DOOR_ALIGNMENT"/>
      </state>
   </fsm>


StateMachine.as, line: 99
   // Going nowhere?
   if ( nextState == null ) return;
   
   // Clear the cancel flag
   canceled = false;
   
   // Exit the current State
   if ( currentState && currentState.exiting ) sendNotification( currentState.exiting, data, nextState.name );

   // Check to see whether the exiting guard has canceled the transition
   if ( canceled ) {
      if ( currentState.cancelAction != null )
      { 
         // offer opportunity to:
         //   Ignore this error - cancelAction resets canceled action
         //   Retry - (re)configure to retry this action...
         //   Continue Abort after clean up - clean up the transition and then end
         sendNotification( currentState.cancelAction, data, nextState.name );
      }
      if ( canceled )
      {

         canceled = false;
         return;
      }
   }
   
   // Enter the next State
   if ( nextState.entering ) sendNotification( nextState.entering, data );


Regards,
Mike

Logged
puremvc
Global Moderator
Hero Member
*****
Posts: 2871



View Profile WWW Email
« Reply #4 on: July 03, 2009, 03:54:28 »

There is no need for 'rollback'.

If a transition is canceled, that's it, you're still in the old state and never transitioned to the new state.

Use the exiting and  entering announcements as GUARDS only, for determining whether you should be allowed to exit the current state or enter the new state, sending a StateMachine.CANCEL if need be.

DO NOT initiate any teardown or build up in anticipation of the new state until the transition has completely taken placed, and the state-specific changed announcement or the StateMachine.CHANGED note is sent.

-=Cliff>
« Last Edit: July 03, 2009, 03:58:07 by puremvc » Logged
mbiggerstaff
Newbie
*
Posts: 4


View Profile Email
« Reply #5 on: July 06, 2009, 01:57:23 »

Cliff / all,

Cliff:  Good morning.  I appreciate your time spent on my forum posts.  I will try to bring it to close very shortly.

In regards to the "rollback" discussion, respectfully, I believe we are both right; its just a matter of command granularity.

If the StateMachine is used only for "atomic actions" (ICommands whose execution is only [potentially] depend a previous state), then yes, you are correct: we don't (necessarily) need a rollback since we are left in a "safe state".

However, I will be using using a AsyncMacroCommand to execute a series of related AsyncCommands, controlled by a StateMachine where only the successful execution of all ICommands in an AsyncMacroCommand will constitute "success".

With this requirement, if the any ICommands fails during the execution of AsyncMacroCommand, I need to restore the StateMachine to the initial starting state ( "rolling back", executing whatever ICommands are need to restore the state.) 

As I mentioned in my first post, this is a transactional model: all ICommands must succeed OR restore to the original state.  Under this transactional model, it can't not stop in the middle of a series of actions.

Does this transactional requirement fit within the current implementation of StateMachine, AsyncMacroCommand and AsyncCommand?  If no and with the modifications mentioned in my previous post, do you believe that will provide the ability to execute transaction-ed commands?

Regards,
Mike

Logged
puremvc
Global Moderator
Hero Member
*****
Posts: 2871



View Profile WWW Email
« Reply #6 on: July 06, 2009, 07:16:50 »

The StateMachine doesn't (and probably won't ever) manage transactional requirements. The creepy feature creature is always at the door, suggesting more and more functionality. The next thing you know, it's so complex and difficult to understand that no one wants to use it. So, we're trying to keep it simple.

If you are in State A and you want to run an AsyncMacroCommand and only move to State B if all its sub-commands pass, then don't send the StateMachine.ACTION until that has taken place. This way there is nothing to roll back and no potential for leaving the app in a questionable state.

-=Cliff>
Logged
Pages: [1]
Print