Skip to content

so5extra 1.6 Enveloped Msg Sending

Yauheni Akhotnikau edited this page Apr 21, 2023 · 1 revision

Purpose

Sending an enveloped message/signal is not an easy task without special tools. SObjectizer Core doesn't provide ready-to-use tools for simplification of sending of enveloped messages. Reimplementation of send() functions (like it is done for Revocable Messages and Revocable Timers) is a boring and complex task. Because of that, there is a need for some tool(s) that allows to:

  • creation of message to be sent as payload inside an envelope;
  • creation of an envelope with this message inside;
  • sending this envelope to an appropriate destination (including send_delayed and send_periodic functionality).

Since v.1.2.0 so5extra provides a family of make()-envelope()-send_to() functions those can be used as such tools.

Header File

The stuff described below is defined in so_5_extra/enveloped_msg/send_functions.hpp header file. So to use this functionality it is necessary to include that file and so_5/all.hpp file:

#include <so_5_extra/enveloped_msg/send_functions.hpp>

#include <so_5/all.hpp>

Making And Sending Enveloped Messages

To make, envelope and then send an enveloped message it is necessary to use chain of make(), envelope() and send_to() functions. For example:

// Create message of type my_message, envelop it into my_envelope
// and then send it to the mbox mb1.
so_5::mbox_t mb1 = ...;
so_5::extra::enveloped_msg::make<my_message>(...)
        .envelope<my_envelope>(...)
        .send_to(mb1);

This chains creates an instance of my_message class (this is performed by make() call). Then the message created is enveloped into a new envelope of type my_envelope (this is performed by envelope() call). And then the envelope is sent to mbox mb1.

There are several forms of send_to() functions, including send_delayed_to() and send_periodic_to():

// Create message of type my_message, envelop it into my_envelope
// and then send it to the mchain ch1.
so_5::mchain_t ch1 = ...;
so_5::extra::enveloped_msg::make<my_message>(...)
      .envelope<my_envelope>(...)
      .send_to(ch1);
 
// Create message of type my_message, envelop it into my_envelope
// and then send it to the direct mbox of the agent a1.
so_5::agent_t & a1 = ...;
so_5::extra::enveloped_msg::make<my_message>(...)
      .envelope<my_envelope>(...)
      .send_to(a1);
 
// Create message of type my_message, envelop it into my_envelope
// and then send it to the mbox mb1 as delayed message.
so_5::mbox_t mb1 = ...;
so_5::extra::enveloped_msg::make<my_message>(...)
      .envelope<my_envelope>(...)
      .send_delayed_to(mb1, 10s);
 
// Create message of type my_message, envelop it into my_envelope
// and then send it to the mchain ch1 as delayed message.
so_5::mchain_t ch1 = ...;
so_5::extra::enveloped_msg::make<my_message>(...)
      .envelope<my_envelope>(...)
      .send_delayed_to(ch1, 10s);
 
// Create message of type my_message, envelop it into my_envelope
// and then send it to the direct mbox of the agent a1 as delayed message.
so_5::agent_t & a1 = ...;
so_5::extra::enveloped_msg::make<my_message>(...)
      .envelope<my_envelope>(...)
      .send_delayed_to(a1, 10s);
 
// Create message of type my_message, envelop it into my_envelope
// and then send it to the mbox mb1 as periodic message.
so_5::mbox_t mb1 = ...;
auto timer_id = so_5::extra::enveloped_msg::make<my_message>(...)
      .envelope<my_envelope>(...)
      .send_periodic_to(mb1, 10s, 30s);
 
// Create message of type my_message, envelop it into my_envelope
// and then send it to the mchain ch1 as delayed message.
so_5::mchain_t ch1 = ...;
auto timer_id = so_5::extra::enveloped_msg::make<my_message>(...)
      .envelope<my_envelope>(...)
      .send_periodic_to(ch1, 10s, 30s);
 
// Create message of type my_message, envelop it into my_envelope
// and then send it to the direct mbox of the agent a1 as delayed message.
so_5::agent_t & a1 = ...;
auto timer_id = so_5::extra::enveloped_msg::make<my_message>(...)
      .envelope<my_envelope>(...)
      .send_periodic_to(a1, 10s, 30s);

Enveloped Envelopes

There can be several calls to envelope(). It allows to envelop an envelope into another envelope:

so_5::extra::enveloped_msg::make<my_message>(...)
    .envelope<inner_envelope_type>(...)
    .envelope<outer_envelope_type>(...)
    .send_to(mbox);

In that case, an instance of my_message will be enveloped into an envelope of type inner_envelope_type. And envelope of type inner_envelope_type will be enveloped into an envelope of type outer_envelope_type.

Requirements For Envelope's Constructor

There is a requirement for envelope's constructors: the first argument of a constructor should be of type so_5::message_ref_t or const so_5::message_ref_t&. This argument is used to passing the payload into an envelope. All other arguments of a constructor can be arbitrary, but they should match to arguments passed to envelope() method.

For example:

class my_envelope final : public so_5::extra::enveloped_msg::just_envelope_t {
    using base_type = so_5::extra::enveloped_msg::just_envelope_t;
    
    std::chrono::steady_clock::time_point not_before_;
    std::chrono::steady_clock::time_point not_after_;
    
public:
    my_envelope(
        so_5::message_ref_t payload,
        std::chrono::steady_clock::time_point not_before,
        std::chrono::steady_clock::time_point not_after)
        : base_type{std::move(payload)}
        , not_before_{not_before}, not_after_{not_after}
        {}
    ...
};
...
const auto now = std::chrono::steady_clock::now();
so_5::extra::enveloped_msg::make<my_message>(...)
    .envelope<my_envelope>(now+10s, now+1m)
    .send_to(mbox);
Clone this wiki locally