couchbase 3.8.2 → 3.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/ext/CMakeLists.txt +16 -1
- data/ext/cache/cpm/{CPM_0.42.0.cmake → CPM_0.43.1.cmake} +18 -2
- data/ext/cache/extconf_include.rb +6 -6
- data/ext/cache/mozilla-ca-bundle.crt +121 -55
- data/ext/cache/mozilla-ca-bundle.sha256 +1 -1
- data/ext/couchbase/CMakeLists.txt +136 -23
- data/ext/couchbase/cmake/APKBUILD.in +25 -4
- data/ext/couchbase/cmake/Bundler.cmake +143 -34
- data/ext/couchbase/cmake/CPM.cmake +126 -12
- data/ext/couchbase/cmake/Cache.cmake +7 -1
- data/ext/couchbase/cmake/CompilerOptions.cmake +1 -1
- data/ext/couchbase/cmake/CompilerWarnings.cmake +17 -6
- data/ext/couchbase/cmake/GrpcProtobuf.cmake +481 -0
- data/ext/couchbase/cmake/OpenSSL.cmake +82 -7
- data/ext/couchbase/cmake/Packaging.cmake +519 -65
- data/ext/couchbase/cmake/Protostellar.cmake +250 -0
- data/ext/couchbase/cmake/Sanitizers.cmake +61 -50
- data/ext/couchbase/cmake/StaticAnalyzers.cmake +16 -5
- data/ext/couchbase/cmake/TestFramework.cmake +283 -0
- data/ext/couchbase/cmake/TestFrameworkAddTests.cmake +51 -0
- data/ext/couchbase/cmake/Testing.cmake +27 -9
- data/ext/couchbase/cmake/ThirdPartyDependencies.cmake +141 -8
- data/ext/couchbase/cmake/VersionInfo.cmake +50 -0
- data/ext/couchbase/cmake/build_config.hxx.in +2 -1
- data/ext/couchbase/cmake/couchbase-cxx-client.spec.in +101 -23
- data/ext/couchbase/cmake/couchbase_cxx_client_static-config.cmake.in +7 -0
- data/ext/couchbase/cmake/couchbase_cxx_client_static.pc.in +2 -0
- data/ext/couchbase/cmake/gRPC_Generate.cmake +58 -0
- data/ext/couchbase/cmake/protobuf_Generate.cmake +69 -0
- data/ext/couchbase/cmake/require-git-checkout.cmake +25 -0
- data/ext/couchbase/cmake/tarball_glob.txt +49 -0
- data/ext/couchbase/core/agent_group.cxx +0 -8
- data/ext/couchbase/core/agent_group.hxx +0 -4
- data/ext/couchbase/core/analytics_stream.cxx +314 -0
- data/ext/couchbase/core/analytics_stream.hxx +129 -0
- data/ext/couchbase/core/analytics_stream_component.cxx +245 -0
- data/ext/couchbase/core/analytics_stream_component.hxx +67 -0
- data/ext/couchbase/core/app_telemetry_meter.cxx +25 -3
- data/ext/couchbase/core/app_telemetry_meter.hxx +77 -0
- data/ext/couchbase/core/app_telemetry_reporter.cxx +7 -6
- data/ext/couchbase/core/bucket.cxx +381 -87
- data/ext/couchbase/core/bucket.hxx +105 -25
- data/ext/couchbase/core/bucket_unit_test_api.hxx +57 -0
- data/ext/couchbase/core/capella.hxx +91 -0
- data/ext/couchbase/core/cluster.cxx +1551 -397
- data/ext/couchbase/core/cluster.hxx +39 -8
- data/ext/couchbase/core/cluster_agent.cxx +0 -8
- data/ext/couchbase/core/cluster_agent.hxx +0 -4
- data/ext/couchbase/core/cluster_options.hxx +26 -3
- data/ext/couchbase/core/collections_component.cxx +39 -15
- data/ext/couchbase/core/config_profiles.cxx +1 -1
- data/ext/couchbase/core/crud_component.cxx +2 -2
- data/ext/couchbase/core/crud_options.hxx +34 -0
- data/ext/couchbase/core/crypto/cbcrypto.cc +18 -13
- data/ext/couchbase/core/document_id_redaction.hxx +81 -0
- data/ext/couchbase/core/error_context/base_error_context.hxx +7 -6
- data/ext/couchbase/core/error_context/key_value.cxx +25 -2
- data/ext/couchbase/core/error_context/key_value.hxx +60 -33
- data/ext/couchbase/core/error_context/key_value_error_context.hxx +16 -15
- data/ext/couchbase/core/error_context/search.hxx +5 -0
- data/ext/couchbase/core/error_context/search_json.hxx +3 -0
- data/ext/couchbase/core/error_context/subdocument_error_context.hxx +19 -18
- data/ext/couchbase/core/error_context/view.hxx +5 -0
- data/ext/couchbase/core/free_form_http_request.cxx +237 -4
- data/ext/couchbase/core/free_form_http_request.hxx +41 -8
- data/ext/couchbase/core/http_component.cxx +300 -284
- data/ext/couchbase/core/http_component.hxx +0 -4
- data/ext/couchbase/core/impl/analytics.cxx +38 -5
- data/ext/couchbase/core/impl/analytics.hxx +34 -0
- data/ext/couchbase/core/impl/bootstrap_error.hxx +0 -3
- data/ext/couchbase/core/impl/collection.cxx +215 -202
- data/ext/couchbase/core/impl/collection_manager.cxx +1 -1
- data/ext/couchbase/core/impl/dns_srv_tracker.cxx +45 -18
- data/ext/couchbase/core/impl/error.cxx +22 -2
- data/ext/couchbase/core/impl/internal_analytics_stream_result.hxx +111 -0
- data/ext/couchbase/core/impl/internal_query_stream_result.hxx +110 -0
- data/ext/couchbase/core/impl/invoke_with_node_id.hxx +15 -7
- data/ext/couchbase/core/impl/key_value_error_category.cxx +6 -0
- data/ext/couchbase/core/impl/lookup_in_replica.cxx +10 -10
- data/ext/couchbase/core/impl/lookup_in_replica.hxx +4 -4
- data/ext/couchbase/core/impl/node_id.cxx +49 -13
- data/ext/couchbase/core/impl/observability_recorder.cxx +12 -2
- data/ext/couchbase/core/impl/observe_poll.cxx +63 -23
- data/ext/couchbase/core/impl/public_analytics_stream_result.cxx +372 -0
- data/ext/couchbase/core/impl/public_bucket.cxx +48 -2
- data/ext/couchbase/core/impl/public_cluster.cxx +229 -42
- data/ext/couchbase/core/impl/public_query_stream_result.cxx +380 -0
- data/ext/couchbase/core/impl/public_transaction_get_multi_replicas_from_preferred_server_group_result.cxx +42 -0
- data/ext/couchbase/core/impl/public_transaction_get_multi_result.cxx +42 -0
- data/ext/couchbase/core/impl/query.cxx +76 -7
- data/ext/couchbase/core/impl/query.hxx +36 -0
- data/ext/couchbase/core/impl/query_index_manager.cxx +54 -1
- data/ext/couchbase/core/impl/replica_utils.cxx +101 -0
- data/ext/couchbase/core/impl/replica_utils.hxx +64 -0
- data/ext/couchbase/core/impl/resolve_node_id.hxx +125 -0
- data/ext/couchbase/core/impl/scope.cxx +70 -0
- data/ext/couchbase/core/impl/search.cxx +31 -1
- data/ext/couchbase/core/impl/transactions.cxx +130 -0
- data/ext/couchbase/core/impl/wait_until_ready.cxx +439 -0
- data/ext/couchbase/core/impl/wait_until_ready.hxx +110 -0
- data/ext/couchbase/core/impl/with_bucket_config_or_timeout.hxx +180 -0
- data/ext/couchbase/core/impl/with_cancellation.hxx +11 -3
- data/ext/couchbase/core/io/configuration_belongs_to_session.hxx +1 -2
- data/ext/couchbase/core/io/dns_client.cxx +122 -45
- data/ext/couchbase/core/io/dns_codec.hxx +21 -21
- data/ext/couchbase/core/io/dns_config.cxx +21 -6
- data/ext/couchbase/core/io/http_command.hxx +149 -121
- data/ext/couchbase/core/io/http_error.hxx +107 -0
- data/ext/couchbase/core/io/http_parser.cxx +4 -0
- data/ext/couchbase/core/io/http_session.cxx +606 -154
- data/ext/couchbase/core/io/http_session.hxx +147 -30
- data/ext/couchbase/core/io/http_session_manager.hxx +329 -382
- data/ext/couchbase/core/io/http_streaming_parser.cxx +4 -0
- data/ext/couchbase/core/io/http_streaming_response.cxx +328 -43
- data/ext/couchbase/core/io/http_streaming_response.hxx +37 -3
- data/ext/couchbase/core/io/mcbp_buffer_pool.hxx +122 -0
- data/ext/couchbase/core/io/mcbp_command.hxx +150 -51
- data/ext/couchbase/core/io/mcbp_command_id.hxx +45 -0
- data/ext/couchbase/core/io/mcbp_message.cxx +9 -1
- data/ext/couchbase/core/io/mcbp_message.hxx +19 -0
- data/ext/couchbase/core/io/mcbp_output_queue.hxx +150 -0
- data/ext/couchbase/core/io/mcbp_parser.cxx +24 -7
- data/ext/couchbase/core/io/mcbp_session.cxx +309 -301
- data/ext/couchbase/core/io/mcbp_session.hxx +27 -18
- data/ext/couchbase/core/io/opaque_ring_table.hxx +145 -0
- data/ext/couchbase/core/io/retry_orchestrator.hxx +6 -5
- data/ext/couchbase/core/io/stream_deadline.hxx +50 -0
- data/ext/couchbase/core/io/streams.cxx +151 -21
- data/ext/couchbase/core/io/streams.hxx +48 -1
- data/ext/couchbase/core/logger/logger.cxx +36 -0
- data/ext/couchbase/core/logger/logger.hxx +46 -6
- data/ext/couchbase/core/logger/redaction.hxx +503 -0
- data/ext/couchbase/core/management/eventing_status.hxx +10 -0
- data/ext/couchbase/core/management/eventing_status_json.hxx +4 -0
- data/ext/couchbase/core/mcbp/big_endian.cxx +1 -1
- data/ext/couchbase/core/mcbp/codec.cxx +27 -18
- data/ext/couchbase/core/mcbp/operation_queue.cxx +2 -2
- data/ext/couchbase/core/mcbp/packet.hxx +2 -2
- data/ext/couchbase/core/mcbp/queue_request.cxx +23 -6
- data/ext/couchbase/core/mcbp/queue_request.hxx +21 -0
- data/ext/couchbase/core/meta/features.hxx +13 -0
- data/ext/couchbase/core/meta/version.cxx +6 -3
- data/ext/couchbase/core/metrics/logging_meter.cxx +5 -10
- data/ext/couchbase/core/metrics/meter_wrapper.cxx +63 -33
- data/ext/couchbase/core/metrics/meter_wrapper.hxx +55 -3
- data/ext/couchbase/core/operations/analytics_response_parsing.cxx +177 -0
- data/ext/couchbase/core/operations/analytics_response_parsing.hxx +55 -0
- data/ext/couchbase/core/operations/document_analytics.cxx +48 -130
- data/ext/couchbase/core/operations/document_analytics.hxx +14 -2
- data/ext/couchbase/core/operations/document_get_all_replicas.hxx +15 -7
- data/ext/couchbase/core/operations/document_get_any_replica.hxx +19 -8
- data/ext/couchbase/core/operations/document_get_projected.cxx +1 -1
- data/ext/couchbase/core/{impl/get_replica.cxx → operations/document_get_replica.cxx} +21 -3
- data/ext/couchbase/core/{impl/get_replica.hxx → operations/document_get_replica.hxx} +31 -4
- data/ext/couchbase/core/operations/document_lookup_in.cxx +10 -10
- data/ext/couchbase/core/operations/document_lookup_in_all_replicas.hxx +228 -198
- data/ext/couchbase/core/operations/document_lookup_in_any_replica.hxx +215 -217
- data/ext/couchbase/core/operations/document_query.cxx +108 -221
- data/ext/couchbase/core/operations/document_query.hxx +18 -4
- data/ext/couchbase/core/operations/document_search.cxx +52 -8
- data/ext/couchbase/core/operations/document_search.hxx +3 -0
- data/ext/couchbase/core/operations/document_view.cxx +3 -3
- data/ext/couchbase/core/operations/management/analytics_dataset_create.cxx +15 -8
- data/ext/couchbase/core/operations/management/analytics_dataset_create.hxx +4 -0
- data/ext/couchbase/core/operations/management/analytics_dataset_drop.cxx +11 -6
- data/ext/couchbase/core/operations/management/analytics_dataset_get_all.cxx +3 -2
- data/ext/couchbase/core/operations/management/analytics_dataverse_create.cxx +10 -5
- data/ext/couchbase/core/operations/management/analytics_dataverse_drop.cxx +10 -5
- data/ext/couchbase/core/operations/management/analytics_get_pending_mutations.cxx +2 -1
- data/ext/couchbase/core/operations/management/analytics_index_create.cxx +33 -8
- data/ext/couchbase/core/operations/management/analytics_index_drop.cxx +12 -7
- data/ext/couchbase/core/operations/management/analytics_index_get_all.cxx +3 -2
- data/ext/couchbase/core/operations/management/analytics_link_connect.cxx +11 -6
- data/ext/couchbase/core/operations/management/analytics_link_create.cxx +3 -3
- data/ext/couchbase/core/operations/management/analytics_link_disconnect.cxx +10 -4
- data/ext/couchbase/core/operations/management/analytics_link_drop.cxx +6 -4
- data/ext/couchbase/core/operations/management/analytics_link_get_all.cxx +4 -3
- data/ext/couchbase/core/operations/management/analytics_link_replace.cxx +3 -3
- data/ext/couchbase/core/operations/management/analytics_link_utils.hxx +1 -1
- data/ext/couchbase/core/operations/management/change_password.cxx +2 -0
- data/ext/couchbase/core/operations/management/collection_drop.cxx +5 -1
- data/ext/couchbase/core/operations/management/error_utils.cxx +60 -6
- data/ext/couchbase/core/operations/management/error_utils.hxx +29 -1
- data/ext/couchbase/core/operations/management/eventing_deploy_function.cxx +9 -3
- data/ext/couchbase/core/operations/management/eventing_drop_function.cxx +8 -3
- data/ext/couchbase/core/operations/management/eventing_get_all_functions.cxx +4 -2
- data/ext/couchbase/core/operations/management/eventing_get_function.cxx +5 -3
- data/ext/couchbase/core/operations/management/eventing_get_status.cxx +4 -2
- data/ext/couchbase/core/operations/management/eventing_pause_function.cxx +9 -3
- data/ext/couchbase/core/operations/management/eventing_resume_function.cxx +9 -3
- data/ext/couchbase/core/operations/management/eventing_undeploy_function.cxx +9 -3
- data/ext/couchbase/core/operations/management/eventing_upsert_function.cxx +9 -3
- data/ext/couchbase/core/operations/management/group_drop.cxx +3 -1
- data/ext/couchbase/core/operations/management/group_get.cxx +3 -1
- data/ext/couchbase/core/operations/management/group_upsert.cxx +11 -8
- data/ext/couchbase/core/operations/management/query_index_build.cxx +5 -2
- data/ext/couchbase/core/operations/management/query_index_create.cxx +9 -3
- data/ext/couchbase/core/operations/management/query_index_drop.cxx +11 -4
- data/ext/couchbase/core/operations/management/query_index_get_all.cxx +1 -1
- data/ext/couchbase/core/operations/management/query_index_get_all_deferred.cxx +1 -1
- data/ext/couchbase/core/operations/management/scope_drop.cxx +5 -1
- data/ext/couchbase/core/operations/management/scope_get_all.cxx +6 -1
- data/ext/couchbase/core/operations/management/search_get_stats.cxx +10 -0
- data/ext/couchbase/core/operations/management/search_index_analyze_document.cxx +3 -2
- data/ext/couchbase/core/operations/management/search_index_control_ingest.cxx +4 -3
- data/ext/couchbase/core/operations/management/search_index_control_plan_freeze.cxx +4 -3
- data/ext/couchbase/core/operations/management/search_index_control_query.cxx +4 -3
- data/ext/couchbase/core/operations/management/search_index_drop.cxx +2 -2
- data/ext/couchbase/core/operations/management/search_index_get.cxx +2 -2
- data/ext/couchbase/core/operations/management/search_index_get_documents_count.cxx +3 -2
- data/ext/couchbase/core/operations/management/search_index_get_stats.cxx +3 -1
- data/ext/couchbase/core/operations/management/search_index_upsert.cxx +2 -2
- data/ext/couchbase/core/operations/management/user_drop.cxx +3 -1
- data/ext/couchbase/core/operations/management/user_get.cxx +3 -1
- data/ext/couchbase/core/operations/management/user_upsert.cxx +12 -9
- data/ext/couchbase/core/operations/management/view_index_drop.cxx +1 -1
- data/ext/couchbase/core/operations/management/view_index_get.cxx +1 -1
- data/ext/couchbase/core/operations/management/view_index_upsert.cxx +1 -1
- data/ext/couchbase/core/operations/operation_traits.hxx +18 -0
- data/ext/couchbase/core/operations/query_response_parsing.cxx +211 -0
- data/ext/couchbase/core/operations/query_response_parsing.hxx +60 -0
- data/ext/couchbase/core/operations_fwd.hxx +3 -3
- data/ext/couchbase/core/origin.cxx +54 -26
- data/ext/couchbase/core/origin.hxx +12 -0
- data/ext/couchbase/core/orphan_reporter.cxx +2 -1
- data/ext/couchbase/core/platform/random.cc +7 -7
- data/ext/couchbase/core/protocol/client_request.cxx +2 -2
- data/ext/couchbase/core/protocol/client_request.hxx +38 -21
- data/ext/couchbase/core/protocol/client_response.cxx +11 -3
- data/ext/couchbase/core/protocol/client_response.hxx +27 -6
- data/ext/couchbase/core/protocol/cmd_append.cxx +2 -2
- data/ext/couchbase/core/protocol/cmd_cluster_map_change_notification.cxx +2 -2
- data/ext/couchbase/core/protocol/cmd_decrement.cxx +6 -6
- data/ext/couchbase/core/protocol/cmd_get.cxx +1 -1
- data/ext/couchbase/core/protocol/cmd_get_and_lock.cxx +2 -2
- data/ext/couchbase/core/protocol/cmd_get_and_touch.cxx +2 -2
- data/ext/couchbase/core/protocol/cmd_get_cluster_config.cxx +6 -4
- data/ext/couchbase/core/protocol/cmd_get_collection_id.cxx +2 -2
- data/ext/couchbase/core/protocol/cmd_get_error_map.cxx +1 -1
- data/ext/couchbase/core/protocol/cmd_get_meta.cxx +4 -4
- data/ext/couchbase/core/protocol/cmd_get_replica.cxx +1 -1
- data/ext/couchbase/core/protocol/cmd_hello.cxx +1 -1
- data/ext/couchbase/core/protocol/cmd_increment.cxx +6 -6
- data/ext/couchbase/core/protocol/cmd_insert.cxx +4 -4
- data/ext/couchbase/core/protocol/cmd_lookup_in.cxx +4 -3
- data/ext/couchbase/core/protocol/cmd_lookup_in_replica.cxx +4 -3
- data/ext/couchbase/core/protocol/cmd_mutate_in.cxx +10 -9
- data/ext/couchbase/core/protocol/cmd_mutate_in.hxx +10 -10
- data/ext/couchbase/core/protocol/cmd_observe_seqno.cxx +7 -7
- data/ext/couchbase/core/protocol/cmd_prepend.cxx +2 -2
- data/ext/couchbase/core/protocol/cmd_remove.cxx +2 -2
- data/ext/couchbase/core/protocol/cmd_replace.cxx +4 -4
- data/ext/couchbase/core/protocol/cmd_touch.cxx +1 -1
- data/ext/couchbase/core/protocol/cmd_upsert.cxx +4 -4
- data/ext/couchbase/core/protocol/datatype.hxx +118 -1
- data/ext/couchbase/core/protocol/frame_info_utils.cxx +1 -1
- data/ext/couchbase/core/protocol/magic.hxx +4 -0
- data/ext/couchbase/core/protocol/magic_fmt.hxx +3 -0
- data/ext/couchbase/core/protocol/server_request.hxx +3 -1
- data/ext/couchbase/core/protocol/status.cxx +1 -1
- data/ext/couchbase/core/protostellar/analytics_converter.hxx +171 -0
- data/ext/couchbase/core/protostellar/bucket_admin_converter.hxx +301 -0
- data/ext/couchbase/core/protostellar/collection_admin_converter.hxx +92 -0
- data/ext/couchbase/core/protostellar/component.cxx +2445 -0
- data/ext/couchbase/core/protostellar/component.hxx +391 -0
- data/ext/couchbase/core/{columnar/bootstrap_notification_subscriber.hxx → protostellar/compression_settings.hxx} +11 -10
- data/ext/couchbase/core/protostellar/credentials.cxx +233 -0
- data/ext/couchbase/core/protostellar/credentials.hxx +88 -0
- data/ext/couchbase/core/protostellar/dispatcher.cxx +57 -0
- data/ext/couchbase/core/protostellar/dispatcher.hxx +482 -0
- data/ext/couchbase/core/protostellar/error_utils.cxx +293 -0
- data/ext/couchbase/core/protostellar/error_utils.hxx +97 -0
- data/ext/couchbase/core/protostellar/json_payload.hxx +49 -0
- data/ext/couchbase/core/protostellar/kv_converter.cxx +70 -0
- data/ext/couchbase/core/protostellar/kv_converter.hxx +600 -0
- data/ext/couchbase/core/protostellar/query_converter.hxx +265 -0
- data/ext/couchbase/core/protostellar/query_index_admin_converter.hxx +291 -0
- data/ext/couchbase/core/protostellar/query_proto.hxx +73 -0
- data/ext/couchbase/core/protostellar/search_converter.hxx +244 -0
- data/ext/couchbase/core/protostellar/search_index_admin_converter.hxx +156 -0
- data/ext/couchbase/core/protostellar/view_converter.hxx +158 -0
- data/ext/couchbase/core/query_stream.cxx +447 -0
- data/ext/couchbase/core/query_stream.hxx +141 -0
- data/ext/couchbase/core/query_stream_component.cxx +243 -0
- data/ext/couchbase/core/query_stream_component.hxx +68 -0
- data/ext/couchbase/core/range_scan_load_balancer.cxx +15 -8
- data/ext/couchbase/core/range_scan_orchestrator.cxx +15 -3
- data/ext/couchbase/core/response_handler.hxx +41 -4
- data/ext/couchbase/core/row_streamer.cxx +332 -46
- data/ext/couchbase/core/row_streamer.hxx +31 -1
- data/ext/couchbase/core/row_streamer_options.hxx +55 -0
- data/ext/couchbase/core/sasl/client.h +3 -0
- data/ext/couchbase/core/search_scoring.hxx +66 -0
- data/ext/couchbase/core/stream_error_details.hxx +69 -0
- data/ext/couchbase/core/timeout_defaults.hxx +0 -1
- data/ext/couchbase/core/topology/capabilities.hxx +6 -0
- data/ext/couchbase/core/topology/capabilities_fmt.hxx +3 -0
- data/ext/couchbase/core/topology/configuration.cxx +21 -6
- data/ext/couchbase/core/topology/configuration.hxx +29 -8
- data/ext/couchbase/core/topology/configuration_json.hxx +3 -0
- data/ext/couchbase/core/topology/error_map_json.hxx +3 -1
- data/ext/couchbase/core/tracing/threshold_logging_tracer.cxx +70 -4
- data/ext/couchbase/core/tracing/threshold_logging_tracer.hxx +10 -0
- data/ext/couchbase/core/transactions/active_transaction_record.cxx +0 -34
- data/ext/couchbase/core/transactions/attempt_context_impl.cxx +108 -63
- data/ext/couchbase/core/transactions/attempt_context_impl.hxx +19 -2
- data/ext/couchbase/core/transactions/error_list.hxx +2 -2
- data/ext/couchbase/core/transactions/get_multi_fetch.hxx +160 -0
- data/ext/couchbase/core/transactions/get_multi_orchestrator.cxx +326 -125
- data/ext/couchbase/core/transactions/get_multi_transaction_id.hxx +62 -0
- data/ext/couchbase/core/transactions/internal/atr_entry.hxx +22 -2
- data/ext/couchbase/core/transactions/internal/transaction_context.hxx +2 -2
- data/ext/couchbase/core/transactions/internal/transactions_cleanup.hxx +23 -1
- data/ext/couchbase/core/transactions/internal/utils.hxx +50 -14
- data/ext/couchbase/core/transactions/staged_mutation.cxx +23 -18
- data/ext/couchbase/core/transactions/staged_mutation.hxx +15 -4
- data/ext/couchbase/core/transactions/transaction_context.cxx +55 -40
- data/ext/couchbase/core/transactions/transaction_get_result.hxx +16 -0
- data/ext/couchbase/core/transactions/transactions.cxx +3 -55
- data/ext/couchbase/core/transactions/transactions_cleanup.cxx +165 -72
- data/ext/couchbase/core/transactions/transactions_config.cxx +0 -11
- data/ext/couchbase/core/transactions/utils.cxx +10 -0
- data/ext/couchbase/core/transactions/waitable_op_list.hxx +2 -2
- data/ext/couchbase/core/transactions.hxx +9 -9
- data/ext/couchbase/core/utils/byteswap.hxx +166 -9
- data/ext/couchbase/core/utils/connection_string.cxx +50 -85
- data/ext/couchbase/core/utils/connection_string.hxx +15 -0
- data/ext/couchbase/core/{columnar/backoff_calculator.hxx → utils/deadline.hxx} +13 -13
- data/ext/couchbase/core/utils/duration_parser.cxx +1 -1
- data/ext/couchbase/core/utils/json_streaming_lexer.cxx +48 -5
- data/ext/couchbase/core/utils/json_streaming_lexer.hxx +4 -1
- data/ext/couchbase/core/utils/movable_function.hxx +301 -52
- data/ext/couchbase/core/utils/name_codec.hxx +154 -11
- data/ext/couchbase/core/{columnar/retry_info.hxx → utils/process_id.hxx} +18 -13
- data/ext/couchbase/core/utils/url_codec.cxx +12 -51
- data/ext/couchbase/core/websocket_codec.cxx +13 -37
- data/ext/couchbase/couchbase/analytics_options.hxx +21 -10
- data/ext/couchbase/couchbase/analytics_row.hxx +105 -0
- data/ext/couchbase/couchbase/analytics_stream_result.hxx +266 -0
- data/ext/couchbase/couchbase/boolean_query.hxx +3 -3
- data/ext/couchbase/couchbase/bucket.hxx +57 -0
- data/ext/couchbase/couchbase/cluster.hxx +183 -5
- data/ext/couchbase/{core/columnar/security_options.hxx → couchbase/cluster_state.hxx} +18 -14
- data/ext/couchbase/couchbase/codec/lenient_json_transcoder.hxx +69 -0
- data/ext/couchbase/couchbase/collection.hxx +234 -14
- data/ext/couchbase/couchbase/common_durability_options.hxx +18 -3
- data/ext/couchbase/couchbase/conjunction_query.hxx +1 -1
- data/ext/couchbase/couchbase/create_dataset_analytics_options.hxx +6 -1
- data/ext/couchbase/couchbase/date_range_query.hxx +2 -2
- data/ext/couchbase/couchbase/decrement_options.hxx +1 -1
- data/ext/couchbase/couchbase/disjunction_query.hxx +1 -1
- data/ext/couchbase/couchbase/error.hxx +32 -0
- data/ext/couchbase/couchbase/error_codes.hxx +33 -1
- data/ext/couchbase/couchbase/geo_bounding_box_query.hxx +1 -1
- data/ext/couchbase/couchbase/geo_distance_query.hxx +1 -1
- data/ext/couchbase/couchbase/geo_polygon_query.hxx +1 -1
- data/ext/couchbase/couchbase/get_replica_options.hxx +68 -0
- data/ext/couchbase/couchbase/get_replica_result.hxx +5 -3
- data/ext/couchbase/couchbase/get_replica_strategy.hxx +161 -0
- data/ext/couchbase/couchbase/get_result.hxx +1 -0
- data/ext/couchbase/couchbase/increment_options.hxx +1 -1
- data/ext/couchbase/couchbase/insert_options.hxx +1 -1
- data/ext/couchbase/couchbase/match_phrase_query.hxx +1 -1
- data/ext/couchbase/couchbase/match_query.hxx +1 -1
- data/ext/couchbase/couchbase/mutate_in_options.hxx +3 -3
- data/ext/couchbase/couchbase/network_options.hxx +1 -1
- data/ext/couchbase/couchbase/node_id.hxx +42 -14
- data/ext/couchbase/couchbase/node_id_for_options.hxx +7 -1
- data/ext/couchbase/couchbase/node_ids_options.hxx +8 -2
- data/ext/couchbase/couchbase/numeric_range_query.hxx +1 -1
- data/ext/couchbase/couchbase/phrase_query.hxx +1 -1
- data/ext/couchbase/couchbase/prefix_query.hxx +1 -1
- data/ext/couchbase/couchbase/query_options.hxx +23 -12
- data/ext/couchbase/couchbase/query_row.hxx +111 -0
- data/ext/couchbase/couchbase/query_stream_result.hxx +302 -0
- data/ext/couchbase/couchbase/query_string_query.hxx +3 -3
- data/ext/couchbase/couchbase/regexp_query.hxx +1 -1
- data/ext/couchbase/couchbase/replace_options.hxx +3 -3
- data/ext/couchbase/couchbase/result.hxx +14 -3
- data/ext/couchbase/couchbase/scan_result_item.hxx +1 -0
- data/ext/couchbase/couchbase/scope.hxx +85 -2
- data/ext/couchbase/couchbase/search_options.hxx +58 -8
- data/ext/couchbase/couchbase/search_scoring.hxx +94 -0
- data/ext/couchbase/couchbase/search_scoring_none.hxx +51 -0
- data/ext/couchbase/couchbase/search_scoring_reciprocal_rank_fusion.hxx +88 -0
- data/ext/couchbase/couchbase/search_scoring_relative_score_fusion.hxx +70 -0
- data/ext/couchbase/couchbase/term_range_query.hxx +1 -1
- data/ext/couchbase/couchbase/tracing/request_span.hxx +46 -0
- data/ext/couchbase/couchbase/transactions/transaction_get_multi_replicas_from_preferred_server_group_result.hxx +23 -21
- data/ext/couchbase/couchbase/transactions/transaction_get_multi_result.hxx +24 -19
- data/ext/couchbase/couchbase/transactions/transaction_get_result.hxx +17 -3
- data/ext/couchbase/couchbase/transactions/transactions_config.hxx +4 -2
- data/ext/couchbase/couchbase/transactions.hxx +27 -18
- data/ext/couchbase/couchbase/upsert_options.hxx +3 -3
- data/ext/couchbase/couchbase/vector_query.hxx +1 -1
- data/ext/couchbase/couchbase/wait_until_ready_options.hxx +111 -0
- data/ext/couchbase/couchbase/wildcard_query.hxx +1 -1
- data/ext/extconf.rb +15 -10
- data/ext/rcb_analytics.cxx +82 -102
- data/ext/rcb_backend.cxx +42 -36
- data/ext/rcb_backend.hxx +2 -0
- data/ext/rcb_buckets.cxx +47 -59
- data/ext/rcb_collections.cxx +42 -52
- data/ext/rcb_crud.cxx +345 -224
- data/ext/rcb_diagnostics.cxx +117 -27
- data/ext/rcb_exceptions.cxx +152 -99
- data/ext/rcb_exceptions.hxx +25 -0
- data/ext/rcb_extras.cxx +18 -19
- data/ext/rcb_hdr_histogram.cxx +19 -4
- data/ext/rcb_logger.cxx +202 -27
- data/ext/rcb_logger.hxx +12 -0
- data/ext/rcb_multi.cxx +40 -40
- data/ext/rcb_observability.cxx +7 -5
- data/ext/rcb_query.cxx +99 -142
- data/ext/rcb_range_scan.cxx +41 -35
- data/ext/rcb_search.cxx +98 -99
- data/ext/rcb_users.cxx +36 -56
- data/ext/rcb_utils.cxx +100 -37
- data/ext/rcb_utils.hxx +287 -33
- data/ext/rcb_version.cxx +1 -1
- data/ext/rcb_views.cxx +55 -51
- data/lib/active_support/cache/couchbase_store.rb +77 -12
- data/lib/couchbase/bucket.rb +20 -0
- data/lib/couchbase/cluster.rb +17 -0
- data/lib/couchbase/collection.rb +36 -1
- data/lib/couchbase/errors.rb +18 -0
- data/lib/couchbase/fork_hooks.rb +16 -7
- data/lib/couchbase/get_replica_strategy.rb +89 -0
- data/lib/couchbase/logger.rb +1 -1
- data/lib/couchbase/management/analytics_index_manager.rb +15 -15
- data/lib/couchbase/management/bucket_manager.rb +6 -6
- data/lib/couchbase/management/collection_manager.rb +6 -6
- data/lib/couchbase/management/query_index_manager.rb +7 -7
- data/lib/couchbase/management/search_index_manager.rb +13 -13
- data/lib/couchbase/management/user_manager.rb +10 -10
- data/lib/couchbase/management/view_index_manager.rb +5 -5
- data/lib/couchbase/options.rb +174 -42
- data/lib/couchbase/protostellar/bucket.rb +4 -0
- data/lib/couchbase/protostellar/cluster.rb +4 -0
- data/lib/couchbase/protostellar/collection.rb +4 -0
- data/lib/couchbase/protostellar/error_handling.rb +2 -1
- data/lib/couchbase/protostellar/request.rb +1 -0
- data/lib/couchbase/protostellar/request_generator/kv.rb +16 -2
- data/lib/couchbase/protostellar/request_generator/search.rb +17 -1
- data/lib/couchbase/protostellar/retry/orchestrator.rb +3 -2
- data/lib/couchbase/protostellar/retry/strategies/fail_fast.rb +33 -0
- data/lib/couchbase/protostellar/retry/strategies.rb +1 -0
- data/lib/couchbase/search_options.rb +95 -6
- data/lib/couchbase/version.rb +1 -1
- metadata +91 -33
- data/ext/0001-fix-build-for-mingw-w64-ucrt-x86_64-toolchain.patch +0 -40
- data/ext/couchbase/core/columnar/agent.hxx +0 -71
- data/ext/couchbase/core/columnar/agent_config.hxx +0 -59
- data/ext/couchbase/core/columnar/background_bootstrap_listener.hxx +0 -42
- data/ext/couchbase/core/columnar/backoff_calculator.cxx +0 -62
- data/ext/couchbase/core/columnar/columnar_agent.cxx +0 -147
- data/ext/couchbase/core/columnar/columnar_agent_config.cxx +0 -48
- data/ext/couchbase/core/columnar/columnar_error.cxx +0 -51
- data/ext/couchbase/core/columnar/database_management_options.hxx +0 -56
- data/ext/couchbase/core/columnar/error.hxx +0 -51
- data/ext/couchbase/core/columnar/error_codes.cxx +0 -107
- data/ext/couchbase/core/columnar/error_codes.hxx +0 -75
- data/ext/couchbase/core/columnar/management_component.cxx +0 -300
- data/ext/couchbase/core/columnar/management_component.hxx +0 -56
- data/ext/couchbase/core/columnar/query_component.cxx +0 -523
- data/ext/couchbase/core/columnar/query_component.hxx +0 -57
- data/ext/couchbase/core/columnar/query_options.hxx +0 -59
- data/ext/couchbase/core/columnar/query_result.cxx +0 -130
- data/ext/couchbase/core/columnar/query_result.hxx +0 -78
- data/ext/couchbase/core/io/config_tracker.cxx +0 -687
- data/ext/couchbase/core/io/config_tracker.hxx +0 -123
|
@@ -201,11 +201,14 @@ attempt_context_impl::check_and_handle_blocking_transactions(
|
|
|
201
201
|
if (err) {
|
|
202
202
|
return cb(err);
|
|
203
203
|
}
|
|
204
|
-
return check_atr_entry_for_blocking_document(
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
204
|
+
return check_atr_entry_for_blocking_document(
|
|
205
|
+
doc,
|
|
206
|
+
std::make_shared<async_timed_exp_delay>(
|
|
207
|
+
std::make_shared<asio::steady_timer>(cluster_ref().io_context()),
|
|
208
|
+
std::chrono::milliseconds(50),
|
|
209
|
+
std::chrono::milliseconds(500),
|
|
210
|
+
std::chrono::seconds(1)),
|
|
211
|
+
std::move(cb));
|
|
209
212
|
}
|
|
210
213
|
CB_ATTEMPT_CTX_LOG_DEBUG(this,
|
|
211
214
|
"doc \"{}\" is in another transaction {}, but doesn't have enough "
|
|
@@ -919,7 +922,7 @@ attempt_context_impl::replace(const transaction_get_result& document,
|
|
|
919
922
|
CB_ATTEMPT_CTX_LOG_TRACE(
|
|
920
923
|
self, "replacing {} with {}", document, utils::to_string(content.data));
|
|
921
924
|
self->check_if_done(cb);
|
|
922
|
-
staged_mutation* existing_sm = self->staged_mutations_->find_any(document.id());
|
|
925
|
+
const staged_mutation* existing_sm = self->staged_mutations_->find_any(document.id());
|
|
923
926
|
if (existing_sm != nullptr && existing_sm->type() == staged_mutation_type::REMOVE) {
|
|
924
927
|
CB_ATTEMPT_CTX_LOG_DEBUG(
|
|
925
928
|
self, "found existing REMOVE of {} while replacing", document);
|
|
@@ -972,9 +975,7 @@ attempt_context_impl::replace(const transaction_get_result& document,
|
|
|
972
975
|
self->create_staged_insert(document.id(),
|
|
973
976
|
std::move(content),
|
|
974
977
|
document.cas().value(),
|
|
975
|
-
|
|
976
|
-
std::chrono::milliseconds(300),
|
|
977
|
-
self->overall()->config().timeout),
|
|
978
|
+
self->staged_insert_delay(),
|
|
978
979
|
op_id,
|
|
979
980
|
std::move(cb));
|
|
980
981
|
return;
|
|
@@ -1312,7 +1313,7 @@ attempt_context_impl::insert(const core::document_id& id,
|
|
|
1312
1313
|
try {
|
|
1313
1314
|
self->check_if_done(cb);
|
|
1314
1315
|
auto op_id = uid_generator::next();
|
|
1315
|
-
staged_mutation* existing_sm = self->staged_mutations_->find_any(id);
|
|
1316
|
+
const staged_mutation* existing_sm = self->staged_mutations_->find_any(id);
|
|
1316
1317
|
if ((existing_sm != nullptr) &&
|
|
1317
1318
|
(existing_sm->type() == staged_mutation_type::INSERT ||
|
|
1318
1319
|
existing_sm->type() == staged_mutation_type::REPLACE)) {
|
|
@@ -1345,14 +1346,8 @@ attempt_context_impl::insert(const core::document_id& id,
|
|
|
1345
1346
|
std::move(cb));
|
|
1346
1347
|
}
|
|
1347
1348
|
const std::uint64_t cas = 0;
|
|
1348
|
-
self->create_staged_insert(
|
|
1349
|
-
|
|
1350
|
-
cas,
|
|
1351
|
-
exp_delay(std::chrono::milliseconds(5),
|
|
1352
|
-
std::chrono::milliseconds(300),
|
|
1353
|
-
self->overall()->config().timeout),
|
|
1354
|
-
op_id,
|
|
1355
|
-
std::move(cb));
|
|
1349
|
+
self->create_staged_insert(
|
|
1350
|
+
id, std::move(content), cas, self->staged_insert_delay(), op_id, std::move(cb));
|
|
1356
1351
|
});
|
|
1357
1352
|
} catch (const std::exception& e) {
|
|
1358
1353
|
return self->op_completed_with_error(
|
|
@@ -1401,19 +1396,24 @@ attempt_context_impl::select_atr_if_needed_unlocked(
|
|
|
1401
1396
|
CB_ATTEMPT_CTX_LOG_ERROR(this, "unexpected error \"{}\" during select atr if needed", e.what());
|
|
1402
1397
|
}
|
|
1403
1398
|
}
|
|
1404
|
-
template<typename Handler
|
|
1399
|
+
template<typename Handler>
|
|
1405
1400
|
void
|
|
1406
|
-
attempt_context_impl::check_atr_entry_for_blocking_document(
|
|
1407
|
-
|
|
1408
|
-
|
|
1401
|
+
attempt_context_impl::check_atr_entry_for_blocking_document(
|
|
1402
|
+
const transaction_get_result& doc,
|
|
1403
|
+
std::shared_ptr<async_timed_exp_delay> delay,
|
|
1404
|
+
Handler&& cb)
|
|
1409
1405
|
{
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1406
|
+
(*delay)([self = shared_from_this(), doc, delay, cb = std::forward<Handler>(cb)](
|
|
1407
|
+
const std::exception_ptr& delay_err) mutable {
|
|
1408
|
+
if (delay_err) {
|
|
1409
|
+
return cb(transaction_operation_failed(FAIL_WRITE_WRITE_CONFLICT,
|
|
1410
|
+
"document is in another transaction")
|
|
1411
|
+
.retry());
|
|
1412
|
+
}
|
|
1413
|
+
return self->hooks_.before_check_atr_entry_for_blocking_doc(
|
|
1414
|
+
self,
|
|
1414
1415
|
doc.id().key(),
|
|
1415
|
-
[self
|
|
1416
|
-
auto ec) mutable {
|
|
1416
|
+
[self, delay = std::move(delay), cb = std::move(cb), doc](auto ec) mutable {
|
|
1417
1417
|
if (ec) {
|
|
1418
1418
|
return cb(transaction_operation_failed(FAIL_WRITE_WRITE_CONFLICT,
|
|
1419
1419
|
"document is in another transaction")
|
|
@@ -1453,7 +1453,8 @@ attempt_context_impl::check_atr_entry_for_blocking_document(const transaction_ge
|
|
|
1453
1453
|
"existing atr entry found in state {}, retrying",
|
|
1454
1454
|
attempt_state_name(it->state()));
|
|
1455
1455
|
}
|
|
1456
|
-
return self->check_atr_entry_for_blocking_document(
|
|
1456
|
+
return self->check_atr_entry_for_blocking_document(
|
|
1457
|
+
doc, std::move(delay), std::move(cb));
|
|
1457
1458
|
}
|
|
1458
1459
|
}
|
|
1459
1460
|
CB_ATTEMPT_CTX_LOG_DEBUG(self, "no blocking atr entry");
|
|
@@ -1465,11 +1466,7 @@ attempt_context_impl::check_atr_entry_for_blocking_document(const transaction_ge
|
|
|
1465
1466
|
.retry());
|
|
1466
1467
|
});
|
|
1467
1468
|
});
|
|
1468
|
-
}
|
|
1469
|
-
return cb(
|
|
1470
|
-
transaction_operation_failed(FAIL_WRITE_WRITE_CONFLICT, "document is in another transaction")
|
|
1471
|
-
.retry());
|
|
1472
|
-
}
|
|
1469
|
+
});
|
|
1473
1470
|
}
|
|
1474
1471
|
void
|
|
1475
1472
|
attempt_context_impl::remove(const transaction_get_result& document, VoidCallback&& cb)
|
|
@@ -1993,11 +1990,11 @@ dump_request(const core::operations::query_request& req) -> std::string
|
|
|
1993
1990
|
std::string raw = "{";
|
|
1994
1991
|
for (const auto& x : req.raw) {
|
|
1995
1992
|
raw += x.first;
|
|
1996
|
-
raw +=
|
|
1993
|
+
raw += ':';
|
|
1997
1994
|
raw += x.second.str();
|
|
1998
|
-
raw +=
|
|
1995
|
+
raw += ',';
|
|
1999
1996
|
}
|
|
2000
|
-
raw +=
|
|
1997
|
+
raw += '}';
|
|
2001
1998
|
std::string params;
|
|
2002
1999
|
for (const auto& x : req.positional_parameters) {
|
|
2003
2000
|
params.append(x.str());
|
|
@@ -2049,6 +2046,7 @@ attempt_context_impl::wrap_query(
|
|
|
2049
2046
|
|
|
2050
2047
|
if (check_expiry) {
|
|
2051
2048
|
if (has_expired_client_side(hook_point, std::nullopt)) {
|
|
2049
|
+
query_check_expired_ = true;
|
|
2052
2050
|
auto err = std::make_exception_ptr(
|
|
2053
2051
|
transaction_operation_failed(FAIL_EXPIRY,
|
|
2054
2052
|
fmt::format("{} expired in stage {}", statement, hook_point))
|
|
@@ -3241,10 +3239,10 @@ attempt_context_impl::set_atr_pending_locked(
|
|
|
3241
3239
|
// This bounds the value to [0-timeout]. It should always be in this
|
|
3242
3240
|
// range, this is just to protect against the application clock
|
|
3243
3241
|
// changing.
|
|
3244
|
-
const
|
|
3242
|
+
const auto remaining_bounded_nanos =
|
|
3245
3243
|
std::max(std::min(remaining.count(), self->overall()->config().timeout.count()),
|
|
3246
3244
|
static_cast<std::chrono::nanoseconds::rep>(0));
|
|
3247
|
-
const
|
|
3245
|
+
const auto remaining_bounded_msecs = remaining_bounded_nanos / 1'000'000;
|
|
3248
3246
|
|
|
3249
3247
|
core::operations::mutate_in_request req{ self->atr_id_.value() };
|
|
3250
3248
|
|
|
@@ -3403,6 +3401,7 @@ attempt_context_impl::do_get(const core::document_id& id,
|
|
|
3403
3401
|
return self->get_doc(
|
|
3404
3402
|
id,
|
|
3405
3403
|
allow_replica,
|
|
3404
|
+
std::nullopt,
|
|
3406
3405
|
[self,
|
|
3407
3406
|
id,
|
|
3408
3407
|
allow_replica,
|
|
@@ -3578,6 +3577,7 @@ execute_lookup(attempt_context_impl* ctx, LookupInRequest& req, Callback&& cb)
|
|
|
3578
3577
|
void
|
|
3579
3578
|
attempt_context_impl::get_doc(const core::document_id& id,
|
|
3580
3579
|
bool allow_replica,
|
|
3580
|
+
std::optional<std::chrono::milliseconds> timeout,
|
|
3581
3581
|
std::function<void(std::optional<error_class>,
|
|
3582
3582
|
std::optional<external_exception>,
|
|
3583
3583
|
std::optional<std::string>,
|
|
@@ -3601,27 +3601,21 @@ attempt_context_impl::get_doc(const core::document_id& id,
|
|
|
3601
3601
|
|
|
3602
3602
|
try {
|
|
3603
3603
|
if (allow_replica) {
|
|
3604
|
-
|
|
3605
|
-
|
|
3606
|
-
|
|
3607
|
-
|
|
3608
|
-
|
|
3609
|
-
|
|
3610
|
-
|
|
3611
|
-
|
|
3612
|
-
|
|
3613
|
-
|
|
3614
|
-
}
|
|
3615
|
-
core::operations::lookup_in_any_replica_request req{ id };
|
|
3616
|
-
req.read_preference = couchbase::read_preference::selected_server_group_or_all_available;
|
|
3617
|
-
req.specs = specs;
|
|
3618
|
-
req.access_deleted = config->capabilities.supports_subdoc_access_deleted();
|
|
3619
|
-
execute_lookup(this, req, cb);
|
|
3620
|
-
});
|
|
3604
|
+
// Per the transactions spec ("Fetching an individual document") and MB-63241, a replica read
|
|
3605
|
+
// must not be combined with the accessDeleted flag; the reference SDKs omit it on the replica
|
|
3606
|
+
// path. We therefore always read replicas without accessDeleted (so tombstones are not
|
|
3607
|
+
// visible there) and need no bucket-config capability probe.
|
|
3608
|
+
core::operations::lookup_in_any_replica_request req{ id };
|
|
3609
|
+
req.read_preference = couchbase::read_preference::selected_server_group_or_all_available;
|
|
3610
|
+
req.specs = specs;
|
|
3611
|
+
req.access_deleted = false;
|
|
3612
|
+
req.timeout = timeout;
|
|
3613
|
+
execute_lookup(this, req, cb);
|
|
3621
3614
|
} else {
|
|
3622
3615
|
core::operations::lookup_in_request req{ id };
|
|
3623
3616
|
req.access_deleted = true;
|
|
3624
3617
|
req.specs = specs;
|
|
3618
|
+
req.timeout = timeout;
|
|
3625
3619
|
execute_lookup(this, req, cb);
|
|
3626
3620
|
}
|
|
3627
3621
|
} catch (const std::exception& e) {
|
|
@@ -3658,8 +3652,8 @@ attempt_context_impl::create_staged_insert_error_handler(const core::document_id
|
|
|
3658
3652
|
transaction_operation_failed(ec, "transient error in insert").retry());
|
|
3659
3653
|
case FAIL_AMBIGUOUS:
|
|
3660
3654
|
CB_ATTEMPT_CTX_LOG_DEBUG(this, "FAIL_AMBIGUOUS in create_staged_insert, retrying");
|
|
3661
|
-
|
|
3662
|
-
|
|
3655
|
+
return retry_create_staged_insert(
|
|
3656
|
+
id, content, cas, std::forward<Delay>(delay), op_id, std::forward<Handler>(cb));
|
|
3663
3657
|
case FAIL_OTHER:
|
|
3664
3658
|
return op_completed_with_error(
|
|
3665
3659
|
std::forward<Handler>(cb),
|
|
@@ -3720,6 +3714,7 @@ attempt_context_impl::create_staged_insert_error_handler(const core::document_id
|
|
|
3720
3714
|
return self->get_doc(
|
|
3721
3715
|
id,
|
|
3722
3716
|
false,
|
|
3717
|
+
std::nullopt,
|
|
3723
3718
|
[self, id, content, op_id, cb = std::forward<Handler>(cb), error_handler, delay](
|
|
3724
3719
|
std::optional<error_class> ec3,
|
|
3725
3720
|
std::optional<external_exception> /* cause */,
|
|
@@ -3747,8 +3742,7 @@ attempt_context_impl::create_staged_insert_error_handler(const core::document_id
|
|
|
3747
3742
|
"create staged insert found existing deleted doc, "
|
|
3748
3743
|
"retrying with cas {}",
|
|
3749
3744
|
doc->cas().value());
|
|
3750
|
-
|
|
3751
|
-
return self->create_staged_insert(
|
|
3745
|
+
return self->retry_create_staged_insert(
|
|
3752
3746
|
id, content, doc->cas().value(), delay, op_id, std::forward<Handler>(cb));
|
|
3753
3747
|
}
|
|
3754
3748
|
if (!doc->links().is_document_in_transaction()) {
|
|
@@ -3800,9 +3794,8 @@ attempt_context_impl::create_staged_insert_error_handler(const core::document_id
|
|
|
3800
3794
|
"doc ok to overwrite, retrying create_staged_insert "
|
|
3801
3795
|
"with cas {}",
|
|
3802
3796
|
doc->cas().value());
|
|
3803
|
-
|
|
3804
|
-
|
|
3805
|
-
id, content, doc->cas().value(), delay, op_id, std::forward<Handler>(cb));
|
|
3797
|
+
return self->retry_create_staged_insert(
|
|
3798
|
+
id, content, doc->cas().value(), delay, op_id, std::move(cb));
|
|
3806
3799
|
});
|
|
3807
3800
|
} else {
|
|
3808
3801
|
// no doc now, just retry entire txn
|
|
@@ -3828,6 +3821,58 @@ attempt_context_impl::create_staged_insert_error_handler(const core::document_id
|
|
|
3828
3821
|
}
|
|
3829
3822
|
}
|
|
3830
3823
|
|
|
3824
|
+
auto
|
|
3825
|
+
attempt_context_impl::staged_insert_delay() const -> std::shared_ptr<async_timed_exp_delay>
|
|
3826
|
+
{
|
|
3827
|
+
auto delay = std::make_shared<async_timed_exp_delay>(
|
|
3828
|
+
std::make_shared<asio::steady_timer>(cluster_ref().io_context()),
|
|
3829
|
+
std::chrono::milliseconds(5),
|
|
3830
|
+
std::chrono::milliseconds(300),
|
|
3831
|
+
overall()->config().timeout);
|
|
3832
|
+
// The transaction expiry bounds the retries; a retry limit would fail a long transaction early.
|
|
3833
|
+
delay->max_retries = std::numeric_limits<std::size_t>::max();
|
|
3834
|
+
return delay;
|
|
3835
|
+
}
|
|
3836
|
+
|
|
3837
|
+
template<typename Handler, typename Delay>
|
|
3838
|
+
void
|
|
3839
|
+
attempt_context_impl::retry_create_staged_insert(const core::document_id& id,
|
|
3840
|
+
const codec::encoded_value& content,
|
|
3841
|
+
std::uint64_t cas,
|
|
3842
|
+
Delay&& delay,
|
|
3843
|
+
const std::string& op_id,
|
|
3844
|
+
Handler&& cb)
|
|
3845
|
+
{
|
|
3846
|
+
auto shared_delay = delay;
|
|
3847
|
+
(*shared_delay)([self = shared_from_this(),
|
|
3848
|
+
id,
|
|
3849
|
+
content = content,
|
|
3850
|
+
cas,
|
|
3851
|
+
delay = std::forward<Delay>(delay),
|
|
3852
|
+
op_id,
|
|
3853
|
+
cb = std::forward<Handler>(cb)](const std::exception_ptr& delay_err) mutable {
|
|
3854
|
+
if (delay_err) {
|
|
3855
|
+
try {
|
|
3856
|
+
std::rethrow_exception(delay_err);
|
|
3857
|
+
} catch (const retry_operation_timeout&) {
|
|
3858
|
+
return self->create_staged_insert_error_handler(id,
|
|
3859
|
+
content,
|
|
3860
|
+
cas,
|
|
3861
|
+
delay,
|
|
3862
|
+
op_id,
|
|
3863
|
+
std::move(cb),
|
|
3864
|
+
FAIL_EXPIRY,
|
|
3865
|
+
UNKNOWN,
|
|
3866
|
+
"create_staged_insert retries timed out");
|
|
3867
|
+
} catch (const std::exception& e) {
|
|
3868
|
+
return self->op_completed_with_error(std::move(cb),
|
|
3869
|
+
transaction_operation_failed(FAIL_OTHER, e.what()));
|
|
3870
|
+
}
|
|
3871
|
+
}
|
|
3872
|
+
return self->create_staged_insert(id, std::move(content), cas, delay, op_id, std::move(cb));
|
|
3873
|
+
});
|
|
3874
|
+
}
|
|
3875
|
+
|
|
3831
3876
|
template<typename Handler, typename Delay>
|
|
3832
3877
|
void
|
|
3833
3878
|
attempt_context_impl::create_staged_insert(const core::document_id& id,
|
|
@@ -74,6 +74,7 @@ class transactions;
|
|
|
74
74
|
enum class forward_compat_stage : std::uint8_t;
|
|
75
75
|
class staged_mutation_queue;
|
|
76
76
|
class staged_mutation;
|
|
77
|
+
struct async_timed_exp_delay;
|
|
77
78
|
struct attempt_context_testing_hooks;
|
|
78
79
|
|
|
79
80
|
class attempt_context_impl
|
|
@@ -100,6 +101,8 @@ private:
|
|
|
100
101
|
friend class atr_cleanup_entry;
|
|
101
102
|
// transaction_context needs access to the two functions below
|
|
102
103
|
friend class transaction_context;
|
|
104
|
+
// get_multi fetches raw documents (body + metadata, no MAV/ATR resolution) via get_doc
|
|
105
|
+
friend class get_multi_operation;
|
|
103
106
|
|
|
104
107
|
void insert(const core::document_id& id,
|
|
105
108
|
codec::encoded_value content,
|
|
@@ -461,6 +464,9 @@ public:
|
|
|
461
464
|
|
|
462
465
|
private:
|
|
463
466
|
std::atomic<bool> expiry_overtime_mode_{ false };
|
|
467
|
+
// Set when the client-side expiry check of a query statement fires. Any later failed
|
|
468
|
+
// auto-rollback in this attempt raises EXPIRED instead of FAILED.
|
|
469
|
+
std::atomic<bool> query_check_expired_{ false };
|
|
464
470
|
|
|
465
471
|
auto check_expiry_pre_commit(std::string stage, std::optional<const std::string> doc_id) -> bool;
|
|
466
472
|
|
|
@@ -483,9 +489,9 @@ private:
|
|
|
483
489
|
forward_compat_stage stage,
|
|
484
490
|
std::function<void(std::optional<transaction_operation_failed>)>&& cb);
|
|
485
491
|
|
|
486
|
-
template<typename Handler
|
|
492
|
+
template<typename Handler>
|
|
487
493
|
void check_atr_entry_for_blocking_document(const transaction_get_result& doc,
|
|
488
|
-
|
|
494
|
+
std::shared_ptr<async_timed_exp_delay> delay,
|
|
489
495
|
Handler&& cb);
|
|
490
496
|
|
|
491
497
|
template<typename Handler>
|
|
@@ -513,6 +519,7 @@ private:
|
|
|
513
519
|
|
|
514
520
|
void get_doc(const core::document_id& id,
|
|
515
521
|
bool allow_replica,
|
|
522
|
+
std::optional<std::chrono::milliseconds> timeout,
|
|
516
523
|
std::function<void(std::optional<error_class>,
|
|
517
524
|
std::optional<external_exception>,
|
|
518
525
|
std::optional<std::string>,
|
|
@@ -540,6 +547,16 @@ private:
|
|
|
540
547
|
const std::optional<document_metadata>& document_metadata,
|
|
541
548
|
Handler&& cb);
|
|
542
549
|
|
|
550
|
+
[[nodiscard]] auto staged_insert_delay() const -> std::shared_ptr<async_timed_exp_delay>;
|
|
551
|
+
|
|
552
|
+
template<typename Handler, typename Delay>
|
|
553
|
+
void retry_create_staged_insert(const core::document_id& id,
|
|
554
|
+
const codec::encoded_value& content,
|
|
555
|
+
std::uint64_t cas,
|
|
556
|
+
Delay&& delay,
|
|
557
|
+
const std::string& op_id,
|
|
558
|
+
Handler&& cb);
|
|
559
|
+
|
|
543
560
|
template<typename Handler, typename Delay>
|
|
544
561
|
void create_staged_insert_error_handler(const core::document_id& id,
|
|
545
562
|
const codec::encoded_value& content,
|
|
@@ -39,7 +39,7 @@ public:
|
|
|
39
39
|
}
|
|
40
40
|
void push_back(const transaction_operation_failed& ex)
|
|
41
41
|
{
|
|
42
|
-
std::
|
|
42
|
+
std::scoped_lock<std::mutex> lock(mutex_);
|
|
43
43
|
list_.push_back(ex);
|
|
44
44
|
size_ = list_.size();
|
|
45
45
|
}
|
|
@@ -47,7 +47,7 @@ public:
|
|
|
47
47
|
{
|
|
48
48
|
assert(size_.load() > 0);
|
|
49
49
|
// merge the errors, throw a composite
|
|
50
|
-
std::
|
|
50
|
+
std::scoped_lock<std::mutex> lock(mutex_);
|
|
51
51
|
transaction_operation_failed::merge_errors(list_, cause);
|
|
52
52
|
}
|
|
53
53
|
};
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2021-Present Couchbase, Inc.
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
#pragma once
|
|
18
|
+
|
|
19
|
+
#include "core/document_id.hxx"
|
|
20
|
+
#include "error_class.hxx"
|
|
21
|
+
#include "exceptions.hxx"
|
|
22
|
+
#include "get_multi_transaction_id.hxx"
|
|
23
|
+
#include "internal/doc_record.hxx"
|
|
24
|
+
|
|
25
|
+
#include <algorithm>
|
|
26
|
+
#include <chrono>
|
|
27
|
+
#include <cstdint>
|
|
28
|
+
#include <optional>
|
|
29
|
+
#include <string>
|
|
30
|
+
#include <vector>
|
|
31
|
+
|
|
32
|
+
// Pure decision helpers for the get_multi orchestrator, factored out of get_multi_orchestrator.cxx
|
|
33
|
+
// so the branching that the ExtGetMulti spec specifies can be unit-tested without a cluster. Each
|
|
34
|
+
// function operates on plain data and is free of I/O or orchestrator state.
|
|
35
|
+
namespace couchbase::core::transactions
|
|
36
|
+
{
|
|
37
|
+
enum class get_multi_fetch_outcome : std::uint8_t {
|
|
38
|
+
document_absent,
|
|
39
|
+
retry_after_backoff,
|
|
40
|
+
bound_exceeded,
|
|
41
|
+
fail_expired,
|
|
42
|
+
fail_without_rollback,
|
|
43
|
+
fail_with_rollback,
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
enum class bound_exceeded_action : std::uint8_t {
|
|
47
|
+
preserve_prior_value,
|
|
48
|
+
fail_retryable,
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Decides what a bound-exceeded fetch does with its slot. A document already fetched in an earlier
|
|
53
|
+
* round is kept for the best-effort snapshot the spec's BoundExceeded return allows. But when no
|
|
54
|
+
* value is held for the document -- e.g. reset_and_retry() cleared every slot and the re-fetch hit
|
|
55
|
+
* a transient with the (fixed, already-elapsed) bound -- leaving the slot blank would misreport the
|
|
56
|
+
* document as not-found: a transient is never a document-not-found. The spec's "Global signal
|
|
57
|
+
* handling" instead raises a retryable error when a document is unresolved at the bound, so the
|
|
58
|
+
* enclosing transaction retries rather than returning a wrong absent result.
|
|
59
|
+
*/
|
|
60
|
+
[[nodiscard]] inline auto
|
|
61
|
+
get_multi_bound_exceeded_action(bool has_prior_value) -> bound_exceeded_action
|
|
62
|
+
{
|
|
63
|
+
return has_prior_value ? bound_exceeded_action::preserve_prior_value
|
|
64
|
+
: bound_exceeded_action::fail_retryable;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Maps a failed individual get_multi fetch to the action required by the ExtGetMulti spec's
|
|
69
|
+
* "Fetching an individual document / Error handling" section, adapted to this SDK's error model.
|
|
70
|
+
*
|
|
71
|
+
* The spec branches on a distinct TimeoutException, which this SDK does not have: a read timeout
|
|
72
|
+
* classifies as FAIL_TRANSIENT (unambiguous_timeout) or FAIL_AMBIGUOUS (ambiguous_timeout), the
|
|
73
|
+
* same classes as a genuine transient failure. Rather than guess which occurred, a transient class
|
|
74
|
+
* is disambiguated by whether the operation's read-skew bound has elapsed: before the bound it is a
|
|
75
|
+
* transient error to retry (spec FAIL_TRANSIENT: exponential backoff from 1ms), once the bound has
|
|
76
|
+
* elapsed the SDK stops resolving and returns the best-effort snapshot (spec BoundExceeded).
|
|
77
|
+
* A FAIL_EXPIRY is surfaced as fail_expired so the caller can mark the operation expired (raising
|
|
78
|
+
* TRANSACTION_EXPIRED) rather than a generic failure.
|
|
79
|
+
*/
|
|
80
|
+
[[nodiscard]] inline auto
|
|
81
|
+
classify_get_multi_fetch_error(std::optional<error_class> ec,
|
|
82
|
+
std::optional<external_exception> cause,
|
|
83
|
+
bool read_skew_bound_exceeded) -> get_multi_fetch_outcome
|
|
84
|
+
{
|
|
85
|
+
if (!ec.has_value()) {
|
|
86
|
+
return get_multi_fetch_outcome::document_absent;
|
|
87
|
+
}
|
|
88
|
+
if (cause == DOCUMENT_UNRETRIEVABLE_EXCEPTION || cause == DOCUMENT_NOT_FOUND_EXCEPTION ||
|
|
89
|
+
ec == FAIL_DOC_NOT_FOUND) {
|
|
90
|
+
return get_multi_fetch_outcome::document_absent;
|
|
91
|
+
}
|
|
92
|
+
if (ec == FAIL_TRANSIENT || ec == FAIL_AMBIGUOUS) {
|
|
93
|
+
return read_skew_bound_exceeded ? get_multi_fetch_outcome::bound_exceeded
|
|
94
|
+
: get_multi_fetch_outcome::retry_after_backoff;
|
|
95
|
+
}
|
|
96
|
+
if (ec == FAIL_EXPIRY) {
|
|
97
|
+
return get_multi_fetch_outcome::fail_expired;
|
|
98
|
+
}
|
|
99
|
+
if (ec == FAIL_HARD) {
|
|
100
|
+
return get_multi_fetch_outcome::fail_without_rollback;
|
|
101
|
+
}
|
|
102
|
+
return get_multi_fetch_outcome::fail_with_rollback;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Per-document read timeout: the smaller of the time left before the operation's read-skew bound
|
|
107
|
+
* and the SDK's key-value read timeout (spec "Fetching an individual document": use an operation
|
|
108
|
+
* timeout of min(remaining deadline, 2.5s)). Floored at 1ms so an already-elapsed bound still
|
|
109
|
+
* issues a bounded read that fails fast rather than passing a zero or negative timeout.
|
|
110
|
+
*/
|
|
111
|
+
[[nodiscard]] inline auto
|
|
112
|
+
get_multi_fetch_timeout(std::chrono::steady_clock::duration remaining,
|
|
113
|
+
std::chrono::milliseconds key_value_timeout) -> std::chrono::milliseconds
|
|
114
|
+
{
|
|
115
|
+
const auto remaining_ms = std::chrono::duration_cast<std::chrono::milliseconds>(remaining);
|
|
116
|
+
if (remaining_ms < std::chrono::milliseconds{ 1 }) {
|
|
117
|
+
return std::chrono::milliseconds{ 1 };
|
|
118
|
+
}
|
|
119
|
+
return std::min(remaining_ms, key_value_timeout);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* True when a fetched document is a read-skew victim (spec "Read skew resolution", T1 COMMITTED): a
|
|
124
|
+
* document we fetched that is NOT part of T1 -- it carries no transactional metadata, or belongs to
|
|
125
|
+
* a different attempt -- yet which T1's ATR entry records as mutated (inserted/replaced/removed).
|
|
126
|
+
* Such a document was read before T1 committed and must be re-fetched for a consistent snapshot.
|
|
127
|
+
*/
|
|
128
|
+
[[nodiscard]] inline auto
|
|
129
|
+
contains_mutation(const std::optional<std::vector<doc_record>>& mutated_ids,
|
|
130
|
+
const core::document_id& id) -> bool
|
|
131
|
+
{
|
|
132
|
+
if (!mutated_ids) {
|
|
133
|
+
return false;
|
|
134
|
+
}
|
|
135
|
+
return std::any_of(mutated_ids->begin(), mutated_ids->end(), [&id](const auto& mutation) {
|
|
136
|
+
return mutation == id;
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
[[nodiscard]] inline auto
|
|
141
|
+
is_read_skew_victim(bool doc_exists,
|
|
142
|
+
const std::optional<transaction_id>& doc_transaction_id,
|
|
143
|
+
const std::string& t1_attempt_id,
|
|
144
|
+
const core::document_id& id,
|
|
145
|
+
const std::optional<std::vector<doc_record>>& t1_inserted_ids,
|
|
146
|
+
const std::optional<std::vector<doc_record>>& t1_replaced_ids,
|
|
147
|
+
const std::optional<std::vector<doc_record>>& t1_removed_ids) -> bool
|
|
148
|
+
{
|
|
149
|
+
if (!doc_exists) {
|
|
150
|
+
return false;
|
|
151
|
+
}
|
|
152
|
+
const bool fetched_as_part_of_t1 =
|
|
153
|
+
doc_transaction_id.has_value() && doc_transaction_id->attempt == t1_attempt_id;
|
|
154
|
+
if (fetched_as_part_of_t1) {
|
|
155
|
+
return false;
|
|
156
|
+
}
|
|
157
|
+
return contains_mutation(t1_inserted_ids, id) || contains_mutation(t1_replaced_ids, id) ||
|
|
158
|
+
contains_mutation(t1_removed_ids, id);
|
|
159
|
+
}
|
|
160
|
+
} // namespace couchbase::core::transactions
|