2#ifndef _KURLYK_HTTP_REQUEST_MANAGER_HPP_INCLUDED
3#define _KURLYK_HTTP_REQUEST_MANAGER_HPP_INCLUDED
33 std::unique_ptr<HttpRequest> request_ptr,
43 std::unique_ptr<HttpRequest> request_ptr,
45 std::lock_guard<std::mutex> lock(
m_mutex);
55# if __cplusplus >= 201402L
56 m_pending_requests.push_back(std::make_unique<HttpRequestContext>(std::move(request_ptr), std::move(callback)));
69 return m_rate_limiter.create_limit(requests_per_period, period_ms);
102 if (callback) callback();
105 std::lock_guard<std::mutex> lock(
m_mutex);
131 std::lock_guard<std::mutex> lock(
m_mutex);
153 std::unique_lock<std::mutex> lock(
m_mutex);
156 std::vector<std::unique_ptr<HttpRequestContext>> pending_request;
157 std::vector<std::unique_ptr<HttpRequestContext>> failed_requests;
162 auto& request = context->request;
165 failed_requests.push_back(std::move(context));
172 request->general_rate_limit_id,
173 request->specific_rate_limit_id);
178 pending_request.push_back(std::move(context));
184 if (!failed_requests.empty()) {
185 for (
const auto &context : failed_requests) {
186# if __cplusplus >= 201402L
187 auto response = std::make_unique<HttpResponse>();
189 auto response = std::unique_ptr<HttpResponse>(
new HttpResponse());
191 const long BAD_REQUEST = 400;
193 response->status_code = BAD_REQUEST;
194 response->ready =
true;
195 context->callback(std::move(response));
197 failed_requests.clear();
201 if (pending_request.empty())
return;
202# if __cplusplus >= 201402L
214 if (!request->process()) {
218 auto failed_requests = request->extract_failed_requests();
220 for (
auto& request : failed_requests) {
230 auto& request_context = *it;
231 if (!request_context || !request_context->request) {
236 const auto now = std::chrono::steady_clock::now();
237 const auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(now - request_context->start_time);
238 const auto& retry_delay_ms = request_context->request->retry_delay_ms;
239 if (duration.count() >= retry_delay_ms) {
240 std::unique_lock<std::mutex> lock(
m_mutex);
252 std::unique_lock<std::mutex> lock(
m_mutex);
260 if (!requests_to_cancel.count(request_context->request->request_id))
continue;
261# if __cplusplus >= 201402L
262 auto response = std::make_unique<HttpResponse>();
264 auto response = std::unique_ptr<HttpResponse>(
new HttpResponse());
266 const long CANCELED_REQUEST_CODE = 499;
268 response->status_code = CANCELED_REQUEST_CODE;
269 response->ready =
true;
270 request_context->callback(std::move(response));
273 m_failed_requests.remove_if([&](
const std::unique_ptr<HttpRequestContext>& ctx) {
274 return ctx && ctx->request && requests_to_cancel.count(ctx->request->request_id) > 0;
279 handler->cancel_request_by_id(requests_to_cancel);
282 for (
const auto &request : requests_to_cancel) {
283 for (
const auto &callback : request.second) {
284 if (callback) callback();
291 std::unique_lock<std::mutex> lock(
m_mutex);
296 for (
const auto &request_context : pending_requests) {
297# if __cplusplus >= 201402L
298 auto response = std::make_unique<HttpResponse>();
300 auto response = std::unique_ptr<HttpResponse>(
new HttpResponse());
302 const long CANCELED_REQUEST_CODE = 499;
304 response->status_code = CANCELED_REQUEST_CODE;
305 response->ready =
true;
306 request_context->callback(std::move(response));
309# if __cplusplus >= 201402L
310 auto response = std::make_unique<HttpResponse>();
312 auto response = std::unique_ptr<HttpResponse>(
new HttpResponse());
314 const long CANCELED_REQUEST_CODE = 499;
316 response->status_code = CANCELED_REQUEST_CODE;
317 response->ready =
true;
318 request_context->callback(std::move(response));
324 curl_global_init(CURL_GLOBAL_ALL);
329 curl_global_cleanup();
Manages multiple asynchronous HTTP requests using libcurl's multi interface.
Defines the HttpRateLimiter class for managing rate limits on HTTP requests.
Defines the HttpRequestContext class for managing HTTP request context, including retries and timing.
Handles multiple asynchronous HTTP requests using libcurl's multi interface.
Manages rate limits for HTTP requests, ensuring compliance with set limits.
Represents the context of an HTTP request, including the request object, callback function,...
HttpRequestManager(const HttpRequestManager &)=delete
Deleted copy constructor to enforce the singleton pattern.
std::size_t max_pending_requests() const
Returns the current maximum pending request count.
std::atomic< bool > m_shutdown
Flag indicating if shutdown has been requested.
const bool add_request(std::unique_ptr< HttpRequest > request_ptr, HttpResponseCallback callback)
Adds a new HTTP request to the manager.
std::unordered_map< uint64_t, callback_list_t > m_requests_to_cancel
Map of request IDs to their associated cancellation callbacks.
void set_max_pending_requests(std::size_t max_pending_requests)
Sets the maximum number of pending requests accepted into the global queue.
const long create_rate_limit(long requests_per_period, long period_ms)
Creates a rate limit with specified parameters.
std::list< std::unique_ptr< HttpRequestContext > > m_failed_requests
List of failed HTTP requests for retrying.
void process_active_requests()
Processes active requests, moving failed ones to the failed requests list for retrying.
void cancel_request_by_id(uint64_t request_id, std::function< void()> callback)
Cancels a request by its unique identifier.
static HttpRequestManager & get_instance()
Get the singleton instance of HttpRequestManager.
std::list< std::unique_ptr< HttpBatchRequestHandler > > m_active_request_batches
List of currently active HTTP request batches.
std::atomic< uint64_t > m_request_id_counter
Atomic counter for unique request IDs.
void process_retry_failed_requests()
Attempts to retry failed requests if their retry delay has passed.
std::atomic< std::size_t > m_max_pending_requests
Maximum number of requests accepted into the pending queue, or zero if unbounded.
virtual ~HttpRequestManager()
Private destructor to clean up global resources.
SubmitResult submit_request(std::unique_ptr< HttpRequest > request_ptr, HttpResponseCallback callback)
Attempts to enqueue a new HTTP request and reports the admission result.
HttpRateLimiter m_rate_limiter
Rate limiter for controlling request frequency.
std::list< std::function< void()> > callback_list_t
const bool is_loaded() const override
Checks if there are active, pending, or failed requests.
std::mutex m_mutex
Mutex to protect access to the pending requests list and requests-to-cancel map.
void process_cancel_requests()
Processes and cancels HTTP requests based on their IDs.
bool remove_limit(long limit_id)
Removes an existing rate limit with the specified identifier.
uint64_t generate_request_id()
Generates a new unique request ID.
void shutdown() override
Shuts down the request manager, clearing all active and pending requests.
HttpRequestManager & operator=(const HttpRequestManager &)=delete
Deleted copy assignment operator to enforce the singleton pattern.
HttpRequestManager()
Private constructor to initialize global resources (e.g., cURL).
void cleanup_pending_requests()
Cleans up pending requests, marking each as failed and invoking its callback.
void process() override
Processes all requests in the manager.
void process_pending_requests()
Processes all pending requests, moving valid requests to active batches or marking them as failed.
std::list< std::unique_ptr< HttpRequestContext > > m_pending_requests
List of pending HTTP requests awaiting processing.
Represents the response received from an HTTP request, including headers, content,...
Interface for modules managed by NetworkWorker (e.g., HTTP, WebSocket).
@ ShuttingDown
Operation was rejected because the owning subsystem is shutting down.
@ QueueLimitExceeded
Operation was rejected because the bounded queue is already full.
std::error_code make_error_code(ClientError e)
Creates a std::error_code from a ClientError value.
Primary namespace for the Kurlyk library, encompassing initialization, request management,...
std::function< void(HttpResponsePtr response)> HttpResponseCallback
Type definition for the callback function used to handle HTTP responses.
Represents the synchronous result of trying to enqueue or submit work.
bool accepted
Indicates whether the work item was accepted for processing.