Clio  develop
The XRP Ledger API server.
Loading...
Searching...
No Matches
SendingQueue.hpp
1#pragma once
2
3#include "web/ng/Error.hpp"
4
5#include <boost/asio/any_io_executor.hpp>
6#include <boost/asio/error.hpp>
7#include <boost/asio/spawn.hpp>
8#include <boost/system/detail/error_code.hpp>
9
10#include <cstddef>
11#include <expected>
12#include <functional>
13#include <queue>
14#include <utility>
15
16namespace web::ng::impl {
17
18template <typename T>
19class SendingQueue {
20public:
21 using Sender = std::function<
22 void(T const&, boost::asio::basic_yield_context<boost::asio::any_io_executor>)>;
23
24private:
25 std::queue<T> queue_;
26 Sender sender_;
27 Error error_;
28 bool isSending_{false};
29 size_t maxSize_;
30
31public:
32 SendingQueue(Sender sender, size_t maxSize) : sender_{std::move(sender)}, maxSize_{maxSize}
33 {
34 }
35
36 std::expected<void, Error>
37 send(T message, boost::asio::yield_context yield)
38 {
39 if (error_)
40 return std::unexpected{error_};
41
42 if (queue_.size() >= maxSize_) {
43 error_ = boost::asio::error::timed_out;
44 return std::unexpected{error_};
45 }
46
47 queue_.push(std::move(message));
48 if (isSending_)
49 return {};
50
51 isSending_ = true;
52 while (not queue_.empty() and not error_) {
53 auto const responseToSend = std::move(queue_.front());
54 queue_.pop();
55
56 Error writeError;
57 sender_(responseToSend, yield[writeError]);
58 if (writeError)
59 error_ = writeError;
60 }
61 isSending_ = false;
62 if (error_)
63 return std::unexpected{error_};
64 return {};
65 }
66};
67
68} // namespace web::ng::impl