Kurlyk
Loading...
Searching...
No Matches
HttpClient.hpp
Go to the documentation of this file.
1#pragma once
2#ifndef _KURLYK_HTTP_CLIENT_HPP_INCLUDED
3#define _KURLYK_HTTP_CLIENT_HPP_INCLUDED
4
7
8namespace kurlyk {
9
13 class HttpClient {
14 public:
15
21
24 HttpClient(const std::string& host) :
25 m_host(host) {
28 }
29
30 HttpClient(const HttpClient&) = delete;
31 void operator=(const HttpClient&) = delete;
32
36 auto& instance = HttpRequestManager::get_instance();
38 instance.remove_limit(m_request.general_rate_limit_id);
39 }
41 instance.remove_limit(m_request.specific_rate_limit_id);
42 }
43 }
44
48 auto promise = std::make_shared<std::promise<void>>();
49 auto future = promise->get_future();
51 try {
52 promise->set_value();
53 } catch (const std::future_error& e) {
54 if (e.code() == std::make_error_condition(std::future_errc::promise_already_satisfied)) {
55 KURLYK_HANDLE_ERROR(e, "Promise already satisfied in HttpClient::request callback");
56 } else {
57 KURLYK_HANDLE_ERROR(e, "Future error in HttpClient::request callback");
58 }
59 } catch (const std::exception& e) {
60 KURLYK_HANDLE_ERROR(e, "Unhandled exception in HttpClient::request callback");
61 } catch (...) {
62 // Unknown fatal error in request callback
63 }
64 });
66 try {
67 future.get();
68 } catch (const std::exception& e) {
69 KURLYK_HANDLE_ERROR(e, "cancel_requests() future.get() failed");
70 }
71 }
72
75 void set_host(const std::string& host) {
76 m_host = host;
77 }
78
81 void set_headers(const kurlyk::Headers& headers) {
82 m_request.headers = headers;
83 }
84
89 long limit_id,
91 auto& instance = HttpRequestManager::get_instance();
92 switch (type) {
95 instance.remove_limit(m_request.general_rate_limit_id);
96 }
97 m_request.general_rate_limit_id = limit_id;
99 break;
102 instance.remove_limit(m_request.specific_rate_limit_id);
103 }
104 m_request.specific_rate_limit_id = limit_id;
106 break;
107 }
108 }
109
115 long limit_id,
117 assign_rate_limit_id(limit_id, type);
118 }
119
125 long requests_per_period,
126 long period_ms,
128 auto& instance = HttpRequestManager::get_instance();
129 switch (type) {
132 instance.remove_limit(m_request.general_rate_limit_id);
133 }
134 m_request.general_rate_limit_id = instance.create_rate_limit(requests_per_period, period_ms);
136 break;
139 instance.remove_limit(m_request.specific_rate_limit_id);
140 }
141 m_request.specific_rate_limit_id = instance.create_rate_limit(requests_per_period, period_ms);
143 break;
144 }
145 }
146
151 long requests_per_minute,
153 long period_ms = 60000; // 1 minute in milliseconds
154 return set_rate_limit(requests_per_minute, period_ms, type);
155 }
156
161 long requests_per_second,
163 long period_ms = 1000; // 1 second in milliseconds
164 return set_rate_limit(requests_per_second, period_ms, type);
165 }
166
173 bool identity = false,
174 bool deflate = false,
175 bool gzip = false,
176 bool brotli = false) {
177 m_request.set_accept_encoding(identity, deflate, gzip, brotli);
178 }
179
182 void set_accept_encoding(const std::string& value) {
183 m_request.accept_encoding = value;
184 }
185
188 void set_accept_language(const std::string& value) {
189 m_request.headers.emplace("Accept-Language", value);
190 }
191
194 void set_content_type(const std::string& value) {
195 m_request.headers.emplace("Content-Type", value);
196 }
197
200 void set_origin(const std::string& value) {
201 m_request.headers.emplace("Origin", value);
202 }
203
206 void set_referer(const std::string& value) {
207 m_request.headers.emplace("Referer", value);
208 }
209
212 void set_dnt(const bool value) {
213 if (value) m_request.headers.emplace("dnt", "1");
214 }
215
218 void set_follow_location(bool value) {
219 m_request.follow_location = value;
220 }
221
224 void set_auto_referer(bool value) {
225 m_request.auto_referer = value;
226 }
227
230 void set_proxy_tunnel(bool value) {
231 m_request.proxy_tunnel = value;
232 }
233
237 void set_head_only(bool value) {
238 m_request.head_only = value;
239 }
240
243 void set_streaming(bool streaming) {
244 m_request.streaming = streaming;
245 }
246
252 const std::string& ip,
253 int port,
255 m_request.set_proxy(ip, port, type);
256 }
257
265 const std::string& ip,
266 const int port,
267 const std::string& username,
268 const std::string& password,
270 m_request.set_proxy(ip, port, username, password, type);
271 }
272
277 const std::string& username,
278 const std::string& password) {
279 m_request.set_proxy_auth(username, password);
280 }
281
284 void set_proxy_server(const std::string& server) {
285 m_request.set_proxy_server(server);
286 }
287
290 void set_proxy_auth(const std::string& auth) {
291 m_request.set_proxy_auth(auth);
292 }
293
297 m_request.set_proxy_type(type);
298 }
299
303 void set_retry_attempts(long retry_attempts, long retry_delay_ms) {
304 m_request.set_retry_attempts(retry_attempts, retry_delay_ms);
305 }
306
309 void add_valid_status(long status) {
310 m_request.add_valid_status(status);
311 }
312
315 void set_valid_statuses(const std::set<long>& statuses) {
316 m_request.set_valid_statuses(statuses);
317 }
318
321 m_request.clear_valid_statuses();
322 }
323
326 void set_user_agent(const std::string& user_agent) {
327 m_request.set_user_agent(user_agent);
328 }
329
332 void set_cookie(const std::string& cookie) {
333 m_request.set_cookie(cookie);
334 }
335
338 void set_cert_file(const std::string& cert_file) {
339 m_request.set_cert_file(cert_file);
340 }
341
344 void set_ca_file(const std::string& ca_file) {
345 m_request.set_ca_file(ca_file);
346 }
347
350 void set_timeout(long timeout) {
351 m_request.set_timeout(timeout);
352 }
353
356 void set_connect_timeout(long connect_timeout) {
357 m_request.set_connect_timeout(connect_timeout);
358 }
359
362 void set_verbose(bool verbose) {
363 m_request.verbose = verbose;
364 }
365
368 void set_debug_header(bool debug_header) {
369 m_request.debug_header = debug_header;
370 }
371
374 void set_max_redirects(long max_redirects) {
375 m_request.max_redirects = max_redirects;
376 }
377
383 std::unique_ptr<HttpRequest> request_ptr,
384 HttpResponseCallback callback) {
386 std::move(request_ptr), std::move(callback));
387 if (submit_result) {
389 }
390 return submit_result;
391 }
392
402 const std::string &method,
403 const std::string& path,
404 const QueryParams &query,
405 const Headers &headers,
406 const std::string &content,
407 HttpResponseCallback callback) {
408# if __cplusplus >= 201402L
409 std::unique_ptr<HttpRequest> request_ptr = std::make_unique<HttpRequest>(m_request);
410# else
411 std::unique_ptr<HttpRequest> request_ptr = std::unique_ptr<HttpRequest>(new HttpRequest(m_request));
412# endif
413 request_ptr->method = method;
414 request_ptr->set_url(m_host, path, query);
415 request_ptr->headers.insert(headers.begin(), headers.end());
416 request_ptr->content = content;
417 return request(std::move(request_ptr), std::move(callback));
418 }
419
430 const std::string &method,
431 const std::string& path,
432 const QueryParams &query,
433 const Headers &headers,
434 const std::string &content,
435 long specific_rate_limit_id,
436 HttpResponseCallback callback) {
437# if __cplusplus >= 201402L
438 std::unique_ptr<HttpRequest> request_ptr = std::make_unique<HttpRequest>(m_request);
439# else
440 std::unique_ptr<HttpRequest> request_ptr = std::unique_ptr<HttpRequest>(new HttpRequest(m_request));
441# endif
442 request_ptr->method = method;
443 request_ptr->set_url(m_host, path, query);
444 request_ptr->headers.insert(headers.begin(), headers.end());
445 request_ptr->content = content;
446
447 // Set the specific rate limit ID for this request
449 HttpRequestManager::get_instance().remove_limit(request_ptr->specific_rate_limit_id);
450 }
451 request_ptr->specific_rate_limit_id = specific_rate_limit_id;
453
454 return request(std::move(request_ptr), std::move(callback));
455 }
456
463 bool get(
464 const std::string& path,
465 const QueryParams& query,
466 const Headers& headers,
467 HttpResponseCallback callback) {
468 return request("GET", path, query, headers, std::string(), std::move(callback));
469 }
470
478 bool post(
479 const std::string& path,
480 const QueryParams& query,
481 const Headers& headers,
482 const std::string& content,
483 HttpResponseCallback callback) {
484 return request("POST", path, query, headers, content, std::move(callback));
485 }
486
494 bool get(
495 const std::string& path,
496 const QueryParams& query,
497 const Headers& headers,
498 long specific_rate_limit_id,
499 HttpResponseCallback callback) {
500 return request("GET", path, query, headers, std::string(), specific_rate_limit_id, std::move(callback));
501 }
502
511 bool post(
512 const std::string& path,
513 const QueryParams& query,
514 const Headers& headers,
515 const std::string& content,
516 long specific_rate_limit_id,
517 HttpResponseCallback callback) {
518 return request("POST", path, query, headers, content, specific_rate_limit_id, std::move(callback));
519 }
520
528 std::future<HttpResponsePtr> request(
529 const std::string& method,
530 const std::string& path,
531 const QueryParams& query,
532 const Headers& headers,
533 const std::string& content) {
534# if __cplusplus >= 201402L
535 auto request_ptr = std::make_unique<HttpRequest>(m_request);
536# else
537 auto request_ptr = std::unique_ptr<HttpRequest>(new HttpRequest(m_request));
538# endif
539 request_ptr->method = method;
540 request_ptr->set_url(m_host, path, query);
541 request_ptr->headers.insert(headers.begin(), headers.end());
542 request_ptr->content = content;
543
544 auto promise = std::make_shared<std::promise<HttpResponsePtr>>();
545 auto future = promise->get_future();
546
547 HttpResponseCallback callback = [promise](HttpResponsePtr response) {
548 safe_set_response(promise, std::move(response));
549 };
550
552 promise, std::move(request_ptr), std::move(callback));
553
554 return future;
555 }
556
565 std::future<HttpResponsePtr> request(
566 const std::string& method,
567 const std::string& path,
568 const QueryParams& query,
569 const Headers& headers,
570 const std::string& content,
571 long specific_rate_limit_id) {
572# if __cplusplus >= 201402L
573 auto request_ptr = std::make_unique<HttpRequest>(m_request);
574# else
575 auto request_ptr = std::unique_ptr<HttpRequest>(new HttpRequest(m_request));
576# endif
577 request_ptr->method = method;
578 request_ptr->set_url(m_host, path, query);
579 request_ptr->headers.insert(headers.begin(), headers.end());
580 request_ptr->content = content;
581
582 // Set the specific rate limit ID for this request
584 HttpRequestManager::get_instance().remove_limit(request_ptr->specific_rate_limit_id);
585 }
586 request_ptr->specific_rate_limit_id = specific_rate_limit_id;
588
589 auto promise = std::make_shared<std::promise<HttpResponsePtr>>();
590 auto future = promise->get_future();
591
592 HttpResponseCallback callback = [promise](HttpResponsePtr response) {
593 safe_set_response(promise, std::move(response));
594 };
595
597 promise, std::move(request_ptr), std::move(callback));
598
599 return future;
600 }
601
607 std::future<HttpResponsePtr> get(
608 const std::string& path,
609 const QueryParams& query,
610 const Headers& headers) {
611 return request("GET", path, query, headers, std::string());
612 }
613
620 std::future<HttpResponsePtr> post(
621 const std::string& path,
622 const QueryParams& query,
623 const Headers& headers,
624 const std::string& content) {
625 return request("POST", path, query, headers, content);
626 }
627
634 std::future<HttpResponsePtr> get(
635 const std::string& path,
636 const QueryParams& query,
637 const Headers& headers,
638 long specific_rate_limit_id) {
639 return request("GET", path, query, headers, std::string(), specific_rate_limit_id);
640 }
641
649 std::future<HttpResponsePtr> post(
650 const std::string& path,
651 const QueryParams& query,
652 const Headers& headers,
653 const std::string& content,
654 long specific_rate_limit_id) {
655 return request("POST", path, query, headers, content, specific_rate_limit_id);
656 }
657
658 private:
660 std::string m_host;
663
669 std::unique_ptr<HttpRequest> request_ptr,
670 HttpResponseCallback callback) {
671 return submit_request(std::move(request_ptr), std::move(callback)).accepted;
672 }
673
677 static void safe_set_response(
678 std::shared_ptr<std::promise<HttpResponsePtr>> promise,
679 HttpResponsePtr response) {
680 if (!response || !response->ready) return;
681 try {
682 promise->set_value(std::move(response));
683 } catch (const std::future_error& e) {
684 if (e.code() == std::make_error_condition(std::future_errc::promise_already_satisfied)) {
685 KURLYK_HANDLE_ERROR(e, "Promise already satisfied in HttpClient::request callback");
686 } else {
687 KURLYK_HANDLE_ERROR(e, "Future error in HttpClient::request callback");
688 }
689 } catch (const std::exception& e) {
690 KURLYK_HANDLE_ERROR(e, "Unhandled exception in HttpClient::request callback");
691 } catch (...) {
692 // Unknown fatal error in request callback
693 }
694 }
695
700# if __cplusplus >= 201402L
701 auto response = std::make_unique<HttpResponse>();
702# else
703 auto response = std::unique_ptr<HttpResponse>(new HttpResponse());
704# endif
705 response->ready = true;
706 response->status_code = 0;
707 response->error_code = submit_result.error_code;
708 response->error_message = submit_result.error_code.message();
709 return response;
710 }
711
717 std::shared_ptr<std::promise<HttpResponsePtr>> promise,
718 std::unique_ptr<HttpRequest> request_ptr,
719 HttpResponseCallback callback) {
720 try {
721 const SubmitResult submit_result = submit_request(std::move(request_ptr), std::move(callback));
722 if (!submit_result) {
723 safe_set_response(promise, make_submit_error_response(submit_result));
724 }
725 } catch (const std::exception& e) {
726 KURLYK_HANDLE_ERROR(e, "Exception while submitting request");
727 try {
728 promise->set_exception(std::current_exception());
729 } catch (...) {} // fallback
730 } catch (...) {
731 // Unknown fatal error while submitting request
732 try {
733 promise->set_exception(std::current_exception());
734 } catch (...) {} // fallback
735 }
736 }
737
739 static void ensure_initialized() {
740 static bool is_initialized = false;
741 if (!is_initialized) {
742 is_initialized = true;
745 }
746 }
747
748 }; // HttpClient
749
750}; // namespace kurlyk
751
752#endif // _KURLYK_HTTP_CLIENT_HPP_INCLUDED
#define KURLYK_HANDLE_ERROR(e, msg)
bool get(const std::string &path, const QueryParams &query, const Headers &headers, long specific_rate_limit_id, HttpResponseCallback callback)
Sends a GET request with a specific rate limit ID.
bool request(std::unique_ptr< HttpRequest > request_ptr, HttpResponseCallback callback)
Adds the request to the request manager and notifies the worker to process it.
void set_proxy_auth(const std::string &auth)
Sets the proxy authentication credentials.
~HttpClient()
Destroys the client, cancels its active request, and releases owned rate limits.
HttpRequest m_request
The request object used for configuring and sending requests.
void set_valid_statuses(const std::set< long > &statuses)
Replaces all valid HTTP status codes for the request.
void set_head_only(bool value)
Configures whether to send only the HTTP headers (HEAD request).
void set_rate_limit(long requests_per_period, long period_ms, RateLimitType type=RateLimitType::RL_GENERAL)
Sets the rate limit for HTTP requests.
void set_verbose(bool verbose)
Enables or disables verbose output.
void set_accept_language(const std::string &value)
Sets the Accept-Language header value.
std::future< HttpResponsePtr > request(const std::string &method, const std::string &path, const QueryParams &query, const Headers &headers, const std::string &content, long specific_rate_limit_id)
Sends an HTTP request with a specified method, path, specific rate limit ID and parameters,...
std::string m_host
The base host URL for the HTTP client.
void set_max_redirects(long max_redirects)
Sets the maximum number of redirects for the client.
void set_rate_limit_id(long limit_id, RateLimitType type=RateLimitType::RL_GENERAL)
Sets the rate limit ID for the HTTP request (alias for assign_rate_limit_id).
std::future< HttpResponsePtr > post(const std::string &path, const QueryParams &query, const Headers &headers, const std::string &content, long specific_rate_limit_id)
Sends an asynchronous POST request with a specific rate limit ID and returns a future with the respon...
void set_content_type(const std::string &value)
Sets the Content-Type header value.
bool post(const std::string &path, const QueryParams &query, const Headers &headers, const std::string &content, HttpResponseCallback callback)
Sends a POST request.
bool request(const std::string &method, const std::string &path, const QueryParams &query, const Headers &headers, const std::string &content, HttpResponseCallback callback)
Sends an HTTP request with the specified method, path, and parameters.
HttpClient(const HttpClient &)=delete
void add_valid_status(long status)
Adds a valid HTTP status code to the request.
HttpClient()
Default constructor for HttpClient.
void set_streaming(bool streaming)
Enables or disables intermediate callbacks for response body chunks.
void set_ca_file(const std::string &ca_file)
Sets the path to the CA certificate file.
void clear_valid_statuses()
Clears the set of valid HTTP status codes for the request.
SubmitResult submit_request(std::unique_ptr< HttpRequest > request_ptr, HttpResponseCallback callback)
Attempts to submit a prepared request to the global HTTP manager.
std::future< HttpResponsePtr > request(const std::string &method, const std::string &path, const QueryParams &query, const Headers &headers, const std::string &content)
Sends an HTTP request with a specified method, path, and parameters, and returns a future with the re...
void set_proxy(const std::string &ip, int port, ProxyType type=ProxyType::PROXY_HTTP)
Sets the proxy server address.
void set_rate_limit_rps(long requests_per_second, RateLimitType type=RateLimitType::RL_GENERAL)
Sets the rate limit based on requests per second (RPS).
void safe_submit_request(std::shared_ptr< std::promise< HttpResponsePtr > > promise, std::unique_ptr< HttpRequest > request_ptr, HttpResponseCallback callback)
Submits a request and propagates any failure to the provided promise.
void set_cert_file(const std::string &cert_file)
Sets the client certificate file path.
static void safe_set_response(std::shared_ptr< std::promise< HttpResponsePtr > > promise, HttpResponsePtr response)
Safely sets the response value on the given promise.
void set_auto_referer(bool value)
Configures whether to automatically set the Referer header on redirects.
void set_connect_timeout(long connect_timeout)
Sets the connection timeout duration.
bool is_general_limit_owned
Flag indicating if the client owns the general rate limit.
void assign_rate_limit_id(long limit_id, RateLimitType type=RateLimitType::RL_GENERAL)
Assigns an existing rate limit to the HTTP request.
void set_retry_attempts(long retry_attempts, long retry_delay_ms)
Sets retry attempts and delay between retries for HTTP requests.
void set_timeout(long timeout)
Sets the timeout duration for HTTP requests.
void set_proxy_server(const std::string &server)
Sets the proxy server address.
std::future< HttpResponsePtr > get(const std::string &path, const QueryParams &query, const Headers &headers)
Sends a GET request asynchronously and returns a future with the response.
void set_referer(const std::string &value)
Sets the Referer header value.
void set_follow_location(bool value)
Configures whether to follow redirects automatically.
void set_proxy(const std::string &ip, const int port, const std::string &username, const std::string &password, ProxyType type=ProxyType::PROXY_HTTP)
Sets the proxy server address with authentication details.
void set_cookie(const std::string &cookie)
Sets the cookie string for HTTP requests.
std::future< HttpResponsePtr > get(const std::string &path, const QueryParams &query, const Headers &headers, long specific_rate_limit_id)
Sends an asynchronous GET request with a specific rate limit ID and returns a future with the respons...
std::future< HttpResponsePtr > post(const std::string &path, const QueryParams &query, const Headers &headers, const std::string &content)
Sends a POST request asynchronously and returns a future with the response.
void set_accept_encoding(const std::string &value)
Sets a custom Accept-Encoding header value.
void set_user_agent(const std::string &user_agent)
Sets the User-Agent header.
void set_origin(const std::string &value)
Sets the Origin header value.
HttpClient(const std::string &host)
Constructs an HttpClient with the specified host.
void set_proxy_tunnel(bool value)
Configures whether to use a tunneling proxy for HTTP requests.
bool post(const std::string &path, const QueryParams &query, const Headers &headers, const std::string &content, long specific_rate_limit_id, HttpResponseCallback callback)
Sends a POST request with a specific rate limit ID.
static HttpResponsePtr make_submit_error_response(const SubmitResult &submit_result)
Creates a ready HTTP response describing a synchronous submission rejection.
static void ensure_initialized()
Ensures that the network worker and request manager are initialized.
void set_host(const std::string &host)
Sets the host URL for the HTTP client.
bool get(const std::string &path, const QueryParams &query, const Headers &headers, HttpResponseCallback callback)
Sends a GET request.
void set_debug_header(bool debug_header)
Enables or disables debug headers.
void set_proxy_auth(const std::string &username, const std::string &password)
Sets proxy authentication credentials.
void set_headers(const kurlyk::Headers &headers)
Sets the default headers for HTTP requests.
void set_dnt(const bool value)
Sets the Do Not Track (DNT) header value.
bool is_specific_limit_owned
Flag indicating if the client owns the specific rate limit.
void set_rate_limit_rpm(long requests_per_minute, RateLimitType type=RateLimitType::RL_GENERAL)
Sets the rate limit based on requests per minute (RPM).
bool request(const std::string &method, const std::string &path, const QueryParams &query, const Headers &headers, const std::string &content, long specific_rate_limit_id, HttpResponseCallback callback)
Sends an HTTP request with the specified method, path, parameters, and specific rate limit ID.
void operator=(const HttpClient &)=delete
void set_accept_encoding(bool identity=false, bool deflate=false, bool gzip=false, bool brotli=false)
Sets the Accept-Encoding header.
void set_proxy_type(ProxyType type)
Sets the proxy type.
void cancel_requests()
Cancels the active request associated with this client and waits for its completion.
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.
SubmitResult submit_request(std::unique_ptr< HttpRequest > request_ptr, HttpResponseCallback callback)
Attempts to enqueue a new HTTP request and reports the admission result.
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.
Represents an HTTP request.
Represents the response received from an HTTP request, including headers, content,...
void notify()
Notifies the worker to begin processing requests or tasks.
static NetworkWorker & get_instance()
Get the singleton instance of NetworkWorker.
void start(const bool use_async)
Starts the worker thread for asynchronous task processing.
#define KURLYK_AUTO_INIT_USE_ASYNC
Determines whether the NetworkWorker runs in a background thread during automatic initialization.
Definition kurlyk.hpp:20
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.
RateLimitType
Defines rate limit scope categories.
Definition enums.hpp:24
@ RL_GENERAL
Applies globally to all requests.
Definition enums.hpp:25
@ RL_SPECIFIC
Applies to specific client/request.
Definition enums.hpp:26
void safe_set_response(std::shared_ptr< std::promise< HttpResponsePtr > > promise, HttpResponsePtr response)
Safely sets an HTTP response on the provided promise.
Definition utils.hpp:113
ProxyType
Enumeration of supported proxy types compatible with libcurl.
Definition enums.hpp:12
@ PROXY_HTTP
HTTP proxy.
Definition enums.hpp:13
std::unique_ptr< HttpResponse > HttpResponsePtr
A unique pointer to an HttpResponse object for memory management.
utils::CaseInsensitiveMultimap Headers
Alias for HTTP headers, providing a case-insensitive unordered multimap.
utils::CaseInsensitiveMultimap QueryParams
Alias for query parameters in HTTP requests, stored case-insensitively.
HttpResponsePtr make_submit_error_response(const SubmitResult &submit_result)
Creates a ready HTTP response describing a synchronous submission rejection.
Definition utils.hpp:97
Represents the synchronous result of trying to enqueue or submit work.
std::error_code error_code
Describes the rejection reason when accepted is false.