int agent_behavior_test()
{
struct sig_cs_start final : public so_5::signal_t
{
};
struct sig_cs_calling final : public so_5::signal_t
{
};
struct sig_cs_established final : public so_5::signal_t
{
};
struct sig_cs_finished final : public so_5::signal_t
{
};
struct sig_cs_terminated final : public so_5::signal_t
{
};
struct sig_ag_login final : public so_5::signal_t
{
};
struct sig_ag_logout final : public so_5::signal_t
{
};
struct sig_ag_ready final : public so_5::signal_t
{
};
class test_agent : public so_5::agent_t
{
so_5::state_t st_ag_login{this, "agent is logged in"};
so_5::state_t st_ag_ready{initial_substate_of{st_ag_login}, "agent is ready"};
so_5::state_t st_ag_calling{substate_of{st_ag_login}, "agent is calling"};
so_5::state_t st_ag_onphone{substate_of{st_ag_login}, "agent is onphone"};
so_5::state_t st_ag_wrapup{substate_of{st_ag_login}, "agent is wrapup"};
so_5::state_t st_ag_busy{substate_of{st_ag_login}, "agent is busy"};
so_5::state_t st_ag_logout{this, "agent is logged out"};
public:
test_agent(
context_t ctx, const so_5::mbox_t &mbox, int account_id) : so_5::agent_t(ctx),
m_account_id(account_id),
m_mbox(mbox) {}
void so_define_agent() override
{
this >>= st_ag_login;
so_subscribe(m_mbox)
.in(st_ag_wrapup)
.event(&test_agent::on_sig_ag_ready);
so_subscribe(m_mbox)
.in(st_ag_ready)
.event(&test_agent::on_sig_cs_start);
so_subscribe(m_mbox)
.in(st_ag_ready)
.event(&test_agent::on_sig_cs_calling);
so_subscribe(m_mbox)
.in(st_ag_calling)
.event(&test_agent::on_sig_cs_established);
so_subscribe(m_mbox)
.in(st_ag_onphone)
.in(st_ag_calling)
.event(&test_agent::on_sig_cs_finished);
so_subscribe(m_mbox)
.in(st_ag_ready)
.in(st_ag_wrapup)
.event(&test_agent::on_sig_cs_terminated);
so_subscribe(m_mbox)
.in(st_ag_logout)
.event(&test_agent::on_sig_ag_login);
so_subscribe(m_mbox)
.in(st_ag_login)
.event(&test_agent::on_sig_ag_logout);
}
private:
void on_sig_ag_ready(so_5::mhood_t<sig_ag_ready>)
{
cur_state();
if (incoming_logout) {
this >>= st_ag_logout;
incoming_logout = false;
ag_log() << "agent has been logged out";
} else {
this >>= st_ag_ready;
}
cur_state();
}
void on_sig_cs_start(so_5::mhood_t<sig_cs_start>)
{
ag_log() << "incoming sig_cs_started";
}
void on_sig_cs_calling(so_5::mhood_t<sig_cs_calling>)
{
cur_state();
this >>= st_ag_calling;
cur_state();
}
void on_sig_cs_established(so_5::mhood_t<sig_cs_established>)
{
cur_state();
this >>= st_ag_onphone;
incoming_logout = true;
cur_state();
}
void on_sig_cs_finished(so_5::mhood_t<sig_cs_finished>)
{
cur_state();
if (st_ag_onphone == so_current_state())
{
this >>= st_ag_wrapup;
so_5::send_delayed<sig_ag_ready>(m_mbox, std::chrono::seconds(2));
}
else
{
this >>= st_ag_ready;
}
cur_state();
}
void on_sig_cs_terminated(so_5::mhood_t<sig_cs_terminated>)
{
ag_log() << "incoming sig_cs_terminated";
}
void on_sig_ag_login(so_5::mhood_t<sig_ag_login>)
{
cur_state();
this >>= st_ag_ready;
cur_state();
}
void on_sig_ag_logout(so_5::mhood_t<sig_ag_logout>)
{
cur_state();
ag_log() << "logout event is coming, the agent supposed to be looged out as soon as it become ready";
incoming_logout = true;
cur_state();
}
private:
const int m_account_id;
so_5::mbox_t m_mbox;
bool incoming_logout = false;
};
try
{
so_5::launch([](so_5::environment_t &env) {
logger::create_logger_actor(env);
namespace pool_disp = so_5::disp::adv_thread_pool;
so_5::mbox_t mbox = env.create_mbox();
env.introduce_coop(
pool_disp::make_dispatcher(env, 2).binder(
pool_disp::bind_params_t{}.fifo(pool_disp::fifo_t::individual)),
[&mbox](so_5::coop_t &coop) {
coop.make_agent<test_agent>(mbox, 42);
});
so_5::send<sig_cs_start>(mbox);
so_5::send<sig_cs_calling>(mbox);
so_5::send<sig_ag_logout>(mbox);
so_5::send<sig_cs_established>(mbox);
so_5::send<sig_cs_finished>(mbox);
so_5::send<sig_cs_terminated>(mbox);
});
}
catch (const std::exception &ex)
{
std::cerr << "Error: " << ex.what() << std::endl;
return 1;
}
return 0;
}
звонок начинается со sig_cs_start и заканчивается sig_cs_terminated. сигнал sig_ag_logout приходит с админки в момент когда агент находится на звонке (calling). он должен запомнить это событие, завершить звонок и только когда будет опять перейдет в состояние ожидания (ready) проверить флаг и разлогиниться. я просто думал что есть способ обойтись без дополнительного флага и как-то через хистори или отложенное событие, я не знаю есть ли такая возможность, отложить обработку logout.