couchbase 3.0.0.beta.1-universal-darwin-19 → 3.0.0-universal-darwin-19

Sign up to get free protection for your applications and to get access to all the features.
Files changed (104) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +227 -0
  3. data/.rubocop_todo.yml +47 -0
  4. data/CONTRIBUTING.md +110 -0
  5. data/Gemfile +4 -0
  6. data/README.md +3 -3
  7. data/Rakefile +1 -1
  8. data/couchbase.gemspec +40 -39
  9. data/examples/analytics.rb +123 -108
  10. data/examples/auth.rb +33 -0
  11. data/examples/crud.rb +16 -2
  12. data/examples/managing_analytics_indexes.rb +18 -4
  13. data/examples/managing_buckets.rb +17 -3
  14. data/examples/managing_collections.rb +22 -9
  15. data/examples/managing_query_indexes.rb +38 -18
  16. data/examples/managing_search_indexes.rb +21 -6
  17. data/examples/managing_view_indexes.rb +18 -4
  18. data/examples/query.rb +17 -3
  19. data/examples/query_with_consistency.rb +30 -20
  20. data/examples/search.rb +116 -101
  21. data/examples/search_with_consistency.rb +43 -30
  22. data/examples/subdocument.rb +42 -30
  23. data/examples/view.rb +19 -10
  24. data/ext/CMakeLists.txt +40 -2
  25. data/ext/build_version.hxx.in +1 -1
  26. data/ext/couchbase/bucket.hxx +190 -38
  27. data/ext/couchbase/cluster.hxx +22 -4
  28. data/ext/couchbase/configuration.hxx +14 -14
  29. data/ext/couchbase/couchbase.cxx +108 -12
  30. data/ext/couchbase/error_map.hxx +202 -2
  31. data/ext/couchbase/errors.hxx +8 -2
  32. data/ext/couchbase/io/dns_client.hxx +6 -6
  33. data/ext/couchbase/io/http_command.hxx +2 -2
  34. data/ext/couchbase/io/http_session.hxx +7 -11
  35. data/ext/couchbase/io/http_session_manager.hxx +3 -3
  36. data/ext/couchbase/io/mcbp_command.hxx +101 -44
  37. data/ext/couchbase/io/mcbp_session.hxx +144 -49
  38. data/ext/couchbase/io/retry_action.hxx +30 -0
  39. data/ext/couchbase/io/retry_context.hxx +39 -0
  40. data/ext/couchbase/io/retry_orchestrator.hxx +96 -0
  41. data/ext/couchbase/io/retry_reason.hxx +235 -0
  42. data/ext/couchbase/io/retry_strategy.hxx +156 -0
  43. data/ext/couchbase/operations/document_decrement.hxx +2 -0
  44. data/ext/couchbase/operations/document_exists.hxx +2 -0
  45. data/ext/couchbase/operations/document_get.hxx +2 -0
  46. data/ext/couchbase/operations/document_get_and_lock.hxx +2 -0
  47. data/ext/couchbase/operations/document_get_and_touch.hxx +2 -0
  48. data/ext/couchbase/operations/document_get_projected.hxx +2 -0
  49. data/ext/couchbase/operations/document_increment.hxx +2 -0
  50. data/ext/couchbase/operations/document_insert.hxx +2 -0
  51. data/ext/couchbase/operations/document_lookup_in.hxx +2 -0
  52. data/ext/couchbase/operations/document_mutate_in.hxx +3 -0
  53. data/ext/couchbase/operations/document_query.hxx +10 -0
  54. data/ext/couchbase/operations/document_remove.hxx +2 -0
  55. data/ext/couchbase/operations/document_replace.hxx +2 -0
  56. data/ext/couchbase/operations/document_search.hxx +8 -3
  57. data/ext/couchbase/operations/document_touch.hxx +2 -0
  58. data/ext/couchbase/operations/document_unlock.hxx +2 -0
  59. data/ext/couchbase/operations/document_upsert.hxx +2 -0
  60. data/ext/couchbase/operations/query_index_create.hxx +14 -4
  61. data/ext/couchbase/operations/query_index_drop.hxx +12 -2
  62. data/ext/couchbase/operations/query_index_get_all.hxx +11 -2
  63. data/ext/couchbase/origin.hxx +47 -17
  64. data/ext/couchbase/platform/backtrace.c +189 -0
  65. data/ext/couchbase/platform/backtrace.h +54 -0
  66. data/ext/couchbase/platform/terminate_handler.cc +122 -0
  67. data/ext/couchbase/platform/terminate_handler.h +36 -0
  68. data/ext/couchbase/protocol/cmd_get_cluster_config.hxx +6 -1
  69. data/ext/couchbase/protocol/status.hxx +14 -4
  70. data/ext/couchbase/version.hxx +2 -2
  71. data/ext/extconf.rb +39 -36
  72. data/ext/test/main.cxx +64 -16
  73. data/lib/couchbase.rb +0 -1
  74. data/lib/couchbase/analytics_options.rb +2 -4
  75. data/lib/couchbase/authenticator.rb +14 -0
  76. data/lib/couchbase/binary_collection.rb +9 -9
  77. data/lib/couchbase/binary_collection_options.rb +8 -6
  78. data/lib/couchbase/bucket.rb +18 -18
  79. data/lib/couchbase/cluster.rb +121 -90
  80. data/lib/couchbase/collection.rb +36 -38
  81. data/lib/couchbase/collection_options.rb +31 -17
  82. data/lib/couchbase/common_options.rb +1 -1
  83. data/lib/couchbase/datastructures/couchbase_list.rb +16 -16
  84. data/lib/couchbase/datastructures/couchbase_map.rb +18 -18
  85. data/lib/couchbase/datastructures/couchbase_queue.rb +13 -13
  86. data/lib/couchbase/datastructures/couchbase_set.rb +8 -7
  87. data/lib/couchbase/errors.rb +10 -3
  88. data/lib/couchbase/json_transcoder.rb +2 -2
  89. data/lib/couchbase/libcouchbase.bundle +0 -0
  90. data/lib/couchbase/management/analytics_index_manager.rb +37 -37
  91. data/lib/couchbase/management/bucket_manager.rb +25 -25
  92. data/lib/couchbase/management/collection_manager.rb +3 -3
  93. data/lib/couchbase/management/query_index_manager.rb +59 -14
  94. data/lib/couchbase/management/search_index_manager.rb +15 -12
  95. data/lib/couchbase/management/user_manager.rb +1 -1
  96. data/lib/couchbase/management/view_index_manager.rb +11 -5
  97. data/lib/couchbase/mutation_state.rb +12 -0
  98. data/lib/couchbase/query_options.rb +23 -9
  99. data/lib/couchbase/scope.rb +61 -1
  100. data/lib/couchbase/search_options.rb +40 -27
  101. data/lib/couchbase/subdoc.rb +31 -28
  102. data/lib/couchbase/version.rb +2 -2
  103. data/lib/couchbase/view_options.rb +0 -1
  104. metadata +20 -7
@@ -0,0 +1,30 @@
1
+ /* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2
+ /*
3
+ * Copyright 2020 Couchbase, Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ #pragma once
19
+
20
+ #include <chrono>
21
+ #include <optional>
22
+
23
+ namespace couchbase::io
24
+ {
25
+ struct retry_action {
26
+ bool retry_requested{ false };
27
+ std::chrono::milliseconds duration{};
28
+ };
29
+
30
+ } // namespace couchbase::io
@@ -0,0 +1,39 @@
1
+ /* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2
+ /*
3
+ * Copyright 2020 Couchbase, Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ #pragma once
19
+
20
+ #include <set>
21
+ #include <chrono>
22
+
23
+ #include <io/retry_reason.hxx>
24
+ #include <io/retry_strategy.hxx>
25
+
26
+ namespace couchbase::io
27
+ {
28
+
29
+ template<class RetryStrategy>
30
+ struct retry_context
31
+ {
32
+ bool idempotent;
33
+ int retry_attempts{ 0 };
34
+ std::chrono::milliseconds last_duration{ 0 };
35
+ std::set<retry_reason> reasons{};
36
+ RetryStrategy strategy{};
37
+ };
38
+
39
+ } // namespace couchbase::io
@@ -0,0 +1,96 @@
1
+ /* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2
+ /*
3
+ * Copyright 2020 Couchbase, Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ #pragma once
19
+
20
+ #include <spdlog/spdlog.h>
21
+
22
+ #include <io/retry_reason.hxx>
23
+ #include <io/retry_action.hxx>
24
+
25
+ namespace couchbase::io::retry_orchestrator
26
+ {
27
+
28
+ namespace priv
29
+ {
30
+ template<class Command>
31
+ std::chrono::milliseconds
32
+ cap_duration(std::chrono::milliseconds uncapped, std::shared_ptr<Command> command)
33
+ {
34
+ auto theoretical_deadline = std::chrono::steady_clock::now() + uncapped;
35
+ auto absolute_deadline = command->deadline.expiry();
36
+ auto delta = std::chrono::duration_cast<std::chrono::milliseconds>(theoretical_deadline - absolute_deadline);
37
+ if (delta.count() > 0) {
38
+ auto capped = uncapped - delta;
39
+ if (capped.count() < 0) {
40
+ return uncapped; // something went wrong, return the uncapped one as a safety net
41
+ }
42
+ return capped;
43
+ }
44
+ return uncapped;
45
+ }
46
+
47
+ std::chrono::milliseconds
48
+ controlled_backoff(int retry_attempts)
49
+ {
50
+ switch (retry_attempts) {
51
+ case 0:
52
+ return std::chrono::milliseconds(1);
53
+ case 1:
54
+ return std::chrono::milliseconds(10);
55
+ case 2:
56
+ return std::chrono::milliseconds(50);
57
+ case 3:
58
+ return std::chrono::milliseconds(100);
59
+ case 4:
60
+ return std::chrono::milliseconds(500);
61
+ default:
62
+ return std::chrono::milliseconds(1000);
63
+ }
64
+ }
65
+
66
+ template<class Manager, class Command>
67
+ void
68
+ retry_with_duration(std::shared_ptr<Manager> manager,
69
+ std::shared_ptr<Command> command,
70
+ retry_reason reason,
71
+ std::chrono::milliseconds duration)
72
+ {
73
+ ++command->request.retries.retry_attempts;
74
+ command->request.retries.reasons.insert(reason);
75
+ command->request.retries.last_duration = duration;
76
+ manager->schedule_for_retry(command, duration);
77
+ }
78
+
79
+ } // namespace priv
80
+
81
+ template<class Manager, class Command>
82
+ void
83
+ maybe_retry(std::shared_ptr<Manager> manager, std::shared_ptr<Command> command, retry_reason reason, std::error_code ec)
84
+ {
85
+ if (always_retry(reason)) {
86
+ return priv::retry_with_duration(manager, command, reason, priv::controlled_backoff(command->request.retries.retry_attempts));
87
+ }
88
+
89
+ retry_action action = command->request.retries.strategy.should_retry(command->request, reason);
90
+ if (action.retry_requested) {
91
+ return priv::retry_with_duration(manager, command, reason, priv::cap_duration(action.duration, command));
92
+ }
93
+ return command->invoke_handler(ec);
94
+ }
95
+
96
+ } // namespace couchbase::io::retry_orchestrator
@@ -0,0 +1,235 @@
1
+ /* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2
+ /*
3
+ * Copyright 2020 Couchbase, Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ #pragma once
19
+
20
+ #include <spdlog/fmt/fmt.h>
21
+
22
+ namespace couchbase::io
23
+ {
24
+ enum class retry_reason {
25
+ /**
26
+ * default value, e.g. when we don't need to retry
27
+ */
28
+ do_not_retry,
29
+
30
+ /**
31
+ * All unexpected/unknown retry errors must not be retried to avoid accidental data loss and non-deterministic behavior.
32
+ */
33
+ unknown,
34
+
35
+ /**
36
+ * The socket is not available into which the operation should’ve been written.
37
+ */
38
+ socket_not_available,
39
+
40
+ /**
41
+ * The service on a node (i.e. kv, query) is not available.
42
+ */
43
+ service_not_available,
44
+
45
+ /**
46
+ * The node where the operation is supposed to be dispatched to is not available.
47
+ */
48
+ node_not_available,
49
+
50
+ /**
51
+ * A not my vbucket response has been received.
52
+ */
53
+ kv_not_my_vbucket,
54
+
55
+ /**
56
+ * A KV response has been received which signals an outdated collection.
57
+ */
58
+ kv_collection_outdated,
59
+
60
+ /**
61
+ * An unknown response was returned and the consulted KV error map indicated a retry.
62
+ */
63
+ kv_error_map_retry_indicated,
64
+
65
+ kv_locked,
66
+
67
+ kv_temporary_failure,
68
+
69
+ kv_sync_write_in_progress,
70
+
71
+ kv_sync_write_re_commit_in_progress,
72
+
73
+ service_response_code_indicated,
74
+
75
+ /**
76
+ * While an operation was in-flight, the underlying socket has been closed.
77
+ */
78
+ socket_closed_while_in_flight,
79
+
80
+ /**
81
+ * The circuit breaker is open for the given socket/endpoint and as a result the operation is not sent into it.
82
+ */
83
+ circuit_breaker_open,
84
+
85
+ query_prepared_statement_failure,
86
+
87
+ query_index_not_found,
88
+
89
+ analytics_temporary_failure,
90
+
91
+ search_too_many_requests,
92
+
93
+ views_temporary_failure,
94
+
95
+ views_no_active_partition,
96
+ };
97
+
98
+ constexpr inline bool
99
+ allows_non_idempotent_retry(retry_reason reason)
100
+ {
101
+ switch (reason) {
102
+ case retry_reason::socket_not_available:
103
+ case retry_reason::service_not_available:
104
+ case retry_reason::node_not_available:
105
+ case retry_reason::kv_not_my_vbucket:
106
+ case retry_reason::kv_collection_outdated:
107
+ case retry_reason::kv_error_map_retry_indicated:
108
+ case retry_reason::kv_locked:
109
+ case retry_reason::kv_temporary_failure:
110
+ case retry_reason::kv_sync_write_in_progress:
111
+ case retry_reason::kv_sync_write_re_commit_in_progress:
112
+ case retry_reason::service_response_code_indicated:
113
+ case retry_reason::circuit_breaker_open:
114
+ case retry_reason::query_prepared_statement_failure:
115
+ case retry_reason::query_index_not_found:
116
+ case retry_reason::analytics_temporary_failure:
117
+ case retry_reason::search_too_many_requests:
118
+ case retry_reason::views_temporary_failure:
119
+ case retry_reason::views_no_active_partition:
120
+ return true;
121
+ case retry_reason::do_not_retry:
122
+ case retry_reason::socket_closed_while_in_flight:
123
+ case retry_reason::unknown:
124
+ return false;
125
+ }
126
+ return false;
127
+ }
128
+
129
+ constexpr inline bool
130
+ always_retry(retry_reason reason)
131
+ {
132
+ switch (reason) {
133
+ case retry_reason::kv_not_my_vbucket:
134
+ case retry_reason::kv_collection_outdated:
135
+ case retry_reason::views_no_active_partition:
136
+ return true;
137
+ case retry_reason::do_not_retry:
138
+ case retry_reason::socket_not_available:
139
+ case retry_reason::service_not_available:
140
+ case retry_reason::node_not_available:
141
+ case retry_reason::kv_error_map_retry_indicated:
142
+ case retry_reason::kv_locked:
143
+ case retry_reason::kv_temporary_failure:
144
+ case retry_reason::kv_sync_write_in_progress:
145
+ case retry_reason::kv_sync_write_re_commit_in_progress:
146
+ case retry_reason::service_response_code_indicated:
147
+ case retry_reason::socket_closed_while_in_flight:
148
+ case retry_reason::circuit_breaker_open:
149
+ case retry_reason::query_prepared_statement_failure:
150
+ case retry_reason::query_index_not_found:
151
+ case retry_reason::analytics_temporary_failure:
152
+ case retry_reason::search_too_many_requests:
153
+ case retry_reason::views_temporary_failure:
154
+ case retry_reason::unknown:
155
+ return false;
156
+ }
157
+ return false;
158
+ }
159
+
160
+ } // namespace couchbase::io
161
+
162
+ template<>
163
+ struct fmt::formatter<couchbase::io::retry_reason> : formatter<string_view> {
164
+ template<typename FormatContext>
165
+ auto format(couchbase::io::retry_reason reason, FormatContext& ctx)
166
+ {
167
+ string_view name = "unknown";
168
+ switch (reason) {
169
+ case couchbase::io::retry_reason::do_not_retry:
170
+ name = "do_not_retry";
171
+ break;
172
+ case couchbase::io::retry_reason::unknown:
173
+ name = "unknown";
174
+ break;
175
+ case couchbase::io::retry_reason::socket_not_available:
176
+ name = "socket_not_available";
177
+ break;
178
+ case couchbase::io::retry_reason::service_not_available:
179
+ name = "service_not_available";
180
+ break;
181
+ case couchbase::io::retry_reason::node_not_available:
182
+ name = "node_not_available";
183
+ break;
184
+ case couchbase::io::retry_reason::kv_not_my_vbucket:
185
+ name = "kv_not_my_vbucket";
186
+ break;
187
+ case couchbase::io::retry_reason::kv_collection_outdated:
188
+ name = "kv_collection_outdated";
189
+ break;
190
+ case couchbase::io::retry_reason::kv_error_map_retry_indicated:
191
+ name = "kv_error_map_retry_indicated";
192
+ break;
193
+ case couchbase::io::retry_reason::kv_locked:
194
+ name = "kv_locked";
195
+ break;
196
+ case couchbase::io::retry_reason::kv_temporary_failure:
197
+ name = "kv_temporary_failure";
198
+ break;
199
+ case couchbase::io::retry_reason::kv_sync_write_in_progress:
200
+ name = "kv_sync_write_in_progress";
201
+ break;
202
+ case couchbase::io::retry_reason::kv_sync_write_re_commit_in_progress:
203
+ name = "kv_sync_write_re_commit_in_progress";
204
+ break;
205
+ case couchbase::io::retry_reason::service_response_code_indicated:
206
+ name = "service_response_code_indicated";
207
+ break;
208
+ case couchbase::io::retry_reason::socket_closed_while_in_flight:
209
+ name = "socket_closed_while_in_flight";
210
+ break;
211
+ case couchbase::io::retry_reason::circuit_breaker_open:
212
+ name = "circuit_breaker_open";
213
+ break;
214
+ case couchbase::io::retry_reason::query_prepared_statement_failure:
215
+ name = "query_prepared_statement_failure";
216
+ break;
217
+ case couchbase::io::retry_reason::query_index_not_found:
218
+ name = "query_index_not_found";
219
+ break;
220
+ case couchbase::io::retry_reason::analytics_temporary_failure:
221
+ name = "analytics_temporary_failure";
222
+ break;
223
+ case couchbase::io::retry_reason::search_too_many_requests:
224
+ name = "search_too_many_requests";
225
+ break;
226
+ case couchbase::io::retry_reason::views_temporary_failure:
227
+ name = "views_temporary_failure";
228
+ break;
229
+ case couchbase::io::retry_reason::views_no_active_partition:
230
+ name = "views_no_active_partition";
231
+ break;
232
+ }
233
+ return formatter<string_view>::format(name, ctx);
234
+ }
235
+ };
@@ -0,0 +1,156 @@
1
+ /* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2
+ /*
3
+ * Copyright 2020 Couchbase, Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ #pragma once
19
+
20
+ #include <gsl/gsl_assert>
21
+
22
+ #include <io/retry_reason.hxx>
23
+ #include <io/retry_action.hxx>
24
+
25
+ namespace couchbase::io::retry_strategy
26
+ {
27
+ namespace backoff
28
+ {
29
+ struct backoff_delay {
30
+ std::chrono::milliseconds delay;
31
+ std::chrono::milliseconds min_delay;
32
+ std::chrono::milliseconds max_delay;
33
+ };
34
+
35
+ class fixed
36
+ {
37
+ private:
38
+ backoff_delay delay_;
39
+
40
+ public:
41
+ explicit fixed(std::chrono::milliseconds delay)
42
+ : delay_{ delay, delay, delay }
43
+ {
44
+ }
45
+
46
+ template<class Request>
47
+ backoff_delay operator()(Request&)
48
+ {
49
+ return delay_;
50
+ }
51
+ };
52
+
53
+ class exponential
54
+ {
55
+ public:
56
+ /**
57
+ * Backoff function with exponential backoff delay. Retries are performed after a backoff interval of
58
+ *
59
+ * first_backoff * (factor^n)
60
+ *
61
+ * where n is the iteration. If max_backoff is not zero, the maximum backoff applied will be limited to max_backoff.
62
+ *
63
+ * If based_on_previous_value is true, backoff will be calculated using
64
+ *
65
+ * prev_backoff * factor
66
+ *
67
+ * When backoffs are combined with jitter, this value will be different from the actual exponential value for the iteration.
68
+ *
69
+ * @param first_backoff First backoff duration
70
+ * @param factor The multiplicand for calculating backoff
71
+ * @param max_backoff Maximum backoff duration
72
+ * @param based_on_previous_value If true, calculation is based on previous value which may be a backoff with jitter applied
73
+ */
74
+ exponential(std::chrono::milliseconds first_backoff,
75
+ int factor,
76
+ std::chrono::milliseconds max_backoff = {},
77
+ bool based_on_previous_value = false)
78
+ {
79
+ Expects(first_backoff.count() > 0);
80
+ if (max_backoff.count() <= 0) {
81
+ max_backoff = std::chrono::milliseconds{ std::numeric_limits<std::chrono::milliseconds::rep>::max() };
82
+ }
83
+ Expects(max_backoff > first_backoff);
84
+ first_backoff_ = first_backoff;
85
+ max_backoff_ = max_backoff;
86
+ factor_ = factor;
87
+ based_on_previous_value_ = based_on_previous_value;
88
+ }
89
+
90
+ template<class Request>
91
+ backoff_delay operator()(Request& request)
92
+ {
93
+ std::chrono::milliseconds previous_backoff = request.retries.last_duration;
94
+ std::chrono::milliseconds next_backoff;
95
+
96
+ if (based_on_previous_value_) {
97
+ if (previous_backoff >= max_backoff_) {
98
+ next_backoff = max_backoff_;
99
+ } else {
100
+ next_backoff = previous_backoff * factor_;
101
+ }
102
+ if (next_backoff < first_backoff_) {
103
+ next_backoff = first_backoff_;
104
+ }
105
+ } else {
106
+ if (previous_backoff >= max_backoff_) {
107
+ next_backoff = max_backoff_;
108
+ } else {
109
+ next_backoff = first_backoff_ * static_cast<int>(std::pow(factor_, request.retries.retry_attempts - 1));
110
+ }
111
+ }
112
+ return { next_backoff, first_backoff_, max_backoff_ };
113
+ }
114
+
115
+ private:
116
+ std::chrono::milliseconds first_backoff_;
117
+ std::chrono::milliseconds max_backoff_;
118
+ int factor_;
119
+ bool based_on_previous_value_;
120
+ };
121
+
122
+ } // namespace backoff
123
+
124
+ class best_effort
125
+ {
126
+ public:
127
+ best_effort()
128
+ : backoff_(std::chrono::milliseconds(1), 2, std::chrono::milliseconds(500))
129
+ {
130
+ }
131
+
132
+ template<class Request>
133
+ retry_action should_retry(Request& request, retry_reason reason)
134
+ {
135
+ if (request.retries.idempotent || allows_non_idempotent_retry(reason)) {
136
+ backoff::backoff_delay delay = backoff_(request);
137
+ return { true, delay.delay };
138
+ }
139
+ return { false };
140
+ }
141
+
142
+ private:
143
+ backoff::exponential backoff_;
144
+ };
145
+
146
+ class fail_fast
147
+ {
148
+ public:
149
+ template<class Request>
150
+ retry_action should_retry(Request&, retry_reason)
151
+ {
152
+ return { false };
153
+ }
154
+ };
155
+
156
+ } // namespace couchbase::io::retry_strategy