Thanks for letting us know about this bug. In fact this was not a use-case we defined initially. I will look into the codebase and try to come up with a solution.
By the way, can you please explain exactly your real use-case here and why you would need a message to be dispatched in 2 different modules which may not be instantiated simultaneously ?
The problem in reality is that we cannot keep indefinitely messages in the queue to avoid any leaks and therefore the plan is to introduce a timeout property and basically it means that if you dispatch a message to a given module which is never instantiated, we don't want to keep indefinitely the message in the queue but delete it as soon as the timeout is reached.
Here with this use case you highlighted, it means that a same message dispatched can be handled by 2 different module types. However, if only moduleA is instantiated but not moduleB, the message would reach moduleA but the message would also have to be kept in the queue until moduleB is instantiated. In this situation if the timeout mechanism is in place, the message is going to be kept in the queue only for a limited amount of time and if your moduleB is within a ViewStack, we do not know when the user will move that next view which mean that we cannot guarantee that the moduleB will receive the message.
If your moduleB within this ViewStack (which may be instantiated at anytime thru a user gesture) needs to know about something, I would design this in the other way around. Instead of having the moduleB waiting to get a message, i would make sure that the moduleB is asking for what it needs when it is instantiated.
The idea is :
The shell application is doing several remote actions at startup (first a login, then getting some xml).
The shell is dispatching a UserEvent.USER_READY when all the actions have been completed.
When the login is done, the first module is automatically launched. (The second module is loaded when the user click on a togglebar.)
As long as the UserEvent message has not been dispatched, modules are not allowed to do anything. When they receive the message, they should both get a list of data from the server.
Because of the issue, when the second module is loaded at anytime later, it won't get the UserEvent message.
1 person found this helpful
Well what you propose as a solution to your problem is not going to work as in your scenario, you have multiple modules which are loaded at different times but more importantly we cannot actually predict when they are going to be loaded if they are loaded at all as its thru a user gesture and the user may never click the togglebar.
The mechanism in place for the module lib is that any message dispatched to a module which is not yet instantiated is going to stay in a queue but this message cannot stay indefinitely in the queue to avoid leaks so we plan to introduce a timeout mechanism which is going to clear the message from the queue as soon as the timeout is reached. basically each message will have a timeout attached to it.
Because in your case we cannot predict when a module is going to be available, and because the USER_READY is going to be most likely dispatched as soon as the user is logged-in and the bootstrap completed. We cannot guarantee that the USER_READY message is going to arrive in the desired modules as the modules may be loaded long after the USER_READY message was dispatched, which means that the timeout may have happened and therefore the message removed from the queue.
We may think of having in the module lib, timeout=-1 (which means that we never remove the messages from the queue) and have a way to manually clear the queue but I do not like this idea really because I think that the solution to the problem you expose here can be designed such a way it would be more robust and more OO
I think you must take this problem the other way around, instead of having your module waiting for something when they are instantiated, your modules must ask for what it need as soon as they are loaded.
A potential solution could be something like this:
- The USER_READY message should be first of all handled in the shell app and store the status in a shared model (shared between all modules and shell).
- Each module access the shared model as soon as they are loaded to look for the user status:
- If the user status is READY you do whatever you need to do
- If the user status is NOT_READY you wait until it is ready
- waiting for the user status to be ready can be done by Observing the user status from the shared model using the [Wire] tag from the ObserverParsley
Does it make sense ?
Sure it makes sense! Thanks for the detailed explanation and for providing a better solution.
I will have a look at the Wire tag from the ObserverParsley lib.
Keep up the good work with the Cairngorm libs, it's great to see you provide existing (and working) solutions to some features that are missing from the parsley lib.
This contradicts with the latest documentation in :
Specifically it says:
"Currently when a message is dispatched and the destination module is never loaded, the message is kept forever in the queue however we are currently working on improving this by providing a timeout to the queue so when the timeout occur, messages are cleaned from the queue."
I have a similar problem in that we dispatch an event from Module A, and Module B is yet to be initialized. When it is initialized the function that listens for that event with [MessageHandler] is never invoked.
I'm using Flex 4.5.1, Parsley 2.4.1 and Cairngorm's Module library 0.17.
In Flex 3, with a previous version of Parsley and a previous version ot the Module library, this worked. So I'm wondering whether something's changed for 0.17 and the documentation in sourceforge has not been updated.
I've applied a workaround for now, but ideally I would prefer it work with events.