|
30 | 30 | #include <string> |
31 | 31 | #include <thread> |
32 | 32 |
|
| 33 | +#include <asio/steady_timer.hpp> |
| 34 | +#include <utility> |
| 35 | + |
33 | 36 | namespace couchbase::core::transactions |
34 | 37 | { |
35 | 38 | // returns the parsed server time from the result of a lookup_in_spec::get(subdoc::lookup_in_macro::vbucket).xattr() call |
@@ -82,6 +85,9 @@ wrap_durable_request(T&& req, const couchbase::transactions::transactions_config |
82 | 85 | return req; |
83 | 86 | } |
84 | 87 |
|
| 88 | +void |
| 89 | +validate_operation_result(result& res, bool ignore_subdoc_errors = true); |
| 90 | + |
85 | 91 | result |
86 | 92 | wrap_operation_future(std::future<result>& fut, bool ignore_subdoc_errors = true); |
87 | 93 |
|
@@ -300,6 +306,81 @@ struct constant_delay { |
300 | 306 | } |
301 | 307 | }; |
302 | 308 |
|
| 309 | +struct async_exp_delay { |
| 310 | + std::shared_ptr<asio::steady_timer> timer; |
| 311 | + std::chrono::microseconds initial_delay; |
| 312 | + std::chrono::microseconds max_delay; |
| 313 | + std::chrono::microseconds timeout; |
| 314 | + mutable std::uint32_t retries; |
| 315 | + mutable std::optional<std::chrono::time_point<std::chrono::steady_clock>> end_time; |
| 316 | + |
| 317 | + template<typename R1, typename P1, typename R2, typename P2, typename R3, typename P3> |
| 318 | + async_exp_delay(std::shared_ptr<asio::steady_timer> timer, |
| 319 | + std::chrono::duration<R1, P1> initial, |
| 320 | + std::chrono::duration<R2, P2> max, |
| 321 | + std::chrono::duration<R3, P3> limit) |
| 322 | + : timer(std::move(timer)) |
| 323 | + , initial_delay(std::chrono::duration_cast<std::chrono::microseconds>(initial)) |
| 324 | + , max_delay(std::chrono::duration_cast<std::chrono::microseconds>(max)) |
| 325 | + , timeout(std::chrono::duration_cast<std::chrono::microseconds>(limit)) |
| 326 | + , retries(0) |
| 327 | + , end_time() |
| 328 | + { |
| 329 | + } |
| 330 | + |
| 331 | + void operator()(utils::movable_function<void(std::error_code)> callback) const |
| 332 | + { |
| 333 | + auto now = std::chrono::steady_clock::now(); |
| 334 | + if (!end_time) { |
| 335 | + end_time = std::chrono::steady_clock::now() + timeout; |
| 336 | + return; |
| 337 | + } |
| 338 | + if (now > *end_time) { |
| 339 | + throw retry_operation_timeout("timed out"); |
| 340 | + } |
| 341 | + auto delay = std::chrono::duration_cast<std::chrono::microseconds>(initial_delay * (jitter() * pow(2, retries++))); |
| 342 | + if (delay > max_delay) { |
| 343 | + delay = max_delay; |
| 344 | + } |
| 345 | + if (now + delay > *end_time) { |
| 346 | + timer->expires_after(*end_time - now); |
| 347 | + } else { |
| 348 | + timer->expires_after(delay); |
| 349 | + } |
| 350 | + timer->async_wait(callback); |
| 351 | + } |
| 352 | +}; |
| 353 | + |
| 354 | +struct async_constant_delay { |
| 355 | + std::shared_ptr<asio::steady_timer> timer; |
| 356 | + std::chrono::microseconds delay; |
| 357 | + std::size_t max_retries; |
| 358 | + std::size_t retries; |
| 359 | + |
| 360 | + template<typename R, typename P> |
| 361 | + async_constant_delay(std::shared_ptr<asio::steady_timer> timer, std::chrono::duration<R, P> d, std::size_t max) |
| 362 | + : timer(std::move(timer)) |
| 363 | + , delay(std::chrono::duration_cast<std::chrono::microseconds>(d)) |
| 364 | + , max_retries(max) |
| 365 | + , retries(0) |
| 366 | + { |
| 367 | + } |
| 368 | + |
| 369 | + explicit async_constant_delay(std::shared_ptr<asio::steady_timer> timer) |
| 370 | + : async_constant_delay(std::move(timer), DEFAULT_RETRY_OP_DELAY, DEFAULT_RETRY_OP_MAX_RETRIES) |
| 371 | + { |
| 372 | + } |
| 373 | + |
| 374 | + void operator()(utils::movable_function<void(std::error_code)> callback) |
| 375 | + { |
| 376 | + if (retries++ >= max_retries) { |
| 377 | + throw retry_operation_retries_exhausted("retries exhausted"); |
| 378 | + } |
| 379 | + timer->expires_after(delay); |
| 380 | + timer->async_wait(callback); |
| 381 | + } |
| 382 | +}; |
| 383 | + |
303 | 384 | std::list<std::string> |
304 | 385 | get_and_open_buckets(std::shared_ptr<core::cluster> c); |
305 | 386 |
|
|
0 commit comments