couchbase 3.8.1 → 3.9.0
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 +2 -2
- 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 +214 -155
- data/ext/cache/mozilla-ca-bundle.sha256 +1 -1
- data/ext/couchbase/CMakeLists.txt +130 -21
- 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 +10 -3
- 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 +1554 -398
- 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 +325 -25
- 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 +66 -0
- 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 +316 -317
- 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 +275 -14
- data/ext/couchbase/core/io/streams.hxx +53 -0
- 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/bucket_create.cxx +37 -38
- data/ext/couchbase/core/operations/management/bucket_update.cxx +26 -28
- 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 +59 -5
- 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 +362 -241
- data/ext/couchbase/core/transactions/attempt_context_impl.hxx +24 -3
- 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 +194 -66
- 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 +15 -4
- 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 +3 -29
- 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 +216 -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 +32 -0
- 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 +33 -14
- 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 +181 -44
- 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 +92 -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
|
@@ -166,34 +166,6 @@ wrap_run(transactions& txns,
|
|
|
166
166
|
return overall->get_transaction_result();
|
|
167
167
|
}
|
|
168
168
|
|
|
169
|
-
template<typename Handler>
|
|
170
|
-
auto
|
|
171
|
-
wrap_public_api_run(transactions& txns,
|
|
172
|
-
const couchbase::transactions::transaction_options& config,
|
|
173
|
-
std::size_t max_attempts,
|
|
174
|
-
Handler&& fn) -> ::couchbase::transactions::transaction_result
|
|
175
|
-
{
|
|
176
|
-
return wrap_run(txns, config, max_attempts, [fn = std::forward<Handler>(fn)](const auto& ctx) {
|
|
177
|
-
const couchbase::error err = fn(ctx);
|
|
178
|
-
if (err && err.ec() != errc::transaction_op::transaction_op_failed) {
|
|
179
|
-
// We intentionally don't handle transaction_op_failed here, as we must have cached the
|
|
180
|
-
// transaction error internally already, which has the full context with the right error class
|
|
181
|
-
// etc.
|
|
182
|
-
if (err.ec().category() == core::impl::transaction_op_category()) {
|
|
183
|
-
throw op_exception(err);
|
|
184
|
-
}
|
|
185
|
-
throw std::system_error(err.ec(), fmt::format("{}", err));
|
|
186
|
-
}
|
|
187
|
-
});
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
auto
|
|
191
|
-
transactions::run(logic&& code) -> ::couchbase::transactions::transaction_result
|
|
192
|
-
{
|
|
193
|
-
const couchbase::transactions::transaction_options config;
|
|
194
|
-
return wrap_run(*this, config, max_attempts_, std::move(code));
|
|
195
|
-
}
|
|
196
|
-
|
|
197
169
|
auto
|
|
198
170
|
transactions::run(const couchbase::transactions::transaction_options& config, logic&& code)
|
|
199
171
|
-> ::couchbase::transactions::transaction_result
|
|
@@ -202,17 +174,9 @@ transactions::run(const couchbase::transactions::transaction_options& config, lo
|
|
|
202
174
|
}
|
|
203
175
|
|
|
204
176
|
auto
|
|
205
|
-
transactions::run(couchbase::transactions::
|
|
206
|
-
const couchbase::transactions::transaction_options& config)
|
|
207
|
-
-> std::pair<couchbase::error, couchbase::transactions::transaction_result>
|
|
177
|
+
transactions::run(logic&& code) -> ::couchbase::transactions::transaction_result
|
|
208
178
|
{
|
|
209
|
-
|
|
210
|
-
return { {}, wrap_public_api_run(*this, config, max_attempts_, std::move(code)) };
|
|
211
|
-
} catch (const transaction_exception& e) {
|
|
212
|
-
// get error from e and return it in the transaction_result
|
|
213
|
-
auto [err_ctx, result] = e.get_transaction_result();
|
|
214
|
-
return std::make_pair(core::impl::make_error(err_ctx), result);
|
|
215
|
-
}
|
|
179
|
+
return run({}, std::move(code));
|
|
216
180
|
}
|
|
217
181
|
|
|
218
182
|
void
|
|
@@ -229,27 +193,11 @@ transactions::run(const couchbase::transactions::transaction_options& config,
|
|
|
229
193
|
}
|
|
230
194
|
}).detach();
|
|
231
195
|
}
|
|
232
|
-
void
|
|
233
|
-
transactions::run(couchbase::transactions::async_txn_logic&& code,
|
|
234
|
-
couchbase::transactions::async_txn_complete_logic&& cb,
|
|
235
|
-
const couchbase::transactions::transaction_options& config)
|
|
236
|
-
{
|
|
237
|
-
std::thread([this, config, code = std::move(code), cb = std::move(cb)]() {
|
|
238
|
-
try {
|
|
239
|
-
auto result = wrap_public_api_run(*this, config, max_attempts_, code);
|
|
240
|
-
return cb({}, result);
|
|
241
|
-
} catch (const transaction_exception& e) {
|
|
242
|
-
auto [ctx, res] = e.get_transaction_result();
|
|
243
|
-
return cb(core::impl::make_error(ctx), res);
|
|
244
|
-
}
|
|
245
|
-
}).detach();
|
|
246
|
-
}
|
|
247
196
|
|
|
248
197
|
void
|
|
249
198
|
transactions::run(async_logic&& code, txn_complete_callback&& cb)
|
|
250
199
|
{
|
|
251
|
-
|
|
252
|
-
return run(config, std::move(code), std::move(cb));
|
|
200
|
+
return run({}, std::move(code), std::move(cb));
|
|
253
201
|
}
|
|
254
202
|
|
|
255
203
|
void
|
|
@@ -27,12 +27,18 @@
|
|
|
27
27
|
#include "internal/utils.hxx"
|
|
28
28
|
|
|
29
29
|
#include "core/operations.hxx"
|
|
30
|
-
#include "core/utils/
|
|
30
|
+
#include "core/utils/process_id.hxx"
|
|
31
31
|
|
|
32
32
|
#include <couchbase/fmt/transaction_keyspace.hxx>
|
|
33
33
|
|
|
34
|
+
#include <asio/post.hpp>
|
|
35
|
+
|
|
36
|
+
#include <deque>
|
|
34
37
|
#include <functional>
|
|
38
|
+
#include <future>
|
|
39
|
+
#include <list>
|
|
35
40
|
#include <memory>
|
|
41
|
+
#include <thread>
|
|
36
42
|
#include <utility>
|
|
37
43
|
|
|
38
44
|
namespace couchbase::core::transactions
|
|
@@ -52,34 +58,13 @@ transactions_cleanup::transactions_cleanup(
|
|
|
52
58
|
: cluster_(std::move(cluster))
|
|
53
59
|
, config_(std::move(config))
|
|
54
60
|
, client_uuid_(uid_generator::next())
|
|
61
|
+
, client_record_owner_pid_(utils::current_process_id())
|
|
55
62
|
{
|
|
56
63
|
start();
|
|
57
64
|
}
|
|
58
65
|
|
|
59
66
|
namespace
|
|
60
67
|
{
|
|
61
|
-
/**
|
|
62
|
-
* ${Mutation.CAS} is written by kvengine with
|
|
63
|
-
* 'macroToString(htonll(info.cas))'. Discussed this with KV team and, though
|
|
64
|
-
* there is consensus that this is off (htonll is definitely wrong, and a string
|
|
65
|
-
* is an odd choice), there are clients (SyncGateway) that consume the current
|
|
66
|
-
* string, so it can't be changed. Note that only little-endian servers are
|
|
67
|
-
* supported for Couchbase, so the 8 byte long inside the string will always be
|
|
68
|
-
* little-endian ordered.
|
|
69
|
-
*
|
|
70
|
-
* Looks like: "0x000058a71dd25c15"
|
|
71
|
-
* Want: 0x155CD21DA7580000 (1539336197457313792 in base10, an epoch
|
|
72
|
-
* time in millionths of a second)
|
|
73
|
-
*/
|
|
74
|
-
auto
|
|
75
|
-
parse_mutation_cas(const std::string& cas) -> std::uint64_t
|
|
76
|
-
{
|
|
77
|
-
if (cas.empty()) {
|
|
78
|
-
return 0;
|
|
79
|
-
}
|
|
80
|
-
return core::utils::byte_swap(std::stoull(cas, nullptr, 16)) / 1000000;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
68
|
// TODO(CXXCBC-549)
|
|
84
69
|
const std::string CLIENT_RECORD_DOC_ID = "_txn:client-record"; // NOLINT(cert-err58-cpp)
|
|
85
70
|
} // namespace
|
|
@@ -108,7 +93,7 @@ transactions_cleanup::clean_collection(
|
|
|
108
93
|
// first make sure the collection is in the list
|
|
109
94
|
while (is_running()) {
|
|
110
95
|
{
|
|
111
|
-
const std::
|
|
96
|
+
const std::scoped_lock<std::mutex> lock(mutex_);
|
|
112
97
|
if (collections_.end() == std::find(collections_.begin(), collections_.end(), keyspace)) {
|
|
113
98
|
CB_LOST_ATTEMPT_CLEANUP_LOG_DEBUG(
|
|
114
99
|
"cleanup for {} ending, no longer in collection cleanup list", keyspace);
|
|
@@ -131,54 +116,125 @@ transactions_cleanup::clean_collection(
|
|
|
131
116
|
all_atrs.size(),
|
|
132
117
|
config_.cleanup_config.cleanup_window.count());
|
|
133
118
|
|
|
119
|
+
// Each ATR is checked with a blocking get_atr. If those were run strictly one-at-a-time the
|
|
120
|
+
// scan rate would be capped by the per-ATR KV latency rather than the cleanup window: on a
|
|
121
|
+
// slow or loaded KV node a single window could fail to scan all ATRs, leaving lost
|
|
122
|
+
// transactions (and the documents they block) uncleaned for far longer than configured. So
|
|
123
|
+
// run the checks with a bounded number in flight: launches are still paced across the window
|
|
124
|
+
// (to avoid flooding the cluster), but a slow lookup no longer holds up the ones behind it.
|
|
125
|
+
std::deque<std::future<void>> in_flight;
|
|
126
|
+
// The pool is created in start() whenever lost-attempts cleanup is enabled, which is the only
|
|
127
|
+
// configuration that spawns collection workers, so it is always present here. Bind a checked
|
|
128
|
+
// reference now rather than dereferencing the optional at each launch.
|
|
129
|
+
if (!atr_cleanup_pool_.has_value()) {
|
|
130
|
+
// Should be unreachable (see above). If the invariant is ever broken, surface it: a silent
|
|
131
|
+
// return here disables lost-attempts cleanup for this collection with no other signal.
|
|
132
|
+
CB_LOST_ATTEMPT_CLEANUP_LOG_ERROR(
|
|
133
|
+
"atr cleanup pool is not initialized; skipping lost-attempts cleanup for {}", keyspace);
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
auto& atr_cleanup_pool = *atr_cleanup_pool_;
|
|
137
|
+
const auto reclaim_one = [&in_flight]() {
|
|
138
|
+
const auto reclaim = [](std::future<void>& f) {
|
|
139
|
+
// get() only rethrows if the task itself threw, which it is written not to, but guard
|
|
140
|
+
// anyway so one bad ATR cannot abort the whole scan.
|
|
141
|
+
try {
|
|
142
|
+
f.get();
|
|
143
|
+
// NOLINTNEXTLINE(bugprone-empty-catch) -- task already logged any error
|
|
144
|
+
} catch (...) {
|
|
145
|
+
// already handled in the task
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
// Reclaim any already-finished check first, so a slow lookup at the front does not hold up
|
|
149
|
+
// the ready ones queued behind it.
|
|
150
|
+
for (auto it = in_flight.begin(); it != in_flight.end(); ++it) {
|
|
151
|
+
if (it->wait_for(std::chrono::seconds(0)) == std::future_status::ready) {
|
|
152
|
+
reclaim(*it);
|
|
153
|
+
in_flight.erase(it);
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
// None ready yet: block on the oldest, since a slot must be freed before launching more.
|
|
158
|
+
reclaim(in_flight.front());
|
|
159
|
+
in_flight.pop_front();
|
|
160
|
+
};
|
|
161
|
+
|
|
134
162
|
for (auto it = all_atrs.begin() + details.index_of_this_client; it < all_atrs.end();
|
|
135
163
|
it += details.num_active_clients) {
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
164
|
+
if (!is_running()) {
|
|
165
|
+
break;
|
|
166
|
+
}
|
|
167
|
+
// This client visits every num_active_clients-th ATR from `it`, so the number it still has
|
|
168
|
+
// to launch is ceil(remaining / stride). Floor division would undercount at the tail,
|
|
169
|
+
// inflating budget_for_this_atr below and over-pacing the scan past the cleanup window.
|
|
170
|
+
const auto stride = std::max<decltype(it)::difference_type>(1, details.num_active_clients);
|
|
171
|
+
const auto atrs_left_for_this_client =
|
|
172
|
+
(std::distance(it, all_atrs.end()) + stride - 1) / stride;
|
|
139
173
|
const auto now = std::chrono::steady_clock::now();
|
|
140
174
|
const auto elapsed_in_cleanup_window =
|
|
141
175
|
std::chrono::duration_cast<std::chrono::microseconds>(now - start);
|
|
142
176
|
const auto remaining_in_cleanup_window = cleanup_window - elapsed_in_cleanup_window;
|
|
177
|
+
// Divide the time left in the window evenly among the ATRs still to launch, so the scan is
|
|
178
|
+
// spread across the window rather than issued as a burst.
|
|
143
179
|
const auto budget_for_this_atr = std::chrono::microseconds(
|
|
144
180
|
remaining_in_cleanup_window.count() /
|
|
145
181
|
std::max<decltype(it)::difference_type>(1, atrs_left_for_this_client));
|
|
146
|
-
//
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
CB_LOST_ATTEMPT_CLEANUP_LOG_DEBUG("cleanup of {} complete", keyspace);
|
|
150
|
-
return;
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
try {
|
|
154
|
-
handle_atr_cleanup({ keyspace.bucket, keyspace.scope, keyspace.collection, atr_id });
|
|
155
|
-
} catch (const std::exception& e) {
|
|
156
|
-
CB_LOST_ATTEMPT_CLEANUP_LOG_ERROR(
|
|
157
|
-
"cleanup of atr {} failed with {}, moving on", atr_id, e.what());
|
|
182
|
+
// Bound concurrency: reclaim a finished slot before launching the next check.
|
|
183
|
+
while (in_flight.size() >= max_in_flight_atr_checks_) {
|
|
184
|
+
reclaim_one();
|
|
158
185
|
}
|
|
159
186
|
|
|
160
|
-
const
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
187
|
+
const std::string atr_id = *it;
|
|
188
|
+
// Offload the blocking check to the shared bounded pool (never the IO thread); keep its
|
|
189
|
+
// future so the loop can bound how many run concurrently and drain them at the end.
|
|
190
|
+
// packaged_task is wrapped in a shared_ptr because asio::post needs a copyable handler.
|
|
191
|
+
auto task = std::make_shared<std::packaged_task<void()>>([this, keyspace, atr_id]() {
|
|
192
|
+
try {
|
|
193
|
+
handle_atr_cleanup({ keyspace.bucket, keyspace.scope, keyspace.collection, atr_id });
|
|
194
|
+
} catch (const std::exception& e) {
|
|
195
|
+
CB_LOST_ATTEMPT_CLEANUP_LOG_ERROR(
|
|
196
|
+
"cleanup of atr {} failed with {}, moving on", atr_id, e.what());
|
|
197
|
+
}
|
|
198
|
+
});
|
|
199
|
+
auto future = task->get_future();
|
|
200
|
+
// Post before recording the future. If asio::post() throws (e.g. allocation failure) the
|
|
201
|
+
// task never runs; recording its future first would leave a future in `in_flight` that
|
|
202
|
+
// never becomes ready, deadlocking reclaim_one()/the drain. On throw, `future` is discarded
|
|
203
|
+
// and the exception unwinds to the per-collection retry below.
|
|
204
|
+
asio::post(atr_cleanup_pool, [task]() {
|
|
205
|
+
(*task)();
|
|
206
|
+
});
|
|
207
|
+
in_flight.emplace_back(std::move(future));
|
|
208
|
+
|
|
209
|
+
// Pace the launch cadence so the scan spreads across the window rather than bursting.
|
|
210
|
+
// Subtract the time already spent this iteration -- reclaiming a slot can block on a slow
|
|
211
|
+
// lookup, and posting takes time -- from the budget, so a slow iteration does not push the
|
|
212
|
+
// scan past the cleanup window. If we are already behind, the remainder is <= 0 and we
|
|
213
|
+
// proceed immediately.
|
|
214
|
+
const auto work_time = std::chrono::duration_cast<std::chrono::microseconds>(
|
|
215
|
+
std::chrono::steady_clock::now() - now);
|
|
216
|
+
const auto sleep_for_this_atr = budget_for_this_atr - work_time;
|
|
217
|
+
if (sleep_for_this_atr.count() > 0 &&
|
|
218
|
+
sleep_for_this_atr.count() < 1000000000) { // safety check protects against bugs
|
|
219
|
+
if (!interruptable_wait(sleep_for_this_atr)) {
|
|
220
|
+
break;
|
|
179
221
|
}
|
|
180
222
|
}
|
|
181
223
|
}
|
|
224
|
+
|
|
225
|
+
// Wait for any still-running checks before completing the run. On stop() the launch loop
|
|
226
|
+
// above has already stopped starting new checks (it breaks on !is_running()), so this only
|
|
227
|
+
// drains the
|
|
228
|
+
// <= max_in_flight_atr_checks_ already in flight. They are reclaimed rather than abandoned
|
|
229
|
+
// because each task references this cleanup state; teardown therefore blocks on them, bounded
|
|
230
|
+
// by the KV read timeout (an in-flight get_atr is not cancelled).
|
|
231
|
+
while (!in_flight.empty()) {
|
|
232
|
+
reclaim_one();
|
|
233
|
+
}
|
|
234
|
+
if (!is_running()) {
|
|
235
|
+
CB_LOST_ATTEMPT_CLEANUP_LOG_DEBUG("cleanup of {} complete", keyspace);
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
182
238
|
} catch (const std::exception& ex) {
|
|
183
239
|
CB_LOST_ATTEMPT_CLEANUP_LOG_ERROR("cleanup failed with {}, trying again in 3 sec...",
|
|
184
240
|
ex.what());
|
|
@@ -586,10 +642,17 @@ transactions_cleanup::add_collection(const couchbase::transactions::transaction_
|
|
|
586
642
|
auto it = std::find(collections_.begin(), collections_.end(), keyspace);
|
|
587
643
|
if (it == collections_.end()) {
|
|
588
644
|
collections_.emplace_back(keyspace);
|
|
589
|
-
//
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
645
|
+
// Spawn only while running. stop() takes the worker handles out and joins them, so a
|
|
646
|
+
// handle appended after that point is one nothing has agreed to join -- and a
|
|
647
|
+
// joinable std::thread that reaches its destructor terminates. Registering the
|
|
648
|
+
// keyspace is still right: start() spawns a worker for everything in collections_,
|
|
649
|
+
// so cleanup resumes for it on the next start.
|
|
650
|
+
if (running_) {
|
|
651
|
+
// start cleaning right away
|
|
652
|
+
lost_attempt_cleanup_workers_.emplace_back([this, keyspace = collections_.back()]() {
|
|
653
|
+
this->clean_collection(keyspace);
|
|
654
|
+
});
|
|
655
|
+
}
|
|
593
656
|
}
|
|
594
657
|
lock.unlock();
|
|
595
658
|
CB_ATTEMPT_CLEANUP_LOG_DEBUG("added {} to lost transaction cleanup", keyspace);
|
|
@@ -599,8 +662,41 @@ transactions_cleanup::add_collection(const couchbase::transactions::transaction_
|
|
|
599
662
|
void
|
|
600
663
|
transactions_cleanup::start()
|
|
601
664
|
{
|
|
602
|
-
|
|
603
|
-
|
|
665
|
+
// The pool has to exist before any worker does: clean_collection() treats a missing pool
|
|
666
|
+
// as a broken invariant and gives up on the keyspace.
|
|
667
|
+
if (config_.cleanup_config.cleanup_lost_attempts) {
|
|
668
|
+
// Blocking per-ATR checks are offloaded to this bounded pool, never the single IO thread.
|
|
669
|
+
atr_cleanup_pool_.emplace(max_in_flight_atr_checks_);
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
{
|
|
673
|
+
// running_ is read under mutex_ everywhere else -- is_running(), interruptable_wait(),
|
|
674
|
+
// add_collection() and stop() -- so it is written under it here too, rather than being
|
|
675
|
+
// the one unsynchronized access to it.
|
|
676
|
+
//
|
|
677
|
+
// Publishing it in the same critical section as the respawn below also settles who
|
|
678
|
+
// spawns what. A concurrent add_collection() either runs before this section and only
|
|
679
|
+
// registers its keyspace, which the loop then spawns for, or after it and spawns for
|
|
680
|
+
// itself, by which point the loop has already gone past. Exactly one worker per
|
|
681
|
+
// keyspace either way.
|
|
682
|
+
const std::unique_lock<std::mutex> lock(mutex_);
|
|
683
|
+
running_ = config_.cleanup_config.cleanup_client_attempts ||
|
|
684
|
+
config_.cleanup_config.cleanup_lost_attempts;
|
|
685
|
+
|
|
686
|
+
if (config_.cleanup_config.cleanup_lost_attempts) {
|
|
687
|
+
// Re-spawn a worker for every keyspace still registered from before a previous
|
|
688
|
+
// stop(). add_collection() below cannot do it: it dedupes on collections_, so
|
|
689
|
+
// for an already-registered keyspace it skips the worker and lost-attempt
|
|
690
|
+
// cleanup stays dead for the rest of the process. Any fork leaves exactly that
|
|
691
|
+
// state behind -- notify_fork(prepare) stops cleanup, notify_fork(parent)
|
|
692
|
+
// starts it again.
|
|
693
|
+
for (const auto& keyspace : collections_) {
|
|
694
|
+
lost_attempt_cleanup_workers_.emplace_back([this, keyspace]() {
|
|
695
|
+
this->clean_collection(keyspace);
|
|
696
|
+
});
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
}
|
|
604
700
|
if (config_.cleanup_config.cleanup_client_attempts) {
|
|
605
701
|
cleanup_thr_ = std::thread([this] {
|
|
606
702
|
attempts_loop();
|
|
@@ -628,12 +724,41 @@ transactions_cleanup::stop()
|
|
|
628
724
|
cleanup_thr_.join();
|
|
629
725
|
CB_ATTEMPT_CLEANUP_LOG_DEBUG("cleanup attempt thread closed");
|
|
630
726
|
}
|
|
631
|
-
|
|
727
|
+
// Take the handles out under mutex_, then join them with the lock released.
|
|
728
|
+
//
|
|
729
|
+
// Under the lock, because add_collection() and start() append to this list while
|
|
730
|
+
// holding mutex_. Walking it while another thread appends is a data race on the
|
|
731
|
+
// list itself, and an append that lands after it was emptied would leave a
|
|
732
|
+
// joinable std::thread to be destroyed later, which terminates.
|
|
733
|
+
//
|
|
734
|
+
// With the lock released, because the workers themselves take mutex_ to see
|
|
735
|
+
// running_ (interruptable_wait, and the collections_ lookup in clean_collection),
|
|
736
|
+
// so joining while holding it deadlocks.
|
|
737
|
+
//
|
|
738
|
+
// Moving the handles out also drops them, which a later start() needs in order to
|
|
739
|
+
// spawn fresh workers. collections_ is deliberately kept: it also holds keyspaces
|
|
740
|
+
// registered at runtime, and discarding those would silently stop cleaning them.
|
|
741
|
+
std::list<std::thread> workers;
|
|
742
|
+
{
|
|
743
|
+
const std::unique_lock<std::mutex> lock(mutex_);
|
|
744
|
+
workers.swap(lost_attempt_cleanup_workers_);
|
|
745
|
+
}
|
|
746
|
+
for (auto& t : workers) {
|
|
632
747
|
CB_LOST_ATTEMPT_CLEANUP_LOG_DEBUG("shutting down all lost attempt threads...");
|
|
633
748
|
if (t.joinable()) {
|
|
634
749
|
t.join();
|
|
635
750
|
}
|
|
636
751
|
}
|
|
752
|
+
// Workers drain their in-flight checks before returning, so the pool is now idle. stop() before
|
|
753
|
+
// join(): the pool's threads wait for work, so join() alone would block indefinitely on an idle
|
|
754
|
+
// pool; stop() requests shutdown so join() returns (there is no pending work left to abandon).
|
|
755
|
+
// Reset afterwards so stop() is idempotent: close() calls stop() from the destructor and the user
|
|
756
|
+
// may also call it explicitly, and a joined pool must not be joined again.
|
|
757
|
+
if (atr_cleanup_pool_) {
|
|
758
|
+
atr_cleanup_pool_->stop();
|
|
759
|
+
atr_cleanup_pool_->join();
|
|
760
|
+
atr_cleanup_pool_.reset();
|
|
761
|
+
}
|
|
637
762
|
}
|
|
638
763
|
|
|
639
764
|
void
|
|
@@ -641,7 +766,10 @@ transactions_cleanup::close()
|
|
|
641
766
|
{
|
|
642
767
|
stop();
|
|
643
768
|
CB_LOST_ATTEMPT_CLEANUP_LOG_DEBUG("all lost attempt cleanup threads closed");
|
|
644
|
-
|
|
769
|
+
// In a forked child the record is the parent's, and the parent is still registered under it.
|
|
770
|
+
if (client_record_owner_pid_ == utils::current_process_id()) {
|
|
771
|
+
remove_client_record_from_all_buckets(client_uuid_);
|
|
772
|
+
}
|
|
645
773
|
}
|
|
646
774
|
|
|
647
775
|
transactions_cleanup::~transactions_cleanup()
|
|
@@ -32,17 +32,6 @@ transactions_config::transactions_config()
|
|
|
32
32
|
|
|
33
33
|
transactions_config::~transactions_config() = default;
|
|
34
34
|
|
|
35
|
-
transactions_config::transactions_config(transactions_config&& c) noexcept
|
|
36
|
-
: level_(c.level_)
|
|
37
|
-
, timeout_(c.timeout_)
|
|
38
|
-
, attempt_context_hooks_(c.attempt_context_hooks_)
|
|
39
|
-
, cleanup_hooks_(c.cleanup_hooks_)
|
|
40
|
-
, metadata_collection_(std::move(c.metadata_collection_))
|
|
41
|
-
, query_config_(c.query_config_)
|
|
42
|
-
, cleanup_config_(std::move(c.cleanup_config_))
|
|
43
|
-
{
|
|
44
|
-
}
|
|
45
|
-
|
|
46
35
|
transactions_config::transactions_config(const transactions_config& config)
|
|
47
36
|
: level_(config.durability_level())
|
|
48
37
|
, timeout_(config.timeout())
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
#include "core/operations/document_lookup_in.hxx"
|
|
21
21
|
#include "core/operations/management/bucket_get_all.hxx"
|
|
22
22
|
#include "core/transactions/error_class.hxx"
|
|
23
|
+
#include "core/utils/byteswap.hxx"
|
|
23
24
|
|
|
24
25
|
#include <couchbase/collection.hxx>
|
|
25
26
|
#include <couchbase/scope.hxx>
|
|
@@ -53,6 +54,15 @@ now_ns_from_vbucket(const tao::json::value& vbucket) -> std::uint64_t
|
|
|
53
54
|
return stoull(now_str, nullptr, 10) * 1000000000;
|
|
54
55
|
}
|
|
55
56
|
|
|
57
|
+
auto
|
|
58
|
+
parse_mutation_cas(const std::string& cas) -> std::uint64_t
|
|
59
|
+
{
|
|
60
|
+
if (cas.empty()) {
|
|
61
|
+
return 0;
|
|
62
|
+
}
|
|
63
|
+
return core::utils::reverse_bytes(std::stoull(cas, nullptr, 16)) / 1000000;
|
|
64
|
+
}
|
|
65
|
+
|
|
56
66
|
void
|
|
57
67
|
wrap_collection_call(result& res, const std::function<void(result&)>& call)
|
|
58
68
|
{
|
|
@@ -79,6 +79,15 @@ public:
|
|
|
79
79
|
// we have the lock. Block all further ops
|
|
80
80
|
allow_ops_ = false;
|
|
81
81
|
}
|
|
82
|
+
// Peek at whether query mode has already been entered. Briefly acquires mutex_ but, unlike
|
|
83
|
+
// get_mode(), never waits on cv_query_ for the query node to be set, so it returns immediately.
|
|
84
|
+
// Used by defensive invariant checks: a KV mutation must never be staged once query mode is
|
|
85
|
+
// entered.
|
|
86
|
+
auto query_mode_entered() const -> bool
|
|
87
|
+
{
|
|
88
|
+
const std::scoped_lock lock(mutex_);
|
|
89
|
+
return mode_.mode == attempt_mode::modes::QUERY;
|
|
90
|
+
}
|
|
82
91
|
auto get_mode() -> attempt_mode
|
|
83
92
|
{
|
|
84
93
|
std::unique_lock<std::mutex> lock(mutex_);
|
|
@@ -143,8 +152,10 @@ public:
|
|
|
143
152
|
{
|
|
144
153
|
// when begin work errors out, it is fatal, so reset to kv mode here, allowing
|
|
145
154
|
// rollback to function properly.
|
|
146
|
-
std::
|
|
155
|
+
const std::scoped_lock lock(mutex_);
|
|
147
156
|
mode_.mode = attempt_mode::modes::KV;
|
|
157
|
+
// query_node is intentionally left populated: a retry runs with a fresh waitable_op_list, and
|
|
158
|
+
// get_mode()'s wait predicate keys on query_node, so clearing it here would serve no purpose.
|
|
148
159
|
cv_query_.notify_all();
|
|
149
160
|
}
|
|
150
161
|
|
|
@@ -158,7 +169,7 @@ public:
|
|
|
158
169
|
}
|
|
159
170
|
void decrement_in_flight()
|
|
160
171
|
{
|
|
161
|
-
std::
|
|
172
|
+
std::scoped_lock<std::mutex> lock(mutex_);
|
|
162
173
|
in_flight_--;
|
|
163
174
|
CB_TXN_LOG_TRACE("in_flight decremented to {}", in_flight_);
|
|
164
175
|
assert(in_flight_ >= 0);
|
|
@@ -170,7 +181,7 @@ public:
|
|
|
170
181
|
private:
|
|
171
182
|
void change_count(int32_t val)
|
|
172
183
|
{
|
|
173
|
-
std::
|
|
184
|
+
std::scoped_lock<std::mutex> lock(mutex_);
|
|
174
185
|
if (allow_ops_) {
|
|
175
186
|
count_ += val;
|
|
176
187
|
if (val > 0) {
|
|
@@ -199,6 +210,6 @@ private:
|
|
|
199
210
|
std::condition_variable cv_ops_;
|
|
200
211
|
std::condition_variable cv_query_;
|
|
201
212
|
std::condition_variable cv_in_flight_;
|
|
202
|
-
std::mutex mutex_;
|
|
213
|
+
mutable std::mutex mutex_;
|
|
203
214
|
};
|
|
204
215
|
} // namespace couchbase::core::transactions
|
|
@@ -127,7 +127,7 @@ using txn_complete_callback =
|
|
|
127
127
|
/** @brief Main class for creating a transaction
|
|
128
128
|
*
|
|
129
129
|
*/
|
|
130
|
-
class transactions
|
|
130
|
+
class transactions
|
|
131
131
|
{
|
|
132
132
|
public:
|
|
133
133
|
/**
|
|
@@ -182,10 +182,6 @@ public:
|
|
|
182
182
|
auto run(const couchbase::transactions::transaction_options& config,
|
|
183
183
|
logic&& code) -> couchbase::transactions::transaction_result;
|
|
184
184
|
|
|
185
|
-
auto run(::couchbase::transactions::txn_logic&& code,
|
|
186
|
-
const couchbase::transactions::transaction_options& config)
|
|
187
|
-
-> std::pair<couchbase::error, couchbase::transactions::transaction_result> override;
|
|
188
|
-
|
|
189
185
|
/**
|
|
190
186
|
* @brief Run a transaction
|
|
191
187
|
*
|
|
@@ -204,9 +200,6 @@ public:
|
|
|
204
200
|
async_logic&& code,
|
|
205
201
|
txn_complete_callback&& cb);
|
|
206
202
|
|
|
207
|
-
void run(couchbase::transactions::async_txn_logic&& code,
|
|
208
|
-
couchbase::transactions::async_txn_complete_logic&& complete_cb,
|
|
209
|
-
const couchbase::transactions::transaction_options& config) override;
|
|
210
203
|
/**
|
|
211
204
|
* @internal
|
|
212
205
|
* called internally - will likely move
|
|
@@ -279,7 +272,7 @@ public:
|
|
|
279
272
|
transactions(core::cluster cluster, couchbase::transactions::transactions_config::built config);
|
|
280
273
|
transactions(core::cluster cluster, const couchbase::transactions::transactions_config& config);
|
|
281
274
|
|
|
282
|
-
~transactions()
|
|
275
|
+
~transactions();
|
|
283
276
|
|
|
284
277
|
private:
|
|
285
278
|
core::cluster cluster_;
|
|
@@ -288,5 +281,12 @@ private:
|
|
|
288
281
|
const std::size_t max_attempts_{ 1000 };
|
|
289
282
|
const std::chrono::milliseconds min_retry_delay_{ 1 };
|
|
290
283
|
};
|
|
284
|
+
|
|
285
|
+
// TODO(DC): Can we replace this with something better?
|
|
286
|
+
// This is needed as the performer needs to access the Core API to set hooks, access cleanup-related
|
|
287
|
+
// metrics, which are not exposed in the Public API.
|
|
288
|
+
auto
|
|
289
|
+
get_core_transactions(const std::shared_ptr<couchbase::transactions::transactions>& transactions)
|
|
290
|
+
-> std::shared_ptr<couchbase::core::transactions::transactions>;
|
|
291
291
|
} // namespace transactions
|
|
292
292
|
} // namespace couchbase::core
|