3#include "util/Mutex.hpp"
4#include "util/config/ConfigDefinition.hpp"
5#include "util/log/Logger.hpp"
6#include "util/prometheus/Counter.hpp"
7#include "util/prometheus/Gauge.hpp"
9#include <boost/asio/spawn.hpp>
10#include <boost/asio/thread_pool.hpp>
11#include <boost/json/object.hpp>
36 [[nodiscard]]
virtual boost::json::object
44 using TaskType = std::function<void(boost::asio::yield_context)>;
46 struct TaskWithTimestamp {
48 std::chrono::system_clock::time_point queuedAt;
51 using QueueType = std::queue<TaskWithTimestamp>;
67 size_t highPriorityCounter = 0;
70 push(
Priority priority, TaskType&& task)
72 auto& queue = [
this, priority] -> QueueType& {
73 if (priority == Priority::High)
79 .task = std::move(task),
80 .queuedAt = std::chrono::system_clock::now(),
88 return high.empty() and normal.empty();
91 [[nodiscard]] std::optional<TaskWithTimestamp>
94 if (not high.empty() and (highPriorityCounter < kTakeHighPrio or normal.empty())) {
95 auto taskWithTimestamp = std::move(high.front());
97 ++highPriorityCounter;
98 return taskWithTimestamp;
101 if (not normal.empty()) {
102 auto taskWithTimestamp = std::move(normal.front());
104 highPriorityCounter = 0;
105 return taskWithTimestamp;
113 static constexpr auto kTakeHighPrio = 4uz;
116 std::reference_wrapper<util::prometheus::CounterInt> queued_;
117 std::reference_wrapper<util::prometheus::CounterInt> durationUs_;
119 std::reference_wrapper<util::prometheus::GaugeInt> curSize_;
120 uint32_t maxSize_ = std::numeric_limits<uint32_t>::max();
122 util::Logger log_{
"RPC"};
123 boost::asio::thread_pool ioc_;
125 std::atomic_bool stopping_;
126 std::atomic_bool processingStarted_{
false};
128 class OneTimeCallable {
129 std::function<void()> func_;
134 setCallable(std::function<
void()> func);
140 operator bool()
const;
142 util::Mutex<OneTimeCallable> onQueueEmpty_;
143 util::Mutex<QueueState> queueState_;
157 WorkQueue(std::uint32_t numWorkers, uint32_t maxSize = 0);
167 WorkQueue(DontStartProcessingTag, std::uint32_t numWorkers, uint32_t maxSize = 0);
184 requestStop(std::function<
void()> onQueueEmpty = [] {});
213 postCoro(TaskType func,
bool isWhiteListed,
Priority priority = Priority::Default);
220 [[nodiscard]] boost::json::object
239 executeTask(boost::asio::yield_context yield);
An asynchronous, thread-safe queue for RPC requests.
Definition WorkQueue.hpp:43
void stop()
Put the work queue into a stopping state and await workers to finish.
Definition WorkQueue.cpp:127
WorkQueue(std::uint32_t numWorkers, uint32_t maxSize=0)
Create an instance of the work queue.
Definition WorkQueue.cpp:64
boost::json::object report() const override
Generate a report of the work queue state.
Definition WorkQueue.cpp:157
void startProcessing()
Start processing of the enqueued tasks.
Definition WorkQueue.cpp:76
bool postCoro(TaskType func, bool isWhiteListed, Priority priority=Priority::Default)
Submit a job to the work queue.
Definition WorkQueue.cpp:89
Priority
Represents a task scheduling priority.
Definition WorkQueue.hpp:57
void join()
Wait until all the jobs in the queue are finished.
size_t size() const
Get the size of the queue.
Definition WorkQueue.cpp:170
static WorkQueue makeWorkQueue(util::config::ClioConfigDefinition const &config)
A factory function that creates the work queue based on a config.
Definition WorkQueue.cpp:144
void requestStop(std::function< void()> onQueueEmpty=[] {})
Put the work queue into a stopping state. This will prevent new jobs from being queued.
Definition WorkQueue.cpp:118
All the config data will be stored and extracted from this class.
Definition ConfigDefinition.hpp:31
This namespace contains all the RPC logic and handlers.
Definition AMMHelpers.cpp:17
An interface for any class providing a report as json object.
Definition WorkQueue.hpp:28
virtual boost::json::object report() const =0
Generate a report of the work queue state.
Definition WorkQueue.hpp:146