53 lines
1.9 KiB
C++
53 lines
1.9 KiB
C++
#pragma once
|
|
|
|
#include "port_impl_base.hpp"
|
|
#include "port_types.hpp"
|
|
#include <stdexcept>
|
|
|
|
#define FMT_HEADER_ONLY
|
|
#include <fmt/format.h>
|
|
#include <fmt/ranges.h>
|
|
|
|
// Request transport: sends a payload and waits for a reply.
|
|
template <typename Port, typename Callback> class PortImpl<port_types_e::REQ, Port, Callback> : public PortImplBase<Port, Callback> {
|
|
public:
|
|
using base_t = PortImplBase<Port, Callback>;
|
|
PortImpl(const Port *port, zmq::context_t &zmq_ctx, const std::map<std::string, std::string> &endpoints, Callback &&callback)
|
|
: PortImplBase<Port, Callback>(port, zmq_ctx, endpoints, std::forward<Callback>(callback)) {
|
|
this->m_sock__ = zmq::socket_t(this->m_ctx__, zmq::socket_type::req);
|
|
|
|
for (const auto &[_, ep] : this->mc_endpoints__) {
|
|
this->m_sock__.connect(ep);
|
|
}
|
|
|
|
// Avoid blocking forever if no REP is available.
|
|
this->m_sock__.set(zmq::sockopt::rcvtimeo, static_cast<int>(base_t::sc_recv_timeout_ms__));
|
|
}
|
|
|
|
void send(const msgpack::sbuffer &data, const std::string &addr = "") const override {
|
|
try {
|
|
zmq::message_t reply;
|
|
this->m_sock__.send(zmq::message_t(data.data(), data.size()), zmq::send_flags::none);
|
|
|
|
this->m_sock__.recv(reply, zmq::recv_flags::none).and_then([&](const auto &res) {
|
|
typename base_t::port_payload_s payload;
|
|
|
|
msgpack::sbuffer buf;
|
|
buf.write(reinterpret_cast<const char *>(reply.data()), reply.size());
|
|
const auto &[typehash, batch] = msgpack::unpack(buf.data(), buf.size()).get().convert(payload);
|
|
|
|
for (const auto &data : batch) {
|
|
this->mc_cbk__(data, typehash);
|
|
}
|
|
|
|
return std::optional(res);
|
|
});
|
|
} catch (const zmq::error_t &err) {
|
|
fmt::print("ZMQ error: {1} ({0})\r\n", err.num(), err.what());
|
|
}
|
|
};
|
|
|
|
private:
|
|
void listen__(std::stop_token st) const override { throw std::runtime_error("Can't listen on REQUEST pattern socket"); }
|
|
};
|