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

Add custom handler for events for which there is no any handler in current state #10

Open
zamazan4ik opened this issue May 31, 2020 · 5 comments

Comments

@zamazan4ik
Copy link
Contributor

zamazan4ik commented May 31, 2020

Hi!

I am trying to use FSM functionality, which is already integrated into SObjectizer (btw thatnk you a lot for such architecture design - that's very useful in an agent development).

I understand, how can I switch between states, how can I add different event handlers for different states.

In my situation I should add custom reaction (more precisely - sent a message to another agent, which is used for error logging) for events, which is sent to an agent and were not handled since for them were not found any handler (e.g. an event A is not allowed in a state ST and I want to notify about such situation my error-handling agent).

Is there any way for doing such stuff? E.g. in Boost.SML it can be done. See https://boost-experimental.github.io/sml/examples.html#error-handling - work with unexpected_event (btw if you see any features, which are missed in SObjectizer implementation of FSM and there are in Boost.SML, would be fine to add them into SObjectizer as well :) )

I've already checked an example about no_handler_message_tracing: https://github.com/Stiffstream/sobjectizer/blob/master/dev/sample/so_5/nohandler_msg_tracing/main.cpp
But I don't think that it is usable in my situation.

Thank you.

@eao197
Copy link
Member

eao197 commented May 31, 2020

If I understand you correctly, deadletter-handlers can help here. There is also a small example of deadletter-handler in the standard SObjectizer's examples.

@zamazan4ik
Copy link
Contributor Author

zamazan4ik commented May 31, 2020

Thank you. If I understand correctly, I shall manually register any possible event in deadletter handler. Is it possible somehow add a generic deadletter handler for any event, for which there is no other handlers? I don't want to register all possible events in my system manually in a deadletter handler.

Probably I should explain a little bit, why it's important for me. In my system there are lot of different events. Different subsets can be handled only in different states. If they send to not corresponding state - they must be ignored with proper logging. Manual registration of a new event to a deadletter handler is not a good solution here since I just can forget about registration in different deadletter nadlers in my system.

Mentioned above Boost.SML has such feature:

"unexpected events handling"_s  + unexpected_event<_> / [] { std::cout << "generic unexpected event" << std::endl; }

@eao197
Copy link
Member

eao197 commented May 31, 2020

SObjectizer doesn't allow the handling of a message of unknown type. That is why a subscription is possible only to a message of a particular type. And there is no way to do "a generic" message handler that can handle any message type (or a message of some subtype).

Messages of any type can be sent to a receiver, but if there is no a subscription for a particular message type that message will be thrown out. This is a specific of SObjectizer. At least for its current form.

And the case is the same for deadletter handlers. That is why you can't have "a generic" deadletter handler.

@zamazan4ik
Copy link
Contributor Author

Hm... Thanks. Seems like the best solution here for will be:

  • Introduce "generic" deadletter handler for all agents in the system (probably as a base class for all agents - I should recheck the possibility for doing such thing with SObjectizer)
  • When new event is introduced in the system - register it in the "generic" deadletter handler. Since I don't see any easy autocheck for automatic finding problems like "You've introduced new event but forgot to register it in the deadletter handler" - here will be some manual work
  • Register the "generic" deadletter handler for all corresponding agents in the system

Hope it'll work. Thank you!

@eao197
Copy link
Member

eao197 commented Jun 1, 2020

I think a trick with the usage of custom mbox and custom message envelope can be used here to avoid manual work.

The scheme is:

  • you create your own custom mbox that envelopes every message into your special envelope. Then this mbox passes the new enveloped message to the actual destination mbox. A proxy from so5extra can be used for the simplification of this task;
  • then you use your custom mbox instance instead of mbox of your agent. It means that you give a reference to your custom mbox to message senders instead of agent's direct mbox;
  • your special envelope has a boolean flag inside. That flag is set to true if a message is delivered to the destination. It means that the flag is set to true only in access_hook with access_context_t::handler_found argument;
  • you check this flag in the destructor of your special envelope and if it isn't true you log the fact that message wasn't handled.

A just_envelope_t from so5extra can be used for the simplification of the implementation of your special envelope.

PS. I'm afraid there is no easier way. I don't even see a good way to extend SObjectizer's functionality to simplify the task of handling missed (unexpected) messages. It's because an obvious approach of addition some so_unexpected_message virtual method to agent_t will conflict with adv_thread_pool dispatcher, where complex scheme with postponing of events is used. Maybe another solution can be invented here, but it's impossible to predict when it can be found and how quickly it can be implemented into SObjectizer.

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

2 participants