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,380 @@
|
|
|
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 <couchbase/error_codes.hxx>
|
|
19
|
+
#include <couchbase/query_meta_data.hxx>
|
|
20
|
+
#include <couchbase/query_metrics.hxx>
|
|
21
|
+
#include <couchbase/query_status.hxx>
|
|
22
|
+
#include <couchbase/query_stream_result.hxx>
|
|
23
|
+
#include <couchbase/query_warning.hxx>
|
|
24
|
+
|
|
25
|
+
#include "core/operations/document_query.hxx"
|
|
26
|
+
#include "core/utils/binary.hxx"
|
|
27
|
+
|
|
28
|
+
#include "error.hxx"
|
|
29
|
+
#include "internal_query_stream_result.hxx"
|
|
30
|
+
#include "observability_recorder.hxx"
|
|
31
|
+
#include "query.hxx"
|
|
32
|
+
|
|
33
|
+
#include <future>
|
|
34
|
+
#include <memory>
|
|
35
|
+
#include <mutex>
|
|
36
|
+
#include <optional>
|
|
37
|
+
#include <string>
|
|
38
|
+
#include <system_error>
|
|
39
|
+
#include <utility>
|
|
40
|
+
#include <vector>
|
|
41
|
+
|
|
42
|
+
namespace couchbase
|
|
43
|
+
{
|
|
44
|
+
namespace
|
|
45
|
+
{
|
|
46
|
+
auto
|
|
47
|
+
to_binary(const std::string& s) -> codec::binary
|
|
48
|
+
{
|
|
49
|
+
return core::utils::to_binary(s);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
auto
|
|
53
|
+
build_query_meta_data(core::operations::query_response::query_meta_data meta) -> query_meta_data
|
|
54
|
+
{
|
|
55
|
+
std::vector<query_warning> warnings;
|
|
56
|
+
if (meta.warnings) {
|
|
57
|
+
warnings.reserve(meta.warnings->size());
|
|
58
|
+
for (auto& w : *meta.warnings) {
|
|
59
|
+
warnings.emplace_back(w.code, std::move(w.message), w.reason, w.retry);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
std::optional<query_metrics> metrics;
|
|
64
|
+
if (meta.metrics) {
|
|
65
|
+
metrics = query_metrics{
|
|
66
|
+
meta.metrics->elapsed_time, meta.metrics->execution_time, meta.metrics->result_count,
|
|
67
|
+
meta.metrics->result_size, meta.metrics->sort_count, meta.metrics->mutation_count,
|
|
68
|
+
meta.metrics->error_count, meta.metrics->warning_count,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
std::optional<codec::binary> signature;
|
|
73
|
+
if (meta.signature) {
|
|
74
|
+
signature = to_binary(*meta.signature);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
std::optional<codec::binary> profile;
|
|
78
|
+
if (meta.profile) {
|
|
79
|
+
profile = to_binary(*meta.profile);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return query_meta_data{
|
|
83
|
+
std::move(meta.request_id),
|
|
84
|
+
std::move(meta.client_context_id),
|
|
85
|
+
core::impl::map_query_status(std::move(meta.status)),
|
|
86
|
+
std::move(warnings),
|
|
87
|
+
metrics,
|
|
88
|
+
std::move(signature),
|
|
89
|
+
std::move(profile),
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
} // namespace
|
|
93
|
+
|
|
94
|
+
// ---------------------------------------------------------------------------
|
|
95
|
+
// internal_query_stream_result implementation
|
|
96
|
+
// ---------------------------------------------------------------------------
|
|
97
|
+
|
|
98
|
+
internal_query_stream_result::internal_query_stream_result(
|
|
99
|
+
core::query_stream stream,
|
|
100
|
+
std::unique_ptr<core::impl::observability_recorder> obs_rec,
|
|
101
|
+
core::error_context::query ctx)
|
|
102
|
+
: stream_{ std::move(stream) }
|
|
103
|
+
, ctx_{ std::move(ctx) }
|
|
104
|
+
, obs_rec_{ std::move(obs_rec) }
|
|
105
|
+
{
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
internal_query_stream_result::~internal_query_stream_result()
|
|
109
|
+
{
|
|
110
|
+
cancel();
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
void
|
|
114
|
+
internal_query_stream_result::cancel()
|
|
115
|
+
{
|
|
116
|
+
// Resolve any parked meta_data() futures with a cancellation error so they don't throw
|
|
117
|
+
// broken_promise when the stream is torn down before reaching a natural terminal. Idempotent
|
|
118
|
+
// via terminal_reached_, so a real terminal that already ran is preserved.
|
|
119
|
+
resolve_meta_data(errc::common::request_canceled);
|
|
120
|
+
stream_.cancel();
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
auto
|
|
124
|
+
internal_query_stream_result::signature() const -> std::optional<codec::binary>
|
|
125
|
+
{
|
|
126
|
+
auto raw = stream_.signature();
|
|
127
|
+
if (!raw) {
|
|
128
|
+
return {};
|
|
129
|
+
}
|
|
130
|
+
return to_binary(*raw);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
void
|
|
134
|
+
internal_query_stream_result::resolve_meta_data(std::error_code ec)
|
|
135
|
+
{
|
|
136
|
+
std::pair<error, query_meta_data> value;
|
|
137
|
+
if (ec) {
|
|
138
|
+
// Report the terminal against the request's context with whatever the response said stamped on,
|
|
139
|
+
// so a mid-stream failure carries the same detail (statement, service error, endpoint) as one
|
|
140
|
+
// that never started. A cancellation leaves the service error code and message unset, because
|
|
141
|
+
// the service never reported one, but the envelope parsed so far is still reported as the body:
|
|
142
|
+
// it names the request id the service logs are keyed by, and the buffered path likewise reports
|
|
143
|
+
// whatever body it received.
|
|
144
|
+
auto ctx = ctx_;
|
|
145
|
+
ctx.ec = ec;
|
|
146
|
+
core::apply_error_details(ctx, stream_.error_details());
|
|
147
|
+
value.first = core::impl::make_error(ctx);
|
|
148
|
+
}
|
|
149
|
+
auto core_meta = stream_.meta_data();
|
|
150
|
+
if (core_meta) {
|
|
151
|
+
value.second = build_query_meta_data(std::move(*core_meta));
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
std::vector<std::promise<std::pair<error, query_meta_data>>> to_satisfy;
|
|
155
|
+
{
|
|
156
|
+
const std::scoped_lock lk{ meta_mutex_ };
|
|
157
|
+
if (terminal_reached_) {
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
terminal_reached_ = true;
|
|
161
|
+
terminal_value_ = value;
|
|
162
|
+
to_satisfy = std::move(pending_meta_promises_);
|
|
163
|
+
pending_meta_promises_.clear();
|
|
164
|
+
}
|
|
165
|
+
for (auto& promise : to_satisfy) {
|
|
166
|
+
promise.set_value(value);
|
|
167
|
+
}
|
|
168
|
+
// Reached exactly once (the terminal_reached_ guard above returns on every later call), so the
|
|
169
|
+
// operation is finished here: record the latency metric and end the operation span. ec is the
|
|
170
|
+
// terminal error (falsy on a clean drain, request_canceled on teardown before a natural end).
|
|
171
|
+
if (obs_rec_) {
|
|
172
|
+
obs_rec_->finish(ec);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
auto
|
|
177
|
+
internal_query_stream_result::meta_data() -> std::future<std::pair<error, query_meta_data>>
|
|
178
|
+
{
|
|
179
|
+
const std::scoped_lock lk{ meta_mutex_ };
|
|
180
|
+
std::promise<std::pair<error, query_meta_data>> promise;
|
|
181
|
+
auto future = promise.get_future();
|
|
182
|
+
if (terminal_reached_) {
|
|
183
|
+
promise.set_value(terminal_value_);
|
|
184
|
+
} else {
|
|
185
|
+
pending_meta_promises_.push_back(std::move(promise));
|
|
186
|
+
}
|
|
187
|
+
return future;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
void
|
|
191
|
+
internal_query_stream_result::next(query_row_handler&& handler)
|
|
192
|
+
{
|
|
193
|
+
{
|
|
194
|
+
// Idempotent terminal: once the stream has ended, re-deliver the terminal (clean end or the
|
|
195
|
+
// terminal error) instead of issuing a pull that would block forever on the drained channel.
|
|
196
|
+
const std::scoped_lock lk{ meta_mutex_ };
|
|
197
|
+
if (terminal_reached_) {
|
|
198
|
+
return handler(terminal_value_.first, std::nullopt);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
bool expected = false;
|
|
202
|
+
if (!pull_in_flight_.compare_exchange_strong(expected, true)) {
|
|
203
|
+
// Enforce the single-outstanding-next() contract instead of racing the single-consumer channel.
|
|
204
|
+
return handler(
|
|
205
|
+
error{ errc::common::invalid_argument, "a previous next() call is still in flight" },
|
|
206
|
+
std::nullopt);
|
|
207
|
+
}
|
|
208
|
+
// Capture a strong self so the object outlives an in-flight pull; dropping the public handle
|
|
209
|
+
// mid-pull would otherwise destroy this object before the channel completion runs (use-after-
|
|
210
|
+
// free). The stream is always owned via shared_ptr (make_shared in dispatch_query_stream).
|
|
211
|
+
stream_.next_row([handler = std::move(handler), self = shared_from_this()](
|
|
212
|
+
std::optional<std::string> row, std::error_code ec) mutable {
|
|
213
|
+
if (row.has_value()) {
|
|
214
|
+
// Real row (ec is falsy). Release the pull gate before invoking the handler so it may
|
|
215
|
+
// immediately issue the next pull.
|
|
216
|
+
self->pull_in_flight_.store(false);
|
|
217
|
+
return handler({}, query_row{ to_binary(*row) });
|
|
218
|
+
}
|
|
219
|
+
// Terminal (nullopt row): publish the terminal state and intentionally leave pull_in_flight_
|
|
220
|
+
// set. Every later next() is served by the terminal_reached_ guard (idempotent re-delivery) and
|
|
221
|
+
// must never issue another pull onto the drained channel, so the gate is never reopened — this
|
|
222
|
+
// also backstops a caller that violates the single-outstanding-next() contract from a racing
|
|
223
|
+
// thread before terminal_reached_ becomes visible.
|
|
224
|
+
self->resolve_meta_data(ec);
|
|
225
|
+
if (ec) {
|
|
226
|
+
// Deliver the contextual error resolve_meta_data() has just published rather than building a
|
|
227
|
+
// bare one here. This is the first and usually only observation of a mid-stream terminal, so
|
|
228
|
+
// it has to carry the same diagnostics as every later next() (served by the terminal_reached_
|
|
229
|
+
// guard above) and as meta_data(); constructing a fresh error here would report the one case
|
|
230
|
+
// this class exists to describe with an empty context.
|
|
231
|
+
error terminal_error;
|
|
232
|
+
{
|
|
233
|
+
const std::scoped_lock lk{ self->meta_mutex_ };
|
|
234
|
+
terminal_error = self->terminal_value_.first;
|
|
235
|
+
}
|
|
236
|
+
return handler(std::move(terminal_error), {});
|
|
237
|
+
}
|
|
238
|
+
return handler({}, {});
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// ---------------------------------------------------------------------------
|
|
243
|
+
// query_stream_result public implementation
|
|
244
|
+
// ---------------------------------------------------------------------------
|
|
245
|
+
|
|
246
|
+
query_stream_result::query_stream_result(std::shared_ptr<internal_query_stream_result> internal)
|
|
247
|
+
: internal_{ std::move(internal) }
|
|
248
|
+
{
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
void
|
|
252
|
+
query_stream_result::next(query_row_handler&& handler) const
|
|
253
|
+
{
|
|
254
|
+
if (!internal_) {
|
|
255
|
+
// Empty handle behaves as an immediately-exhausted stream.
|
|
256
|
+
handler(error{}, std::nullopt);
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
259
|
+
return internal_->next(std::move(handler));
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
auto
|
|
263
|
+
query_stream_result::next() const -> std::future<std::pair<error, std::optional<query_row>>>
|
|
264
|
+
{
|
|
265
|
+
auto barrier = std::make_shared<std::promise<std::pair<error, std::optional<query_row>>>>();
|
|
266
|
+
if (!internal_) {
|
|
267
|
+
// Empty handle behaves as an immediately-exhausted stream.
|
|
268
|
+
barrier->set_value({ error{}, std::nullopt });
|
|
269
|
+
return barrier->get_future();
|
|
270
|
+
}
|
|
271
|
+
internal_->next([barrier](const auto& err, const auto& row) mutable {
|
|
272
|
+
barrier->set_value({ err, row });
|
|
273
|
+
});
|
|
274
|
+
return barrier->get_future();
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
auto
|
|
278
|
+
query_stream_result::signature() const -> std::optional<codec::binary>
|
|
279
|
+
{
|
|
280
|
+
if (!internal_) {
|
|
281
|
+
return {};
|
|
282
|
+
}
|
|
283
|
+
return internal_->signature();
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
auto
|
|
287
|
+
query_stream_result::meta_data() const -> std::future<std::pair<error, query_meta_data>>
|
|
288
|
+
{
|
|
289
|
+
if (!internal_) {
|
|
290
|
+
// Empty handle resolves immediately with empty metadata.
|
|
291
|
+
std::promise<std::pair<error, query_meta_data>> p;
|
|
292
|
+
p.set_value({ error{}, query_meta_data{} });
|
|
293
|
+
return p.get_future();
|
|
294
|
+
}
|
|
295
|
+
return internal_->meta_data();
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
void
|
|
299
|
+
query_stream_result::cancel() const
|
|
300
|
+
{
|
|
301
|
+
if (internal_) {
|
|
302
|
+
return internal_->cancel();
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
// ---------------------------------------------------------------------------
|
|
307
|
+
// iterator implementation
|
|
308
|
+
// ---------------------------------------------------------------------------
|
|
309
|
+
|
|
310
|
+
query_stream_result::iterator::iterator(std::shared_ptr<internal_query_stream_result> internal)
|
|
311
|
+
: internal_{ std::move(internal) }
|
|
312
|
+
{
|
|
313
|
+
if (internal_) {
|
|
314
|
+
fetch_item();
|
|
315
|
+
} else {
|
|
316
|
+
// An empty result handle has no rows: the iterator starts already at end.
|
|
317
|
+
terminal_ = true;
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
void
|
|
322
|
+
query_stream_result::iterator::fetch_item()
|
|
323
|
+
{
|
|
324
|
+
auto barrier = std::make_shared<std::promise<std::pair<error, std::optional<query_row>>>>();
|
|
325
|
+
internal_->next([barrier](const error& err, std::optional<query_row> row) mutable {
|
|
326
|
+
barrier->set_value({ err, std::move(row) });
|
|
327
|
+
});
|
|
328
|
+
auto result = barrier->get_future().get();
|
|
329
|
+
if (result.first) {
|
|
330
|
+
// Terminal error: deliver it as one visible element (still != end()) so a range-for loop can
|
|
331
|
+
// observe it; the next increment then advances to true end.
|
|
332
|
+
item_ = { result.first, {} };
|
|
333
|
+
terminal_ = false;
|
|
334
|
+
error_pending_ = true;
|
|
335
|
+
} else if (!result.second.has_value()) {
|
|
336
|
+
// Clean end-of-stream.
|
|
337
|
+
item_ = {};
|
|
338
|
+
terminal_ = true;
|
|
339
|
+
error_pending_ = false;
|
|
340
|
+
} else {
|
|
341
|
+
item_ = { {}, *result.second };
|
|
342
|
+
terminal_ = false;
|
|
343
|
+
error_pending_ = false;
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
auto
|
|
348
|
+
query_stream_result::iterator::operator*() const -> std::pair<error, query_row>
|
|
349
|
+
{
|
|
350
|
+
return item_;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
auto
|
|
354
|
+
query_stream_result::iterator::operator++() -> query_stream_result::iterator&
|
|
355
|
+
{
|
|
356
|
+
if (error_pending_) {
|
|
357
|
+
// The terminal error element has been consumed; advance to end().
|
|
358
|
+
error_pending_ = false;
|
|
359
|
+
item_ = {};
|
|
360
|
+
terminal_ = true;
|
|
361
|
+
return *this;
|
|
362
|
+
}
|
|
363
|
+
fetch_item();
|
|
364
|
+
return *this;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
auto
|
|
368
|
+
query_stream_result::begin() const -> query_stream_result::iterator
|
|
369
|
+
{
|
|
370
|
+
// The iterator constructor treats a null internal handle as an already-drained stream, so an
|
|
371
|
+
// empty result handle yields begin() == end().
|
|
372
|
+
return query_stream_result::iterator{ internal_ };
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
auto
|
|
376
|
+
query_stream_result::end() const -> query_stream_result::end_sentinel
|
|
377
|
+
{
|
|
378
|
+
return {};
|
|
379
|
+
}
|
|
380
|
+
} // namespace couchbase
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2021-Present Couchbase, Inc.
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
#include <couchbase/transactions/transaction_get_multi_replicas_from_preferred_server_group_result.hxx>
|
|
18
|
+
|
|
19
|
+
#include <couchbase/codec/encoded_value.hxx>
|
|
20
|
+
#include <couchbase/error_codes.hxx>
|
|
21
|
+
|
|
22
|
+
#include <cstddef>
|
|
23
|
+
#include <stdexcept>
|
|
24
|
+
#include <string>
|
|
25
|
+
#include <system_error>
|
|
26
|
+
|
|
27
|
+
namespace couchbase::transactions
|
|
28
|
+
{
|
|
29
|
+
auto
|
|
30
|
+
transaction_get_multi_replicas_from_preferred_server_group_result::content_at(
|
|
31
|
+
std::size_t spec_index) const -> const codec::encoded_value&
|
|
32
|
+
{
|
|
33
|
+
if (spec_index >= content_.size()) {
|
|
34
|
+
throw std::invalid_argument("spec index " + std::to_string(spec_index) + " is not valid");
|
|
35
|
+
}
|
|
36
|
+
if (const auto& content = content_[spec_index]; content.has_value()) {
|
|
37
|
+
return content.value();
|
|
38
|
+
}
|
|
39
|
+
throw std::system_error(errc::key_value::document_not_found,
|
|
40
|
+
"document was not found for index " + std::to_string(spec_index));
|
|
41
|
+
}
|
|
42
|
+
} // namespace couchbase::transactions
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2021-Present Couchbase, Inc.
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
#include <couchbase/transactions/transaction_get_multi_result.hxx>
|
|
18
|
+
|
|
19
|
+
#include <couchbase/codec/encoded_value.hxx>
|
|
20
|
+
#include <couchbase/error_codes.hxx>
|
|
21
|
+
|
|
22
|
+
#include <cstddef>
|
|
23
|
+
#include <stdexcept>
|
|
24
|
+
#include <string>
|
|
25
|
+
#include <system_error>
|
|
26
|
+
|
|
27
|
+
namespace couchbase::transactions
|
|
28
|
+
{
|
|
29
|
+
auto
|
|
30
|
+
transaction_get_multi_result::content_at(std::size_t spec_index) const
|
|
31
|
+
-> const codec::encoded_value&
|
|
32
|
+
{
|
|
33
|
+
if (spec_index >= content_.size()) {
|
|
34
|
+
throw std::invalid_argument("spec index " + std::to_string(spec_index) + " is not valid");
|
|
35
|
+
}
|
|
36
|
+
if (const auto& content = content_[spec_index]; content.has_value()) {
|
|
37
|
+
return content.value();
|
|
38
|
+
}
|
|
39
|
+
throw std::system_error(errc::key_value::document_not_found,
|
|
40
|
+
"document was not found for index " + std::to_string(spec_index));
|
|
41
|
+
}
|
|
42
|
+
} // namespace couchbase::transactions
|
|
@@ -18,22 +18,31 @@
|
|
|
18
18
|
#include <couchbase/error_codes.hxx>
|
|
19
19
|
#include <couchbase/query_options.hxx>
|
|
20
20
|
#include <couchbase/transactions/transaction_query_result.hxx>
|
|
21
|
+
|
|
22
|
+
#include <algorithm>
|
|
23
|
+
#include <cctype>
|
|
21
24
|
#include <utility>
|
|
22
25
|
|
|
23
26
|
#include "core/cluster.hxx"
|
|
24
27
|
#include "core/error_context/transaction_op_error_context.hxx"
|
|
28
|
+
#include "core/free_form_http_request.hxx"
|
|
25
29
|
#include "core/operations/document_query.hxx"
|
|
30
|
+
#include "core/query_stream.hxx"
|
|
26
31
|
#include "core/utils/binary.hxx"
|
|
32
|
+
#include "error.hxx"
|
|
33
|
+
#include "internal_query_stream_result.hxx"
|
|
34
|
+
#include "observability_recorder.hxx"
|
|
35
|
+
#include "query.hxx"
|
|
36
|
+
|
|
37
|
+
#include <memory>
|
|
27
38
|
|
|
28
39
|
namespace couchbase::core::impl
|
|
29
40
|
{
|
|
30
|
-
namespace
|
|
31
|
-
{
|
|
32
41
|
auto
|
|
33
|
-
|
|
42
|
+
map_query_status(std::string status) -> query_status
|
|
34
43
|
{
|
|
35
44
|
std::transform(status.cbegin(), status.cend(), status.begin(), [](unsigned char c) {
|
|
36
|
-
return std::tolower(c);
|
|
45
|
+
return static_cast<char>(std::tolower(c));
|
|
37
46
|
});
|
|
38
47
|
if (status == "running") {
|
|
39
48
|
return query_status::running;
|
|
@@ -65,8 +74,10 @@ map_status(std::string status) -> query_status
|
|
|
65
74
|
return query_status::unknown;
|
|
66
75
|
}
|
|
67
76
|
|
|
77
|
+
namespace
|
|
78
|
+
{
|
|
68
79
|
auto
|
|
69
|
-
map_rows(operations::query_response& resp) -> std::vector<codec::binary>
|
|
80
|
+
map_rows(const operations::query_response& resp) -> std::vector<codec::binary>
|
|
70
81
|
{
|
|
71
82
|
std::vector<codec::binary> rows;
|
|
72
83
|
rows.reserve(resp.rows.size());
|
|
@@ -154,7 +165,7 @@ build_result(operations::query_response& resp) -> query_result
|
|
|
154
165
|
query_meta_data{
|
|
155
166
|
std::move(resp.meta.request_id),
|
|
156
167
|
std::move(resp.meta.client_context_id),
|
|
157
|
-
|
|
168
|
+
map_query_status(resp.meta.status),
|
|
158
169
|
map_warnings(resp),
|
|
159
170
|
map_metrics(resp),
|
|
160
171
|
map_signature(resp),
|
|
@@ -201,6 +212,64 @@ build_query_request(std::string statement,
|
|
|
201
212
|
return request;
|
|
202
213
|
}
|
|
203
214
|
|
|
215
|
+
void
|
|
216
|
+
dispatch_query_stream(const core::cluster& core,
|
|
217
|
+
core::operations::query_request request,
|
|
218
|
+
std::unique_ptr<observability_recorder> obs_rec,
|
|
219
|
+
query_stream_handler&& handler)
|
|
220
|
+
{
|
|
221
|
+
if (!request.adhoc) {
|
|
222
|
+
// Prepared statements rely on buffered retry/replay, so they cannot be streamed live. Run the
|
|
223
|
+
// buffered path and replay the already-parsed result through a buffered query_stream — no JSON
|
|
224
|
+
// re-serialization or re-parsing — so callers observe identical semantics to the adhoc path.
|
|
225
|
+
auto& io = core.io_context();
|
|
226
|
+
core.execute(std::move(request),
|
|
227
|
+
[&io, obs_rec = std::move(obs_rec), handler = std::move(handler)](
|
|
228
|
+
operations::query_response resp) mutable {
|
|
229
|
+
if (resp.ctx.ec) {
|
|
230
|
+
// Terminal reached before a handle exists: record the operation metric/span
|
|
231
|
+
// here.
|
|
232
|
+
obs_rec->finish(resp.ctx.ec);
|
|
233
|
+
return handler(make_error(resp.ctx), {});
|
|
234
|
+
}
|
|
235
|
+
auto stream = std::make_shared<core::query_stream>(
|
|
236
|
+
io, std::move(resp.rows), std::move(resp.meta));
|
|
237
|
+
stream->start([obs_rec = std::move(obs_rec),
|
|
238
|
+
handler = std::move(handler),
|
|
239
|
+
stream,
|
|
240
|
+
ctx = std::move(resp.ctx)](std::error_code early_error) mutable {
|
|
241
|
+
if (early_error) {
|
|
242
|
+
obs_rec->finish(early_error);
|
|
243
|
+
ctx.ec = early_error;
|
|
244
|
+
return handler(make_error(ctx), {});
|
|
245
|
+
}
|
|
246
|
+
// Transfer the recorder to the handle; it finishes the operation at the stream
|
|
247
|
+
// terminal. The buffered request's context travels with it, so a terminal
|
|
248
|
+
// error is reported with the same detail the buffered path would have given.
|
|
249
|
+
auto internal = std::make_shared<internal_query_stream_result>(
|
|
250
|
+
std::move(*stream), std::move(obs_rec), std::move(ctx));
|
|
251
|
+
handler({}, query_stream_result{ std::move(internal) });
|
|
252
|
+
});
|
|
253
|
+
});
|
|
254
|
+
return;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
core.query_stream(std::move(request),
|
|
258
|
+
[obs_rec = std::move(obs_rec), handler = std::move(handler)](
|
|
259
|
+
core::query_stream stream, core::error_context::query ctx) mutable {
|
|
260
|
+
if (ctx.ec) {
|
|
261
|
+
obs_rec->finish(ctx.ec);
|
|
262
|
+
return handler(make_error(ctx), {});
|
|
263
|
+
}
|
|
264
|
+
// The context travels with the handle: a terminal error reached later is
|
|
265
|
+
// reported with the same statement/endpoint detail as a failure to start,
|
|
266
|
+
// plus whatever the trailer said.
|
|
267
|
+
auto internal = std::make_shared<internal_query_stream_result>(
|
|
268
|
+
std::move(stream), std::move(obs_rec), std::move(ctx));
|
|
269
|
+
handler({}, query_stream_result{ std::move(internal) });
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
|
|
204
273
|
auto
|
|
205
274
|
build_transaction_query_result(operations::query_response resp,
|
|
206
275
|
std::error_code txn_ec /*defaults to 0*/)
|
|
@@ -222,7 +291,7 @@ build_transaction_query_result(operations::query_response resp,
|
|
|
222
291
|
{ query_meta_data{
|
|
223
292
|
std::move(resp.meta.request_id),
|
|
224
293
|
std::move(resp.meta.client_context_id),
|
|
225
|
-
|
|
294
|
+
map_query_status(resp.meta.status),
|
|
226
295
|
map_warnings(resp),
|
|
227
296
|
map_metrics(resp),
|
|
228
297
|
map_signature(resp),
|
|
@@ -20,9 +20,27 @@
|
|
|
20
20
|
#include "core/operations/document_query.hxx"
|
|
21
21
|
|
|
22
22
|
#include <couchbase/query_options.hxx>
|
|
23
|
+
#include <couchbase/query_status.hxx>
|
|
24
|
+
|
|
25
|
+
#include <memory>
|
|
26
|
+
#include <string>
|
|
27
|
+
|
|
28
|
+
namespace couchbase::core
|
|
29
|
+
{
|
|
30
|
+
class cluster;
|
|
31
|
+
} // namespace couchbase::core
|
|
23
32
|
|
|
24
33
|
namespace couchbase::core::impl
|
|
25
34
|
{
|
|
35
|
+
class observability_recorder;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Maps the N1QL `status` string from a query response onto the public query_status enum. Shared by
|
|
39
|
+
* the buffered result builder and the streaming result handle so there is one source of truth.
|
|
40
|
+
*/
|
|
41
|
+
auto
|
|
42
|
+
map_query_status(std::string status) -> query_status;
|
|
43
|
+
|
|
26
44
|
auto
|
|
27
45
|
build_query_request(std::string statement,
|
|
28
46
|
std::optional<std::string> query_context,
|
|
@@ -32,4 +50,22 @@ build_query_request(std::string statement,
|
|
|
32
50
|
|
|
33
51
|
auto
|
|
34
52
|
build_result(operations::query_response& resp) -> query_result;
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Dispatches a query as a streaming request and resolves the handler with a query_stream_result.
|
|
56
|
+
*
|
|
57
|
+
* Adhoc requests take the lazy streaming path. Prepared statements (request.adhoc == false) are
|
|
58
|
+
* not streamed; they fall back to the buffered query() path and their rows are replayed through an
|
|
59
|
+
* in-memory query_stream so callers observe identical semantics.
|
|
60
|
+
*
|
|
61
|
+
* @param obs_rec the operation's observability recorder. Its operation span is already threaded
|
|
62
|
+
* into request.parent_span by the caller; ownership is transferred to the resulting stream handle,
|
|
63
|
+
* which calls finish() once when the stream reaches its terminal (drained, errored, or cancelled),
|
|
64
|
+
* so the streaming path emits the same operation span + latency metric as the buffered query().
|
|
65
|
+
*/
|
|
66
|
+
void
|
|
67
|
+
dispatch_query_stream(const core::cluster& core,
|
|
68
|
+
core::operations::query_request request,
|
|
69
|
+
std::unique_ptr<observability_recorder> obs_rec,
|
|
70
|
+
query_stream_handler&& handler);
|
|
35
71
|
} // namespace couchbase::core::impl
|