Stiffstream / sobjectizer

An implementation of Actor, Publish-Subscribe, and CSP models in one rather small C++ framework. With performance, quality, and stability proved by years in the production.

Home Page:https://stiffstream.com/en/products/sobjectizer.html

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

[Best practice] How to unsubscribe from all remaining messages on shutdown?

ilpropheta opened this issue · comments

Hi,
suppose I have an agent that can be slow at processing incoming messages. Under some circumstances, I don't want to wait for it to complete when shutdown is sent from the environment, instead I want to terminate it immediately.

The agent is subscribed to a SPMC message box that might contain several messages already. I just want to ignore them all when shutdown is requested.

I had a look at stop guards but I am not sure this is the way to go (it seems to me that they solve exactly the opposite problem).

What's the best practice to get such a behavior?

Let's start from a skeleton of that agent:

class SlowAgent : public so_5::agent_t
{
public:
	SlowAgent(context_t c, so_5::mbox_t input)
		: agent_t(std::move(c)), m_input(std::move(input))
	{
	}

protected:
	void so_define_agent() override
	{
		so_subscribe_self().event([](int i) {
			// just fake some slow processing...
			std::cout << "doing " << i << "\n";
			Sleep(1000);
			std::cout << "done\n";
		});
	}
	
private:
	so_5::mbox_t m_input;
};

Thanks!

Hi!

It's not an easy question. Let me take some time to think about it.

It seems that this case requires support of messages with different priorities. In that case you can have msg_do_something_heavy with low priority and msg_shutdown with high priority. It allows to switch an agent in a different state when msg_shutdown arrives (message msg_do_something_heavy will just be ignored in that state):

class SlowAgent : public so_5::agent_t
{
  state_t st_normal{this};
  state_t st_shut_down{this};
  ...
public:
  void so_define_agent() override
  {
    this >>= st_normal;
    st_normal
      .event([](mhood_t<msg_do_something_heavy> cmd) {
        ... // Some time-consuming processing.
      })
      .event([this](mhood_t<msg_shutdown>) {
        this >> st_shut_down; // Or call so_deactivate_agent().
      });
    // No subscription for st_shut_down.
  }
  ...
};

In that case, you send a msg_shutdown message before shutting your agent. That message will be delivered before any other messages that are already in the event queue (like msg_do_something_heavy). The agent will be switched to a state in that all other messages will just be ignored.

But SO-5.6/5.7 doesn't support message priorities.

There is an example how a dispatcher with priorities can be implemented: https://github.com/Stiffstream/so5_custom_queue_disps_demo
And the description of that example in Russian: https://habr.com/ru/post/531566/ (Hope a service like Google Translate or DeepL can help here).

Thanks @eao197 for your response. Message priorities would be the perfect fit. However, at the moment I don't want to introduce too much "custom code" around the framework.

Actually, I have redesigned the data flow of this particular agent in terms of a message chain and solved this problem by closing it with drop_content. It's not as slick as with message priorities but it's an acceptable trade-off at the moment.

Any future plans for making them a standard feature?

Any future plans for making them a standard feature?

Because it's another time when message priorities are discussed this feature has to be added to SObjectizer in some form (maybe in the form of another dispatcher). But it's hard to predict when it could be done in the current situation. I hope github won't be closed for my country.

Sure @eao197 , the current situation is critical and definitely much more important than any other things right now. Definitely impossible to make any predictions.