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
|
@@ -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,10 +27,13 @@
|
|
|
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>
|
|
35
38
|
#include <future>
|
|
36
39
|
#include <list>
|
|
@@ -55,34 +58,13 @@ transactions_cleanup::transactions_cleanup(
|
|
|
55
58
|
: cluster_(std::move(cluster))
|
|
56
59
|
, config_(std::move(config))
|
|
57
60
|
, client_uuid_(uid_generator::next())
|
|
61
|
+
, client_record_owner_pid_(utils::current_process_id())
|
|
58
62
|
{
|
|
59
63
|
start();
|
|
60
64
|
}
|
|
61
65
|
|
|
62
66
|
namespace
|
|
63
67
|
{
|
|
64
|
-
/**
|
|
65
|
-
* ${Mutation.CAS} is written by kvengine with
|
|
66
|
-
* 'macroToString(htonll(info.cas))'. Discussed this with KV team and, though
|
|
67
|
-
* there is consensus that this is off (htonll is definitely wrong, and a string
|
|
68
|
-
* is an odd choice), there are clients (SyncGateway) that consume the current
|
|
69
|
-
* string, so it can't be changed. Note that only little-endian servers are
|
|
70
|
-
* supported for Couchbase, so the 8 byte long inside the string will always be
|
|
71
|
-
* little-endian ordered.
|
|
72
|
-
*
|
|
73
|
-
* Looks like: "0x000058a71dd25c15"
|
|
74
|
-
* Want: 0x155CD21DA7580000 (1539336197457313792 in base10, an epoch
|
|
75
|
-
* time in millionths of a second)
|
|
76
|
-
*/
|
|
77
|
-
auto
|
|
78
|
-
parse_mutation_cas(const std::string& cas) -> std::uint64_t
|
|
79
|
-
{
|
|
80
|
-
if (cas.empty()) {
|
|
81
|
-
return 0;
|
|
82
|
-
}
|
|
83
|
-
return core::utils::byte_swap(std::stoull(cas, nullptr, 16)) / 1000000;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
68
|
// TODO(CXXCBC-549)
|
|
87
69
|
const std::string CLIENT_RECORD_DOC_ID = "_txn:client-record"; // NOLINT(cert-err58-cpp)
|
|
88
70
|
} // namespace
|
|
@@ -111,7 +93,7 @@ transactions_cleanup::clean_collection(
|
|
|
111
93
|
// first make sure the collection is in the list
|
|
112
94
|
while (is_running()) {
|
|
113
95
|
{
|
|
114
|
-
const std::
|
|
96
|
+
const std::scoped_lock<std::mutex> lock(mutex_);
|
|
115
97
|
if (collections_.end() == std::find(collections_.begin(), collections_.end(), keyspace)) {
|
|
116
98
|
CB_LOST_ATTEMPT_CLEANUP_LOG_DEBUG(
|
|
117
99
|
"cleanup for {} ending, no longer in collection cleanup list", keyspace);
|
|
@@ -134,54 +116,125 @@ transactions_cleanup::clean_collection(
|
|
|
134
116
|
all_atrs.size(),
|
|
135
117
|
config_.cleanup_config.cleanup_window.count());
|
|
136
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
|
+
|
|
137
162
|
for (auto it = all_atrs.begin() + details.index_of_this_client; it < all_atrs.end();
|
|
138
163
|
it += details.num_active_clients) {
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
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;
|
|
142
173
|
const auto now = std::chrono::steady_clock::now();
|
|
143
174
|
const auto elapsed_in_cleanup_window =
|
|
144
175
|
std::chrono::duration_cast<std::chrono::microseconds>(now - start);
|
|
145
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.
|
|
146
179
|
const auto budget_for_this_atr = std::chrono::microseconds(
|
|
147
180
|
remaining_in_cleanup_window.count() /
|
|
148
181
|
std::max<decltype(it)::difference_type>(1, atrs_left_for_this_client));
|
|
149
|
-
//
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
CB_LOST_ATTEMPT_CLEANUP_LOG_DEBUG("cleanup of {} complete", keyspace);
|
|
153
|
-
return;
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
try {
|
|
157
|
-
handle_atr_cleanup({ keyspace.bucket, keyspace.scope, keyspace.collection, atr_id });
|
|
158
|
-
} catch (const std::exception& e) {
|
|
159
|
-
CB_LOST_ATTEMPT_CLEANUP_LOG_ERROR(
|
|
160
|
-
"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();
|
|
161
185
|
}
|
|
162
186
|
|
|
163
|
-
const
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
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;
|
|
182
221
|
}
|
|
183
222
|
}
|
|
184
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
|
+
}
|
|
185
238
|
} catch (const std::exception& ex) {
|
|
186
239
|
CB_LOST_ATTEMPT_CLEANUP_LOG_ERROR("cleanup failed with {}, trying again in 3 sec...",
|
|
187
240
|
ex.what());
|
|
@@ -590,10 +643,10 @@ transactions_cleanup::add_collection(const couchbase::transactions::transaction_
|
|
|
590
643
|
if (it == collections_.end()) {
|
|
591
644
|
collections_.emplace_back(keyspace);
|
|
592
645
|
// Spawn only while running. stop() takes the worker handles out and joins them, so a
|
|
593
|
-
// handle appended after that point is one nothing has agreed to join -- and a
|
|
594
|
-
// std::thread
|
|
595
|
-
// right: start() spawns a worker for everything in collections_,
|
|
596
|
-
// it on the next start.
|
|
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.
|
|
597
650
|
if (running_) {
|
|
598
651
|
// start cleaning right away
|
|
599
652
|
lost_attempt_cleanup_workers_.emplace_back([this, keyspace = collections_.back()]() {
|
|
@@ -609,17 +662,34 @@ transactions_cleanup::add_collection(const couchbase::transactions::transaction_
|
|
|
609
662
|
void
|
|
610
663
|
transactions_cleanup::start()
|
|
611
664
|
{
|
|
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
|
+
|
|
612
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.
|
|
613
682
|
const std::unique_lock<std::mutex> lock(mutex_);
|
|
614
683
|
running_ = config_.cleanup_config.cleanup_client_attempts ||
|
|
615
684
|
config_.cleanup_config.cleanup_lost_attempts;
|
|
616
685
|
|
|
617
686
|
if (config_.cleanup_config.cleanup_lost_attempts) {
|
|
618
|
-
// Re-spawn a worker for every keyspace still registered from before a previous
|
|
619
|
-
// add_collection() below cannot do
|
|
620
|
-
// already-registered keyspace
|
|
621
|
-
// rest of the process.
|
|
622
|
-
//
|
|
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.
|
|
623
693
|
for (const auto& keyspace : collections_) {
|
|
624
694
|
lost_attempt_cleanup_workers_.emplace_back([this, keyspace]() {
|
|
625
695
|
this->clean_collection(keyspace);
|
|
@@ -654,10 +724,20 @@ transactions_cleanup::stop()
|
|
|
654
724
|
cleanup_thr_.join();
|
|
655
725
|
CB_ATTEMPT_CLEANUP_LOG_DEBUG("cleanup attempt thread closed");
|
|
656
726
|
}
|
|
657
|
-
// Take the handles out under mutex_, then join with the lock released
|
|
658
|
-
//
|
|
659
|
-
//
|
|
660
|
-
//
|
|
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.
|
|
661
741
|
std::list<std::thread> workers;
|
|
662
742
|
{
|
|
663
743
|
const std::unique_lock<std::mutex> lock(mutex_);
|
|
@@ -669,6 +749,16 @@ transactions_cleanup::stop()
|
|
|
669
749
|
t.join();
|
|
670
750
|
}
|
|
671
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
|
+
}
|
|
672
762
|
}
|
|
673
763
|
|
|
674
764
|
void
|
|
@@ -676,7 +766,10 @@ transactions_cleanup::close()
|
|
|
676
766
|
{
|
|
677
767
|
stop();
|
|
678
768
|
CB_LOST_ATTEMPT_CLEANUP_LOG_DEBUG("all lost attempt cleanup threads closed");
|
|
679
|
-
|
|
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
|
+
}
|
|
680
773
|
}
|
|
681
774
|
|
|
682
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
|
{
|
|
@@ -169,7 +169,7 @@ public:
|
|
|
169
169
|
}
|
|
170
170
|
void decrement_in_flight()
|
|
171
171
|
{
|
|
172
|
-
std::
|
|
172
|
+
std::scoped_lock<std::mutex> lock(mutex_);
|
|
173
173
|
in_flight_--;
|
|
174
174
|
CB_TXN_LOG_TRACE("in_flight decremented to {}", in_flight_);
|
|
175
175
|
assert(in_flight_ >= 0);
|
|
@@ -181,7 +181,7 @@ public:
|
|
|
181
181
|
private:
|
|
182
182
|
void change_count(int32_t val)
|
|
183
183
|
{
|
|
184
|
-
std::
|
|
184
|
+
std::scoped_lock<std::mutex> lock(mutex_);
|
|
185
185
|
if (allow_ops_) {
|
|
186
186
|
count_ += val;
|
|
187
187
|
if (val > 0) {
|
|
@@ -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
|