couchbase 3.8.2 → 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 +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 +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 +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 +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 +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 +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 +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 +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 +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
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
|
|
2
|
+
/*
|
|
3
|
+
* Copyright 2026. Couchbase, Inc.
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
#include "query_stream_component.hxx"
|
|
19
|
+
|
|
20
|
+
#include "free_form_http_request.hxx"
|
|
21
|
+
#include "http_component.hxx"
|
|
22
|
+
#include "impl/bootstrap_error.hxx"
|
|
23
|
+
#include "logger/logger.hxx"
|
|
24
|
+
#include "operations/document_query.hxx"
|
|
25
|
+
#include "platform/uuid.h"
|
|
26
|
+
#include "service_type.hxx"
|
|
27
|
+
#include "utils/json.hxx"
|
|
28
|
+
|
|
29
|
+
#include <couchbase/error_codes.hxx>
|
|
30
|
+
|
|
31
|
+
#include <asio/io_context.hpp>
|
|
32
|
+
#include <spdlog/fmt/bundled/core.h>
|
|
33
|
+
#include <tao/json/value.hpp>
|
|
34
|
+
|
|
35
|
+
#include <chrono>
|
|
36
|
+
#include <memory>
|
|
37
|
+
#include <mutex>
|
|
38
|
+
#include <string>
|
|
39
|
+
#include <system_error>
|
|
40
|
+
#include <utility>
|
|
41
|
+
|
|
42
|
+
namespace couchbase::core
|
|
43
|
+
{
|
|
44
|
+
namespace
|
|
45
|
+
{
|
|
46
|
+
auto
|
|
47
|
+
to_error_code(std::error_code err) -> std::error_code
|
|
48
|
+
{
|
|
49
|
+
return err;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
auto
|
|
53
|
+
build_streaming_query_body(const operations::query_request& request,
|
|
54
|
+
const std::string& client_context_id,
|
|
55
|
+
std::chrono::milliseconds timeout) -> std::string
|
|
56
|
+
{
|
|
57
|
+
tao::json::value body{};
|
|
58
|
+
|
|
59
|
+
// The remaining options are identical to the buffered query path; share one encoder so the two
|
|
60
|
+
// stay byte-for-byte consistent. The use_replica capability gate is enforced earlier in
|
|
61
|
+
// cluster::query_stream. This runs first so the control fields set below always win over any
|
|
62
|
+
// same-named `raw` entry a caller may have supplied.
|
|
63
|
+
operations::encode_query_options(body, request);
|
|
64
|
+
|
|
65
|
+
auto timeout_for_service = timeout;
|
|
66
|
+
if (timeout_for_service > std::chrono::milliseconds(5'000)) {
|
|
67
|
+
// Tell the query engine its deadline is 500ms tighter than ours, so we always observe the
|
|
68
|
+
// server-side timeout response before our own deadline fires.
|
|
69
|
+
timeout_for_service -= std::chrono::milliseconds(500);
|
|
70
|
+
}
|
|
71
|
+
body["client_context_id"] = client_context_id;
|
|
72
|
+
body["statement"] = request.statement;
|
|
73
|
+
body["timeout"] = fmt::format("{}ms", timeout_for_service.count());
|
|
74
|
+
|
|
75
|
+
return utils::json::generate(body);
|
|
76
|
+
}
|
|
77
|
+
} // namespace
|
|
78
|
+
|
|
79
|
+
class query_stream_component_impl : public std::enable_shared_from_this<query_stream_component_impl>
|
|
80
|
+
{
|
|
81
|
+
public:
|
|
82
|
+
query_stream_component_impl(asio::io_context& io,
|
|
83
|
+
http_component http,
|
|
84
|
+
std::chrono::milliseconds default_timeout,
|
|
85
|
+
row_streamer_options streaming_options)
|
|
86
|
+
: io_{ io }
|
|
87
|
+
, http_{ std::move(http) }
|
|
88
|
+
, default_timeout_{ default_timeout }
|
|
89
|
+
, streaming_options_{ streaming_options }
|
|
90
|
+
{
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
void execute(operations::query_request request, query_stream_component::handler_type&& handler)
|
|
94
|
+
{
|
|
95
|
+
const std::string client_context_id =
|
|
96
|
+
request.client_context_id.value_or(uuid::to_string(uuid::random()));
|
|
97
|
+
const std::chrono::milliseconds timeout = request.timeout.value_or(default_timeout_);
|
|
98
|
+
|
|
99
|
+
http_request http_req{ service_type::query, "POST" };
|
|
100
|
+
http_req.path = "/query/service";
|
|
101
|
+
|
|
102
|
+
// Everything about the request that an error context reports, known before dispatch. The
|
|
103
|
+
// response-side fields (HTTP status, the service's first error, the endpoint) are filled in as
|
|
104
|
+
// they become available, so a failure at any stage carries as much detail as the buffered path.
|
|
105
|
+
// Held behind a shared_ptr, not by value: it carries the encoded request body in
|
|
106
|
+
// `parameters`, and both the dispatch callback and the synchronous dispatch-failure branch
|
|
107
|
+
// below need it, so sharing avoids deep-copying that body on every streaming request.
|
|
108
|
+
auto base_ctx = std::make_shared<error_context::query>();
|
|
109
|
+
base_ctx->client_context_id = client_context_id;
|
|
110
|
+
base_ctx->statement = request.statement;
|
|
111
|
+
base_ctx->method = http_req.method;
|
|
112
|
+
base_ctx->path = http_req.path;
|
|
113
|
+
|
|
114
|
+
try {
|
|
115
|
+
http_req.body = build_streaming_query_body(request, client_context_id, timeout);
|
|
116
|
+
} catch (const std::exception&) {
|
|
117
|
+
// A caller-supplied raw/parameter value that is not valid JSON fails encoding; surface it as
|
|
118
|
+
// invalid_argument rather than letting the exception escape the public API.
|
|
119
|
+
base_ctx->ec = errc::common::invalid_argument;
|
|
120
|
+
return handler({}, std::move(*base_ctx));
|
|
121
|
+
}
|
|
122
|
+
base_ctx->parameters = http_req.body;
|
|
123
|
+
http_req.timeout = timeout;
|
|
124
|
+
http_req.client_context_id = client_context_id;
|
|
125
|
+
http_req.is_read_only = request.readonly;
|
|
126
|
+
http_req.headers["connection"] = "keep-alive";
|
|
127
|
+
http_req.headers["content-type"] = "application/json";
|
|
128
|
+
if (request.parent_span) {
|
|
129
|
+
http_req.parent_span = request.parent_span;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
auto callback_state = std::make_shared<callback_state_type>(std::move(handler));
|
|
133
|
+
|
|
134
|
+
using dispatch_error = std::error_code;
|
|
135
|
+
|
|
136
|
+
const bool read_only = request.readonly;
|
|
137
|
+
auto op = http_.do_http_request(
|
|
138
|
+
http_req,
|
|
139
|
+
[self = shared_from_this(), callback_state, timeout, read_only, base_ctx](
|
|
140
|
+
http_response resp, dispatch_error err) mutable {
|
|
141
|
+
if (auto ec = to_error_code(err)) {
|
|
142
|
+
base_ctx->ec = ec;
|
|
143
|
+
self->invoke(callback_state, {}, std::move(*base_ctx));
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
// The response is in hand, so the context can now name the endpoint and HTTP status.
|
|
147
|
+
base_ctx->http_status = resp.status_code();
|
|
148
|
+
const auto dispatch_info = resp.dispatch_info();
|
|
149
|
+
base_ctx->hostname = dispatch_info.hostname;
|
|
150
|
+
base_ctx->port = dispatch_info.port;
|
|
151
|
+
if (!dispatch_info.remote_address.empty()) {
|
|
152
|
+
base_ctx->last_dispatched_to = dispatch_info.remote_address;
|
|
153
|
+
}
|
|
154
|
+
if (!dispatch_info.local_address.empty()) {
|
|
155
|
+
base_ctx->last_dispatched_from = dispatch_info.local_address;
|
|
156
|
+
}
|
|
157
|
+
// Use the cluster's streaming tuning, but bound the server between reads with this
|
|
158
|
+
// request's timeout: if it stalls mid-body the stream times out rather than hanging next()
|
|
159
|
+
// forever (the request timeout is otherwise released once headers arrive).
|
|
160
|
+
auto options = self->streaming_options_;
|
|
161
|
+
options.idle_timeout = timeout;
|
|
162
|
+
options.is_read_only = read_only;
|
|
163
|
+
auto stream =
|
|
164
|
+
std::make_shared<query_stream>(self->io_, resp.body(), options, resp.status_code());
|
|
165
|
+
stream->start(
|
|
166
|
+
[self, callback_state, stream, base_ctx](std::error_code early_error) mutable {
|
|
167
|
+
if (early_error) {
|
|
168
|
+
// The preamble is what carried the failure, so stamp its diagnostics before tearing
|
|
169
|
+
// the stream down.
|
|
170
|
+
base_ctx->ec = early_error;
|
|
171
|
+
apply_error_details(*base_ctx, stream->error_details());
|
|
172
|
+
// No consumer will ever take ownership of this stream, so tear the underlying body
|
|
173
|
+
// (socket + timers) down now rather than when the last handle drops.
|
|
174
|
+
stream->cancel();
|
|
175
|
+
self->invoke(callback_state, {}, std::move(*base_ctx));
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
// Hand the base context to the consumer alongside the stream: a terminal error reached
|
|
179
|
+
// later is stamped onto it, so a mid-stream failure reports the same detail as this
|
|
180
|
+
// one.
|
|
181
|
+
self->invoke(callback_state, std::move(*stream), std::move(*base_ctx));
|
|
182
|
+
});
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
if (!op.has_value()) {
|
|
186
|
+
base_ctx->ec = to_error_code(op.error());
|
|
187
|
+
invoke(callback_state, {}, std::move(*base_ctx));
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
private:
|
|
192
|
+
struct callback_state_type {
|
|
193
|
+
explicit callback_state_type(query_stream_component::handler_type h)
|
|
194
|
+
: handler{ std::move(h) }
|
|
195
|
+
{
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
query_stream_component::handler_type handler;
|
|
199
|
+
std::mutex mutex{};
|
|
200
|
+
bool invoked{ false };
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
void invoke(const std::shared_ptr<callback_state_type>& state,
|
|
204
|
+
query_stream stream,
|
|
205
|
+
error_context::query ctx)
|
|
206
|
+
{
|
|
207
|
+
query_stream_component::handler_type handler;
|
|
208
|
+
{
|
|
209
|
+
const std::scoped_lock lock{ state->mutex };
|
|
210
|
+
if (state->invoked) {
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
state->invoked = true;
|
|
214
|
+
handler = std::move(state->handler);
|
|
215
|
+
}
|
|
216
|
+
if (handler) {
|
|
217
|
+
handler(std::move(stream), std::move(ctx));
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
asio::io_context& io_;
|
|
222
|
+
http_component http_;
|
|
223
|
+
std::chrono::milliseconds default_timeout_;
|
|
224
|
+
row_streamer_options streaming_options_;
|
|
225
|
+
};
|
|
226
|
+
|
|
227
|
+
query_stream_component::query_stream_component(asio::io_context& io,
|
|
228
|
+
http_component http,
|
|
229
|
+
std::chrono::milliseconds default_timeout,
|
|
230
|
+
row_streamer_options streaming_options)
|
|
231
|
+
: impl_{ std::make_shared<query_stream_component_impl>(io,
|
|
232
|
+
std::move(http),
|
|
233
|
+
default_timeout,
|
|
234
|
+
streaming_options) }
|
|
235
|
+
{
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
void
|
|
239
|
+
query_stream_component::execute(operations::query_request request, handler_type&& handler) const
|
|
240
|
+
{
|
|
241
|
+
impl_->execute(std::move(request), std::move(handler));
|
|
242
|
+
}
|
|
243
|
+
} // namespace couchbase::core
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
|
|
2
|
+
/*
|
|
3
|
+
* Copyright 2026. Couchbase, Inc.
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
#pragma once
|
|
19
|
+
|
|
20
|
+
#include "error_context/query.hxx"
|
|
21
|
+
#include "operations/document_query.hxx"
|
|
22
|
+
#include "query_stream.hxx"
|
|
23
|
+
#include "utils/movable_function.hxx"
|
|
24
|
+
|
|
25
|
+
#include <chrono>
|
|
26
|
+
#include <memory>
|
|
27
|
+
#include <system_error>
|
|
28
|
+
|
|
29
|
+
namespace asio
|
|
30
|
+
{
|
|
31
|
+
class io_context;
|
|
32
|
+
} // namespace asio
|
|
33
|
+
|
|
34
|
+
namespace couchbase::core
|
|
35
|
+
{
|
|
36
|
+
class http_component;
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Dispatches a classic N1QL query as a streaming HTTP request and resolves to a query_stream
|
|
40
|
+
* handle once the response preamble (signature + upfront errors) has been parsed.
|
|
41
|
+
*
|
|
42
|
+
* Unlike the buffered query() path this never materialises the full response body. It performs no
|
|
43
|
+
* client-side retry or prepared-statement caching: the streaming path is only taken for adhoc
|
|
44
|
+
* requests (the public layer routes prepared statements to the buffered path).
|
|
45
|
+
*/
|
|
46
|
+
class query_stream_component
|
|
47
|
+
{
|
|
48
|
+
public:
|
|
49
|
+
// The context carries the error code (error_context::query::ec) alongside the diagnostics the
|
|
50
|
+
// buffered path reports — statement, parameters, the service's first error, HTTP status and body,
|
|
51
|
+
// and where the request was dispatched — so a streaming failure is as diagnosable as a buffered
|
|
52
|
+
// one. It is delivered on both outcomes: when the stream fails to start it describes that
|
|
53
|
+
// failure, and when it starts it describes the request and its dispatch, for the consumer to
|
|
54
|
+
// report a terminal error against later. Only `ec` differs between the two: falsy means the
|
|
55
|
+
// stream started.
|
|
56
|
+
using handler_type = utils::movable_function<void(query_stream, error_context::query)>;
|
|
57
|
+
|
|
58
|
+
query_stream_component(asio::io_context& io,
|
|
59
|
+
http_component http,
|
|
60
|
+
std::chrono::milliseconds default_timeout,
|
|
61
|
+
row_streamer_options streaming_options = {});
|
|
62
|
+
|
|
63
|
+
void execute(operations::query_request request, handler_type&& handler) const;
|
|
64
|
+
|
|
65
|
+
private:
|
|
66
|
+
std::shared_ptr<class query_stream_component_impl> impl_;
|
|
67
|
+
};
|
|
68
|
+
} // namespace couchbase::core
|
|
@@ -36,7 +36,7 @@ range_scan_node_state::range_scan_node_state(std::queue<std::uint16_t> vbuckets)
|
|
|
36
36
|
auto
|
|
37
37
|
range_scan_node_state::fetch_vbucket_id() -> std::optional<std::uint16_t>
|
|
38
38
|
{
|
|
39
|
-
const std::
|
|
39
|
+
const std::scoped_lock<std::mutex> lock{ mutex_ };
|
|
40
40
|
if (pending_vbuckets_.empty()) {
|
|
41
41
|
return {};
|
|
42
42
|
}
|
|
@@ -49,28 +49,28 @@ range_scan_node_state::fetch_vbucket_id() -> std::optional<std::uint16_t>
|
|
|
49
49
|
void
|
|
50
50
|
range_scan_node_state::notify_stream_ended()
|
|
51
51
|
{
|
|
52
|
-
const std::
|
|
52
|
+
const std::scoped_lock<std::mutex> lock{ mutex_ };
|
|
53
53
|
active_stream_count_--;
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
void
|
|
57
57
|
range_scan_node_state::enqueue_vbucket(std::uint16_t vbucket_id)
|
|
58
58
|
{
|
|
59
|
-
const std::
|
|
59
|
+
const std::scoped_lock<std::mutex> lock{ mutex_ };
|
|
60
60
|
pending_vbuckets_.push(vbucket_id);
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
auto
|
|
64
64
|
range_scan_node_state::active_stream_count() -> std::uint16_t
|
|
65
65
|
{
|
|
66
|
-
const std::
|
|
66
|
+
const std::scoped_lock<std::mutex> lock{ mutex_ };
|
|
67
67
|
return active_stream_count_;
|
|
68
68
|
}
|
|
69
69
|
|
|
70
70
|
auto
|
|
71
71
|
range_scan_node_state::pending_vbucket_count() -> std::size_t
|
|
72
72
|
{
|
|
73
|
-
const std::
|
|
73
|
+
const std::scoped_lock<std::mutex> lock{ mutex_ };
|
|
74
74
|
return pending_vbuckets_.size();
|
|
75
75
|
}
|
|
76
76
|
|
|
@@ -81,8 +81,15 @@ range_scan_load_balancer::range_scan_load_balancer(
|
|
|
81
81
|
{
|
|
82
82
|
std::map<std::int16_t, std::queue<std::uint16_t>> node_to_vbucket_map{};
|
|
83
83
|
for (std::size_t vbucket_id = 0; vbucket_id < vbucket_map.size(); vbucket_id++) {
|
|
84
|
-
auto
|
|
85
|
-
|
|
84
|
+
const auto& chain = vbucket_map[vbucket_id];
|
|
85
|
+
if (chain.empty()) {
|
|
86
|
+
// A row that names no node at all cannot be scanned, and there is no node
|
|
87
|
+
// to queue it against. range_scan_orchestrator refuses such a map before
|
|
88
|
+
// it starts any stream, so leaving the vbucket out here cannot silently
|
|
89
|
+
// shorten a scan.
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
node_to_vbucket_map[chain[0]].push(gsl::narrow_cast<std::uint16_t>(vbucket_id));
|
|
86
93
|
}
|
|
87
94
|
for (auto [node_id, vbucket_ids] : node_to_vbucket_map) {
|
|
88
95
|
nodes_.emplace(node_id, std::move(vbucket_ids));
|
|
@@ -98,7 +105,7 @@ range_scan_load_balancer::seed(std::uint64_t seed)
|
|
|
98
105
|
auto
|
|
99
106
|
range_scan_load_balancer::select_vbucket() -> std::optional<std::uint16_t>
|
|
100
107
|
{
|
|
101
|
-
const std::
|
|
108
|
+
const std::scoped_lock<std::mutex> lock{ select_vbucket_mutex_ };
|
|
102
109
|
|
|
103
110
|
auto min_stream_count = std::numeric_limits<std::uint16_t>::max();
|
|
104
111
|
std::optional<std::int16_t> selected_node_id{};
|
|
@@ -31,6 +31,7 @@
|
|
|
31
31
|
|
|
32
32
|
#include <gsl/util>
|
|
33
33
|
|
|
34
|
+
#include <algorithm>
|
|
34
35
|
#include <atomic>
|
|
35
36
|
#include <chrono>
|
|
36
37
|
#include <future>
|
|
@@ -398,6 +399,16 @@ public:
|
|
|
398
399
|
return cb(errc::common::invalid_argument, {});
|
|
399
400
|
}
|
|
400
401
|
|
|
402
|
+
// A scan needs an active copy for every vbucket, and every row of the map is
|
|
403
|
+
// indexed below to find one. A row that names no node at all leaves the scan
|
|
404
|
+
// unable to cover its vbucket, which is reported rather than served as a
|
|
405
|
+
// silently short result.
|
|
406
|
+
if (std::any_of(vbucket_map_.begin(), vbucket_map_.end(), [](const auto& chain) {
|
|
407
|
+
return chain.empty();
|
|
408
|
+
})) {
|
|
409
|
+
return cb(errc::network::configuration_not_available, {});
|
|
410
|
+
}
|
|
411
|
+
|
|
401
412
|
const get_collection_id_options get_cid_options{ options_.retry_strategy,
|
|
402
413
|
options_.timeout,
|
|
403
414
|
options_.parent_span };
|
|
@@ -429,7 +440,8 @@ public:
|
|
|
429
440
|
};
|
|
430
441
|
|
|
431
442
|
// Get the active node for the vbucket (values in vbucket map are the active node id
|
|
432
|
-
// followed by the ids of the replicas)
|
|
443
|
+
// followed by the ids of the replicas). scan() has already established that every row
|
|
444
|
+
// names one.
|
|
433
445
|
auto node_id = self->vbucket_map_[vbucket][0];
|
|
434
446
|
|
|
435
447
|
auto stream = std::make_shared<range_scan_stream>(
|
|
@@ -510,7 +522,7 @@ public:
|
|
|
510
522
|
} else {
|
|
511
523
|
// Empty signal means that stream has completed
|
|
512
524
|
{
|
|
513
|
-
const std::
|
|
525
|
+
const std::scoped_lock<std::mutex> lock{ self->stream_map_mutex_ };
|
|
514
526
|
self->streams_.erase(signal.vbucket_id);
|
|
515
527
|
}
|
|
516
528
|
return asio::post(asio::bind_executor(
|
|
@@ -540,7 +552,7 @@ public:
|
|
|
540
552
|
auto v = vbucket_id.value();
|
|
541
553
|
std::shared_ptr<range_scan_stream> stream{};
|
|
542
554
|
{
|
|
543
|
-
const std::
|
|
555
|
+
const std::scoped_lock<std::mutex> lock{ stream_map_mutex_ };
|
|
544
556
|
stream = streams_.at(v);
|
|
545
557
|
}
|
|
546
558
|
CB_LOG_TRACE("scanning vbucket {} at node {}", vbucket_id.value(), stream->node_id());
|
|
@@ -18,28 +18,65 @@
|
|
|
18
18
|
#pragma once
|
|
19
19
|
|
|
20
20
|
#include "core/error_context/key_value_error_map_info.hxx"
|
|
21
|
+
|
|
21
22
|
#include <couchbase/retry_reason.hxx>
|
|
22
23
|
|
|
23
24
|
#include <memory>
|
|
24
25
|
#include <optional>
|
|
25
26
|
#include <system_error>
|
|
26
27
|
|
|
28
|
+
namespace couchbase::core::mcbp
|
|
29
|
+
{
|
|
30
|
+
class queue_request;
|
|
31
|
+
} // namespace couchbase::core::mcbp
|
|
32
|
+
|
|
27
33
|
namespace couchbase::core
|
|
28
34
|
{
|
|
29
35
|
namespace io
|
|
30
36
|
{
|
|
31
37
|
struct mcbp_message;
|
|
38
|
+
class mcbp_session;
|
|
32
39
|
} // namespace io
|
|
33
|
-
namespace mcbp
|
|
34
|
-
{
|
|
35
|
-
class queue_request;
|
|
36
|
-
} // namespace mcbp
|
|
37
40
|
|
|
41
|
+
/**
|
|
42
|
+
* Interface for handling MCBP (Memcached Binary Protocol) responses dispatched by
|
|
43
|
+
* @ref io::mcbp_session.
|
|
44
|
+
*
|
|
45
|
+
* Implementors receive the decoded response together with enough context to populate
|
|
46
|
+
* dispatch tracing spans and key-value error contexts without holding a long-lived
|
|
47
|
+
* reference to the session.
|
|
48
|
+
*
|
|
49
|
+
* @note Adding, removing, or reordering parameters of @ref handle_response is an ABI
|
|
50
|
+
* breaking change for any out-of-tree implementors of this interface.
|
|
51
|
+
*/
|
|
38
52
|
class response_handler
|
|
39
53
|
{
|
|
40
54
|
public:
|
|
55
|
+
response_handler() = default;
|
|
56
|
+
response_handler(const response_handler&) = default;
|
|
57
|
+
response_handler(response_handler&&) = delete;
|
|
58
|
+
auto operator=(const response_handler&) -> response_handler& = default;
|
|
59
|
+
auto operator=(response_handler&&) -> response_handler& = delete;
|
|
41
60
|
virtual ~response_handler() = default;
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Called by @ref io::mcbp_session when a queued request completes (successfully or with
|
|
64
|
+
* an error).
|
|
65
|
+
*
|
|
66
|
+
* @param request The originating request. May be empty when the session is shutting
|
|
67
|
+
* down and synthetically cancels in-flight operations.
|
|
68
|
+
* @param session A snapshot of the session that delivered the response, carrying
|
|
69
|
+
* connection metadata (remote/local address and port) needed to populate
|
|
70
|
+
* dispatch tracing spans and error contexts. Used by
|
|
71
|
+
* @ref crud_component (CXXCBC-798) to build
|
|
72
|
+
* @ref key_value_error_context without retaining a live session reference.
|
|
73
|
+
* @param error Transport-level or protocol-level error code; empty on success.
|
|
74
|
+
* @param reason Retry classification hint supplied by the session.
|
|
75
|
+
* @param msg The raw decoded MCBP response message.
|
|
76
|
+
* @param error_info Optional extended error information from the server's error map.
|
|
77
|
+
*/
|
|
42
78
|
virtual void handle_response(std::shared_ptr<mcbp::queue_request> request,
|
|
79
|
+
std::optional<io::mcbp_session> session,
|
|
43
80
|
std::error_code error,
|
|
44
81
|
retry_reason reason,
|
|
45
82
|
io::mcbp_message msg,
|