couchbase 3.8.1 → 3.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +2 -2
- data/ext/CMakeLists.txt +16 -1
- data/ext/cache/cpm/{CPM_0.42.0.cmake → CPM_0.43.1.cmake} +18 -2
- data/ext/cache/extconf_include.rb +6 -6
- data/ext/cache/mozilla-ca-bundle.crt +214 -155
- data/ext/cache/mozilla-ca-bundle.sha256 +1 -1
- data/ext/couchbase/CMakeLists.txt +130 -21
- data/ext/couchbase/cmake/APKBUILD.in +25 -4
- data/ext/couchbase/cmake/Bundler.cmake +143 -34
- data/ext/couchbase/cmake/CPM.cmake +126 -12
- data/ext/couchbase/cmake/Cache.cmake +7 -1
- data/ext/couchbase/cmake/CompilerOptions.cmake +1 -1
- data/ext/couchbase/cmake/CompilerWarnings.cmake +17 -6
- data/ext/couchbase/cmake/GrpcProtobuf.cmake +481 -0
- data/ext/couchbase/cmake/OpenSSL.cmake +10 -3
- data/ext/couchbase/cmake/Packaging.cmake +519 -65
- data/ext/couchbase/cmake/Protostellar.cmake +250 -0
- data/ext/couchbase/cmake/Sanitizers.cmake +61 -50
- data/ext/couchbase/cmake/StaticAnalyzers.cmake +16 -5
- data/ext/couchbase/cmake/TestFramework.cmake +283 -0
- data/ext/couchbase/cmake/TestFrameworkAddTests.cmake +51 -0
- data/ext/couchbase/cmake/Testing.cmake +27 -9
- data/ext/couchbase/cmake/ThirdPartyDependencies.cmake +141 -8
- data/ext/couchbase/cmake/VersionInfo.cmake +50 -0
- data/ext/couchbase/cmake/build_config.hxx.in +2 -1
- data/ext/couchbase/cmake/couchbase-cxx-client.spec.in +101 -23
- data/ext/couchbase/cmake/couchbase_cxx_client_static-config.cmake.in +7 -0
- data/ext/couchbase/cmake/couchbase_cxx_client_static.pc.in +2 -0
- data/ext/couchbase/cmake/gRPC_Generate.cmake +58 -0
- data/ext/couchbase/cmake/protobuf_Generate.cmake +69 -0
- data/ext/couchbase/cmake/require-git-checkout.cmake +25 -0
- data/ext/couchbase/cmake/tarball_glob.txt +49 -0
- data/ext/couchbase/core/agent_group.cxx +0 -8
- data/ext/couchbase/core/agent_group.hxx +0 -4
- data/ext/couchbase/core/analytics_stream.cxx +314 -0
- data/ext/couchbase/core/analytics_stream.hxx +129 -0
- data/ext/couchbase/core/analytics_stream_component.cxx +245 -0
- data/ext/couchbase/core/analytics_stream_component.hxx +67 -0
- data/ext/couchbase/core/app_telemetry_meter.cxx +25 -3
- data/ext/couchbase/core/app_telemetry_meter.hxx +77 -0
- data/ext/couchbase/core/app_telemetry_reporter.cxx +7 -6
- data/ext/couchbase/core/bucket.cxx +381 -87
- data/ext/couchbase/core/bucket.hxx +105 -25
- data/ext/couchbase/core/bucket_unit_test_api.hxx +57 -0
- data/ext/couchbase/core/capella.hxx +91 -0
- data/ext/couchbase/core/cluster.cxx +1554 -398
- data/ext/couchbase/core/cluster.hxx +39 -8
- data/ext/couchbase/core/cluster_agent.cxx +0 -8
- data/ext/couchbase/core/cluster_agent.hxx +0 -4
- data/ext/couchbase/core/cluster_options.hxx +26 -3
- data/ext/couchbase/core/collections_component.cxx +39 -15
- data/ext/couchbase/core/config_profiles.cxx +1 -1
- data/ext/couchbase/core/crud_component.cxx +2 -2
- data/ext/couchbase/core/crud_options.hxx +34 -0
- data/ext/couchbase/core/crypto/cbcrypto.cc +18 -13
- data/ext/couchbase/core/document_id_redaction.hxx +81 -0
- data/ext/couchbase/core/error_context/base_error_context.hxx +7 -6
- data/ext/couchbase/core/error_context/key_value.cxx +25 -2
- data/ext/couchbase/core/error_context/key_value.hxx +60 -33
- data/ext/couchbase/core/error_context/key_value_error_context.hxx +16 -15
- data/ext/couchbase/core/error_context/search.hxx +5 -0
- data/ext/couchbase/core/error_context/search_json.hxx +3 -0
- data/ext/couchbase/core/error_context/subdocument_error_context.hxx +19 -18
- data/ext/couchbase/core/error_context/view.hxx +5 -0
- data/ext/couchbase/core/free_form_http_request.cxx +237 -4
- data/ext/couchbase/core/free_form_http_request.hxx +41 -8
- data/ext/couchbase/core/http_component.cxx +300 -284
- data/ext/couchbase/core/http_component.hxx +0 -4
- data/ext/couchbase/core/impl/analytics.cxx +38 -5
- data/ext/couchbase/core/impl/analytics.hxx +34 -0
- data/ext/couchbase/core/impl/bootstrap_error.hxx +0 -3
- data/ext/couchbase/core/impl/collection.cxx +215 -202
- data/ext/couchbase/core/impl/collection_manager.cxx +1 -1
- data/ext/couchbase/core/impl/dns_srv_tracker.cxx +45 -18
- data/ext/couchbase/core/impl/error.cxx +22 -2
- data/ext/couchbase/core/impl/internal_analytics_stream_result.hxx +111 -0
- data/ext/couchbase/core/impl/internal_query_stream_result.hxx +110 -0
- data/ext/couchbase/core/impl/invoke_with_node_id.hxx +15 -7
- data/ext/couchbase/core/impl/key_value_error_category.cxx +6 -0
- data/ext/couchbase/core/impl/lookup_in_replica.cxx +10 -10
- data/ext/couchbase/core/impl/lookup_in_replica.hxx +4 -4
- data/ext/couchbase/core/impl/node_id.cxx +49 -13
- data/ext/couchbase/core/impl/observability_recorder.cxx +12 -2
- data/ext/couchbase/core/impl/observe_poll.cxx +63 -23
- data/ext/couchbase/core/impl/public_analytics_stream_result.cxx +372 -0
- data/ext/couchbase/core/impl/public_bucket.cxx +48 -2
- data/ext/couchbase/core/impl/public_cluster.cxx +325 -25
- data/ext/couchbase/core/impl/public_query_stream_result.cxx +380 -0
- data/ext/couchbase/core/impl/public_transaction_get_multi_replicas_from_preferred_server_group_result.cxx +42 -0
- data/ext/couchbase/core/impl/public_transaction_get_multi_result.cxx +42 -0
- data/ext/couchbase/core/impl/query.cxx +76 -7
- data/ext/couchbase/core/impl/query.hxx +36 -0
- data/ext/couchbase/core/impl/query_index_manager.cxx +54 -1
- data/ext/couchbase/core/impl/replica_utils.cxx +101 -0
- data/ext/couchbase/core/impl/replica_utils.hxx +64 -0
- data/ext/couchbase/core/impl/resolve_node_id.hxx +125 -0
- data/ext/couchbase/core/impl/scope.cxx +70 -0
- data/ext/couchbase/core/impl/search.cxx +31 -1
- data/ext/couchbase/core/impl/transactions.cxx +130 -0
- data/ext/couchbase/core/impl/wait_until_ready.cxx +439 -0
- data/ext/couchbase/core/impl/wait_until_ready.hxx +110 -0
- data/ext/couchbase/core/impl/with_bucket_config_or_timeout.hxx +180 -0
- data/ext/couchbase/core/impl/with_cancellation.hxx +11 -3
- data/ext/couchbase/core/io/configuration_belongs_to_session.hxx +66 -0
- data/ext/couchbase/core/io/dns_client.cxx +122 -45
- data/ext/couchbase/core/io/dns_codec.hxx +21 -21
- data/ext/couchbase/core/io/dns_config.cxx +21 -6
- data/ext/couchbase/core/io/http_command.hxx +149 -121
- data/ext/couchbase/core/io/http_error.hxx +107 -0
- data/ext/couchbase/core/io/http_parser.cxx +4 -0
- data/ext/couchbase/core/io/http_session.cxx +606 -154
- data/ext/couchbase/core/io/http_session.hxx +147 -30
- data/ext/couchbase/core/io/http_session_manager.hxx +329 -382
- data/ext/couchbase/core/io/http_streaming_parser.cxx +4 -0
- data/ext/couchbase/core/io/http_streaming_response.cxx +328 -43
- data/ext/couchbase/core/io/http_streaming_response.hxx +37 -3
- data/ext/couchbase/core/io/mcbp_buffer_pool.hxx +122 -0
- data/ext/couchbase/core/io/mcbp_command.hxx +150 -51
- data/ext/couchbase/core/io/mcbp_command_id.hxx +45 -0
- data/ext/couchbase/core/io/mcbp_message.cxx +9 -1
- data/ext/couchbase/core/io/mcbp_message.hxx +19 -0
- data/ext/couchbase/core/io/mcbp_output_queue.hxx +150 -0
- data/ext/couchbase/core/io/mcbp_parser.cxx +24 -7
- data/ext/couchbase/core/io/mcbp_session.cxx +316 -317
- data/ext/couchbase/core/io/mcbp_session.hxx +27 -18
- data/ext/couchbase/core/io/opaque_ring_table.hxx +145 -0
- data/ext/couchbase/core/io/retry_orchestrator.hxx +6 -5
- data/ext/couchbase/core/io/stream_deadline.hxx +50 -0
- data/ext/couchbase/core/io/streams.cxx +275 -14
- data/ext/couchbase/core/io/streams.hxx +53 -0
- data/ext/couchbase/core/logger/logger.cxx +36 -0
- data/ext/couchbase/core/logger/logger.hxx +46 -6
- data/ext/couchbase/core/logger/redaction.hxx +503 -0
- data/ext/couchbase/core/management/eventing_status.hxx +10 -0
- data/ext/couchbase/core/management/eventing_status_json.hxx +4 -0
- data/ext/couchbase/core/mcbp/big_endian.cxx +1 -1
- data/ext/couchbase/core/mcbp/codec.cxx +27 -18
- data/ext/couchbase/core/mcbp/operation_queue.cxx +2 -2
- data/ext/couchbase/core/mcbp/packet.hxx +2 -2
- data/ext/couchbase/core/mcbp/queue_request.cxx +23 -6
- data/ext/couchbase/core/mcbp/queue_request.hxx +21 -0
- data/ext/couchbase/core/meta/features.hxx +13 -0
- data/ext/couchbase/core/meta/version.cxx +6 -3
- data/ext/couchbase/core/metrics/logging_meter.cxx +5 -10
- data/ext/couchbase/core/metrics/meter_wrapper.cxx +63 -33
- data/ext/couchbase/core/metrics/meter_wrapper.hxx +55 -3
- data/ext/couchbase/core/operations/analytics_response_parsing.cxx +177 -0
- data/ext/couchbase/core/operations/analytics_response_parsing.hxx +55 -0
- data/ext/couchbase/core/operations/document_analytics.cxx +48 -130
- data/ext/couchbase/core/operations/document_analytics.hxx +14 -2
- data/ext/couchbase/core/operations/document_get_all_replicas.hxx +15 -7
- data/ext/couchbase/core/operations/document_get_any_replica.hxx +19 -8
- data/ext/couchbase/core/operations/document_get_projected.cxx +1 -1
- data/ext/couchbase/core/{impl/get_replica.cxx → operations/document_get_replica.cxx} +21 -3
- data/ext/couchbase/core/{impl/get_replica.hxx → operations/document_get_replica.hxx} +31 -4
- data/ext/couchbase/core/operations/document_lookup_in.cxx +10 -10
- data/ext/couchbase/core/operations/document_lookup_in_all_replicas.hxx +228 -198
- data/ext/couchbase/core/operations/document_lookup_in_any_replica.hxx +215 -217
- data/ext/couchbase/core/operations/document_query.cxx +108 -221
- data/ext/couchbase/core/operations/document_query.hxx +18 -4
- data/ext/couchbase/core/operations/document_search.cxx +52 -8
- data/ext/couchbase/core/operations/document_search.hxx +3 -0
- data/ext/couchbase/core/operations/document_view.cxx +3 -3
- data/ext/couchbase/core/operations/management/analytics_dataset_create.cxx +15 -8
- data/ext/couchbase/core/operations/management/analytics_dataset_create.hxx +4 -0
- data/ext/couchbase/core/operations/management/analytics_dataset_drop.cxx +11 -6
- data/ext/couchbase/core/operations/management/analytics_dataset_get_all.cxx +3 -2
- data/ext/couchbase/core/operations/management/analytics_dataverse_create.cxx +10 -5
- data/ext/couchbase/core/operations/management/analytics_dataverse_drop.cxx +10 -5
- data/ext/couchbase/core/operations/management/analytics_get_pending_mutations.cxx +2 -1
- data/ext/couchbase/core/operations/management/analytics_index_create.cxx +33 -8
- data/ext/couchbase/core/operations/management/analytics_index_drop.cxx +12 -7
- data/ext/couchbase/core/operations/management/analytics_index_get_all.cxx +3 -2
- data/ext/couchbase/core/operations/management/analytics_link_connect.cxx +11 -6
- data/ext/couchbase/core/operations/management/analytics_link_create.cxx +3 -3
- data/ext/couchbase/core/operations/management/analytics_link_disconnect.cxx +10 -4
- data/ext/couchbase/core/operations/management/analytics_link_drop.cxx +6 -4
- data/ext/couchbase/core/operations/management/analytics_link_get_all.cxx +4 -3
- data/ext/couchbase/core/operations/management/analytics_link_replace.cxx +3 -3
- data/ext/couchbase/core/operations/management/analytics_link_utils.hxx +1 -1
- data/ext/couchbase/core/operations/management/bucket_create.cxx +37 -38
- data/ext/couchbase/core/operations/management/bucket_update.cxx +26 -28
- data/ext/couchbase/core/operations/management/change_password.cxx +2 -0
- data/ext/couchbase/core/operations/management/collection_drop.cxx +5 -1
- data/ext/couchbase/core/operations/management/error_utils.cxx +59 -5
- data/ext/couchbase/core/operations/management/error_utils.hxx +29 -1
- data/ext/couchbase/core/operations/management/eventing_deploy_function.cxx +9 -3
- data/ext/couchbase/core/operations/management/eventing_drop_function.cxx +8 -3
- data/ext/couchbase/core/operations/management/eventing_get_all_functions.cxx +4 -2
- data/ext/couchbase/core/operations/management/eventing_get_function.cxx +5 -3
- data/ext/couchbase/core/operations/management/eventing_get_status.cxx +4 -2
- data/ext/couchbase/core/operations/management/eventing_pause_function.cxx +9 -3
- data/ext/couchbase/core/operations/management/eventing_resume_function.cxx +9 -3
- data/ext/couchbase/core/operations/management/eventing_undeploy_function.cxx +9 -3
- data/ext/couchbase/core/operations/management/eventing_upsert_function.cxx +9 -3
- data/ext/couchbase/core/operations/management/group_drop.cxx +3 -1
- data/ext/couchbase/core/operations/management/group_get.cxx +3 -1
- data/ext/couchbase/core/operations/management/group_upsert.cxx +11 -8
- data/ext/couchbase/core/operations/management/query_index_build.cxx +5 -2
- data/ext/couchbase/core/operations/management/query_index_create.cxx +9 -3
- data/ext/couchbase/core/operations/management/query_index_drop.cxx +11 -4
- data/ext/couchbase/core/operations/management/query_index_get_all.cxx +1 -1
- data/ext/couchbase/core/operations/management/query_index_get_all_deferred.cxx +1 -1
- data/ext/couchbase/core/operations/management/scope_drop.cxx +5 -1
- data/ext/couchbase/core/operations/management/scope_get_all.cxx +6 -1
- data/ext/couchbase/core/operations/management/search_get_stats.cxx +10 -0
- data/ext/couchbase/core/operations/management/search_index_analyze_document.cxx +3 -2
- data/ext/couchbase/core/operations/management/search_index_control_ingest.cxx +4 -3
- data/ext/couchbase/core/operations/management/search_index_control_plan_freeze.cxx +4 -3
- data/ext/couchbase/core/operations/management/search_index_control_query.cxx +4 -3
- data/ext/couchbase/core/operations/management/search_index_drop.cxx +2 -2
- data/ext/couchbase/core/operations/management/search_index_get.cxx +2 -2
- data/ext/couchbase/core/operations/management/search_index_get_documents_count.cxx +3 -2
- data/ext/couchbase/core/operations/management/search_index_get_stats.cxx +3 -1
- data/ext/couchbase/core/operations/management/search_index_upsert.cxx +2 -2
- data/ext/couchbase/core/operations/management/user_drop.cxx +3 -1
- data/ext/couchbase/core/operations/management/user_get.cxx +3 -1
- data/ext/couchbase/core/operations/management/user_upsert.cxx +12 -9
- data/ext/couchbase/core/operations/management/view_index_drop.cxx +1 -1
- data/ext/couchbase/core/operations/management/view_index_get.cxx +1 -1
- data/ext/couchbase/core/operations/management/view_index_upsert.cxx +1 -1
- data/ext/couchbase/core/operations/operation_traits.hxx +18 -0
- data/ext/couchbase/core/operations/query_response_parsing.cxx +211 -0
- data/ext/couchbase/core/operations/query_response_parsing.hxx +60 -0
- data/ext/couchbase/core/operations_fwd.hxx +3 -3
- data/ext/couchbase/core/origin.cxx +54 -26
- data/ext/couchbase/core/origin.hxx +12 -0
- data/ext/couchbase/core/orphan_reporter.cxx +2 -1
- data/ext/couchbase/core/platform/random.cc +7 -7
- data/ext/couchbase/core/protocol/client_request.cxx +2 -2
- data/ext/couchbase/core/protocol/client_request.hxx +38 -21
- data/ext/couchbase/core/protocol/client_response.cxx +11 -3
- data/ext/couchbase/core/protocol/client_response.hxx +27 -6
- data/ext/couchbase/core/protocol/cmd_append.cxx +2 -2
- data/ext/couchbase/core/protocol/cmd_cluster_map_change_notification.cxx +2 -2
- data/ext/couchbase/core/protocol/cmd_decrement.cxx +6 -6
- data/ext/couchbase/core/protocol/cmd_get.cxx +1 -1
- data/ext/couchbase/core/protocol/cmd_get_and_lock.cxx +2 -2
- data/ext/couchbase/core/protocol/cmd_get_and_touch.cxx +2 -2
- data/ext/couchbase/core/protocol/cmd_get_cluster_config.cxx +6 -4
- data/ext/couchbase/core/protocol/cmd_get_collection_id.cxx +2 -2
- data/ext/couchbase/core/protocol/cmd_get_error_map.cxx +1 -1
- data/ext/couchbase/core/protocol/cmd_get_meta.cxx +4 -4
- data/ext/couchbase/core/protocol/cmd_get_replica.cxx +1 -1
- data/ext/couchbase/core/protocol/cmd_hello.cxx +1 -1
- data/ext/couchbase/core/protocol/cmd_increment.cxx +6 -6
- data/ext/couchbase/core/protocol/cmd_insert.cxx +4 -4
- data/ext/couchbase/core/protocol/cmd_lookup_in.cxx +4 -3
- data/ext/couchbase/core/protocol/cmd_lookup_in_replica.cxx +4 -3
- data/ext/couchbase/core/protocol/cmd_mutate_in.cxx +10 -9
- data/ext/couchbase/core/protocol/cmd_mutate_in.hxx +10 -10
- data/ext/couchbase/core/protocol/cmd_observe_seqno.cxx +7 -7
- data/ext/couchbase/core/protocol/cmd_prepend.cxx +2 -2
- data/ext/couchbase/core/protocol/cmd_remove.cxx +2 -2
- data/ext/couchbase/core/protocol/cmd_replace.cxx +4 -4
- data/ext/couchbase/core/protocol/cmd_touch.cxx +1 -1
- data/ext/couchbase/core/protocol/cmd_upsert.cxx +4 -4
- data/ext/couchbase/core/protocol/datatype.hxx +118 -1
- data/ext/couchbase/core/protocol/frame_info_utils.cxx +1 -1
- data/ext/couchbase/core/protocol/magic.hxx +4 -0
- data/ext/couchbase/core/protocol/magic_fmt.hxx +3 -0
- data/ext/couchbase/core/protocol/server_request.hxx +3 -1
- data/ext/couchbase/core/protocol/status.cxx +1 -1
- data/ext/couchbase/core/protostellar/analytics_converter.hxx +171 -0
- data/ext/couchbase/core/protostellar/bucket_admin_converter.hxx +301 -0
- data/ext/couchbase/core/protostellar/collection_admin_converter.hxx +92 -0
- data/ext/couchbase/core/protostellar/component.cxx +2445 -0
- data/ext/couchbase/core/protostellar/component.hxx +391 -0
- data/ext/couchbase/core/{columnar/bootstrap_notification_subscriber.hxx → protostellar/compression_settings.hxx} +11 -10
- data/ext/couchbase/core/protostellar/credentials.cxx +233 -0
- data/ext/couchbase/core/protostellar/credentials.hxx +88 -0
- data/ext/couchbase/core/protostellar/dispatcher.cxx +57 -0
- data/ext/couchbase/core/protostellar/dispatcher.hxx +482 -0
- data/ext/couchbase/core/protostellar/error_utils.cxx +293 -0
- data/ext/couchbase/core/protostellar/error_utils.hxx +97 -0
- data/ext/couchbase/core/protostellar/json_payload.hxx +49 -0
- data/ext/couchbase/core/protostellar/kv_converter.cxx +70 -0
- data/ext/couchbase/core/protostellar/kv_converter.hxx +600 -0
- data/ext/couchbase/core/protostellar/query_converter.hxx +265 -0
- data/ext/couchbase/core/protostellar/query_index_admin_converter.hxx +291 -0
- data/ext/couchbase/core/protostellar/query_proto.hxx +73 -0
- data/ext/couchbase/core/protostellar/search_converter.hxx +244 -0
- data/ext/couchbase/core/protostellar/search_index_admin_converter.hxx +156 -0
- data/ext/couchbase/core/protostellar/view_converter.hxx +158 -0
- data/ext/couchbase/core/query_stream.cxx +447 -0
- data/ext/couchbase/core/query_stream.hxx +141 -0
- data/ext/couchbase/core/query_stream_component.cxx +243 -0
- data/ext/couchbase/core/query_stream_component.hxx +68 -0
- data/ext/couchbase/core/range_scan_load_balancer.cxx +15 -8
- data/ext/couchbase/core/range_scan_orchestrator.cxx +15 -3
- data/ext/couchbase/core/response_handler.hxx +41 -4
- data/ext/couchbase/core/row_streamer.cxx +332 -46
- data/ext/couchbase/core/row_streamer.hxx +31 -1
- data/ext/couchbase/core/row_streamer_options.hxx +55 -0
- data/ext/couchbase/core/sasl/client.h +3 -0
- data/ext/couchbase/core/search_scoring.hxx +66 -0
- data/ext/couchbase/core/stream_error_details.hxx +69 -0
- data/ext/couchbase/core/timeout_defaults.hxx +0 -1
- data/ext/couchbase/core/topology/capabilities.hxx +6 -0
- data/ext/couchbase/core/topology/capabilities_fmt.hxx +3 -0
- data/ext/couchbase/core/topology/configuration.cxx +21 -6
- data/ext/couchbase/core/topology/configuration.hxx +29 -8
- data/ext/couchbase/core/topology/configuration_json.hxx +3 -0
- data/ext/couchbase/core/topology/error_map_json.hxx +3 -1
- data/ext/couchbase/core/tracing/threshold_logging_tracer.cxx +70 -4
- data/ext/couchbase/core/tracing/threshold_logging_tracer.hxx +10 -0
- data/ext/couchbase/core/transactions/active_transaction_record.cxx +0 -34
- data/ext/couchbase/core/transactions/attempt_context_impl.cxx +362 -241
- data/ext/couchbase/core/transactions/attempt_context_impl.hxx +24 -3
- data/ext/couchbase/core/transactions/error_list.hxx +2 -2
- data/ext/couchbase/core/transactions/get_multi_fetch.hxx +160 -0
- data/ext/couchbase/core/transactions/get_multi_orchestrator.cxx +326 -125
- data/ext/couchbase/core/transactions/get_multi_transaction_id.hxx +62 -0
- data/ext/couchbase/core/transactions/internal/atr_entry.hxx +22 -2
- data/ext/couchbase/core/transactions/internal/transaction_context.hxx +2 -2
- data/ext/couchbase/core/transactions/internal/transactions_cleanup.hxx +23 -1
- data/ext/couchbase/core/transactions/internal/utils.hxx +50 -14
- data/ext/couchbase/core/transactions/staged_mutation.cxx +23 -18
- data/ext/couchbase/core/transactions/staged_mutation.hxx +15 -4
- data/ext/couchbase/core/transactions/transaction_context.cxx +55 -40
- data/ext/couchbase/core/transactions/transaction_get_result.hxx +16 -0
- data/ext/couchbase/core/transactions/transactions.cxx +3 -55
- data/ext/couchbase/core/transactions/transactions_cleanup.cxx +194 -66
- data/ext/couchbase/core/transactions/transactions_config.cxx +0 -11
- data/ext/couchbase/core/transactions/utils.cxx +10 -0
- data/ext/couchbase/core/transactions/waitable_op_list.hxx +15 -4
- data/ext/couchbase/core/transactions.hxx +9 -9
- data/ext/couchbase/core/utils/byteswap.hxx +166 -9
- data/ext/couchbase/core/utils/connection_string.cxx +50 -85
- data/ext/couchbase/core/utils/connection_string.hxx +15 -0
- data/ext/couchbase/core/{columnar/backoff_calculator.hxx → utils/deadline.hxx} +13 -13
- data/ext/couchbase/core/utils/duration_parser.cxx +1 -1
- data/ext/couchbase/core/utils/json_streaming_lexer.cxx +48 -5
- data/ext/couchbase/core/utils/json_streaming_lexer.hxx +4 -1
- data/ext/couchbase/core/utils/movable_function.hxx +301 -52
- data/ext/couchbase/core/utils/name_codec.hxx +154 -11
- data/ext/couchbase/core/{columnar/retry_info.hxx → utils/process_id.hxx} +18 -13
- data/ext/couchbase/core/utils/url_codec.cxx +12 -51
- data/ext/couchbase/core/websocket_codec.cxx +3 -29
- data/ext/couchbase/couchbase/analytics_options.hxx +21 -10
- data/ext/couchbase/couchbase/analytics_row.hxx +105 -0
- data/ext/couchbase/couchbase/analytics_stream_result.hxx +266 -0
- data/ext/couchbase/couchbase/boolean_query.hxx +3 -3
- data/ext/couchbase/couchbase/bucket.hxx +57 -0
- data/ext/couchbase/couchbase/cluster.hxx +216 -5
- data/ext/couchbase/{core/columnar/security_options.hxx → couchbase/cluster_state.hxx} +18 -14
- data/ext/couchbase/couchbase/codec/lenient_json_transcoder.hxx +69 -0
- data/ext/couchbase/couchbase/collection.hxx +234 -14
- data/ext/couchbase/couchbase/common_durability_options.hxx +18 -3
- data/ext/couchbase/couchbase/conjunction_query.hxx +1 -1
- data/ext/couchbase/couchbase/create_dataset_analytics_options.hxx +6 -1
- data/ext/couchbase/couchbase/date_range_query.hxx +2 -2
- data/ext/couchbase/couchbase/decrement_options.hxx +1 -1
- data/ext/couchbase/couchbase/disjunction_query.hxx +1 -1
- data/ext/couchbase/couchbase/error.hxx +32 -0
- data/ext/couchbase/couchbase/error_codes.hxx +32 -0
- data/ext/couchbase/couchbase/geo_bounding_box_query.hxx +1 -1
- data/ext/couchbase/couchbase/geo_distance_query.hxx +1 -1
- data/ext/couchbase/couchbase/geo_polygon_query.hxx +1 -1
- data/ext/couchbase/couchbase/get_replica_options.hxx +68 -0
- data/ext/couchbase/couchbase/get_replica_result.hxx +5 -3
- data/ext/couchbase/couchbase/get_replica_strategy.hxx +161 -0
- data/ext/couchbase/couchbase/get_result.hxx +1 -0
- data/ext/couchbase/couchbase/increment_options.hxx +1 -1
- data/ext/couchbase/couchbase/insert_options.hxx +1 -1
- data/ext/couchbase/couchbase/match_phrase_query.hxx +1 -1
- data/ext/couchbase/couchbase/match_query.hxx +1 -1
- data/ext/couchbase/couchbase/mutate_in_options.hxx +3 -3
- data/ext/couchbase/couchbase/network_options.hxx +1 -1
- data/ext/couchbase/couchbase/node_id.hxx +42 -14
- data/ext/couchbase/couchbase/node_id_for_options.hxx +7 -1
- data/ext/couchbase/couchbase/node_ids_options.hxx +8 -2
- data/ext/couchbase/couchbase/numeric_range_query.hxx +1 -1
- data/ext/couchbase/couchbase/phrase_query.hxx +1 -1
- data/ext/couchbase/couchbase/prefix_query.hxx +1 -1
- data/ext/couchbase/couchbase/query_options.hxx +23 -12
- data/ext/couchbase/couchbase/query_row.hxx +111 -0
- data/ext/couchbase/couchbase/query_stream_result.hxx +302 -0
- data/ext/couchbase/couchbase/query_string_query.hxx +3 -3
- data/ext/couchbase/couchbase/regexp_query.hxx +1 -1
- data/ext/couchbase/couchbase/replace_options.hxx +3 -3
- data/ext/couchbase/couchbase/result.hxx +14 -3
- data/ext/couchbase/couchbase/scan_result_item.hxx +1 -0
- data/ext/couchbase/couchbase/scope.hxx +85 -2
- data/ext/couchbase/couchbase/search_options.hxx +58 -8
- data/ext/couchbase/couchbase/search_scoring.hxx +94 -0
- data/ext/couchbase/couchbase/search_scoring_none.hxx +51 -0
- data/ext/couchbase/couchbase/search_scoring_reciprocal_rank_fusion.hxx +88 -0
- data/ext/couchbase/couchbase/search_scoring_relative_score_fusion.hxx +70 -0
- data/ext/couchbase/couchbase/term_range_query.hxx +1 -1
- data/ext/couchbase/couchbase/tracing/request_span.hxx +46 -0
- data/ext/couchbase/couchbase/transactions/transaction_get_multi_replicas_from_preferred_server_group_result.hxx +23 -21
- data/ext/couchbase/couchbase/transactions/transaction_get_multi_result.hxx +24 -19
- data/ext/couchbase/couchbase/transactions/transaction_get_result.hxx +17 -3
- data/ext/couchbase/couchbase/transactions/transactions_config.hxx +4 -2
- data/ext/couchbase/couchbase/transactions.hxx +27 -18
- data/ext/couchbase/couchbase/upsert_options.hxx +3 -3
- data/ext/couchbase/couchbase/vector_query.hxx +1 -1
- data/ext/couchbase/couchbase/wait_until_ready_options.hxx +111 -0
- data/ext/couchbase/couchbase/wildcard_query.hxx +1 -1
- data/ext/extconf.rb +15 -10
- data/ext/rcb_analytics.cxx +82 -102
- data/ext/rcb_backend.cxx +42 -36
- data/ext/rcb_backend.hxx +2 -0
- data/ext/rcb_buckets.cxx +47 -59
- data/ext/rcb_collections.cxx +42 -52
- data/ext/rcb_crud.cxx +345 -224
- data/ext/rcb_diagnostics.cxx +117 -27
- data/ext/rcb_exceptions.cxx +152 -99
- data/ext/rcb_exceptions.hxx +25 -0
- data/ext/rcb_extras.cxx +18 -19
- data/ext/rcb_hdr_histogram.cxx +19 -4
- data/ext/rcb_logger.cxx +202 -27
- data/ext/rcb_logger.hxx +12 -0
- data/ext/rcb_multi.cxx +40 -40
- data/ext/rcb_observability.cxx +7 -5
- data/ext/rcb_query.cxx +99 -142
- data/ext/rcb_range_scan.cxx +41 -35
- data/ext/rcb_search.cxx +98 -99
- data/ext/rcb_users.cxx +36 -56
- data/ext/rcb_utils.cxx +100 -37
- data/ext/rcb_utils.hxx +287 -33
- data/ext/rcb_version.cxx +1 -1
- data/ext/rcb_views.cxx +55 -51
- data/lib/active_support/cache/couchbase_store.rb +77 -12
- data/lib/couchbase/bucket.rb +20 -0
- data/lib/couchbase/cluster.rb +33 -14
- data/lib/couchbase/collection.rb +36 -1
- data/lib/couchbase/errors.rb +18 -0
- data/lib/couchbase/fork_hooks.rb +16 -7
- data/lib/couchbase/get_replica_strategy.rb +89 -0
- data/lib/couchbase/logger.rb +1 -1
- data/lib/couchbase/management/analytics_index_manager.rb +15 -15
- data/lib/couchbase/management/bucket_manager.rb +6 -6
- data/lib/couchbase/management/collection_manager.rb +6 -6
- data/lib/couchbase/management/query_index_manager.rb +7 -7
- data/lib/couchbase/management/search_index_manager.rb +13 -13
- data/lib/couchbase/management/user_manager.rb +10 -10
- data/lib/couchbase/management/view_index_manager.rb +5 -5
- data/lib/couchbase/options.rb +181 -44
- data/lib/couchbase/protostellar/bucket.rb +4 -0
- data/lib/couchbase/protostellar/cluster.rb +4 -0
- data/lib/couchbase/protostellar/collection.rb +4 -0
- data/lib/couchbase/protostellar/error_handling.rb +2 -1
- data/lib/couchbase/protostellar/request.rb +1 -0
- data/lib/couchbase/protostellar/request_generator/kv.rb +16 -2
- data/lib/couchbase/protostellar/request_generator/search.rb +17 -1
- data/lib/couchbase/protostellar/retry/orchestrator.rb +3 -2
- data/lib/couchbase/protostellar/retry/strategies/fail_fast.rb +33 -0
- data/lib/couchbase/protostellar/retry/strategies.rb +1 -0
- data/lib/couchbase/search_options.rb +95 -6
- data/lib/couchbase/version.rb +1 -1
- metadata +92 -33
- data/ext/0001-fix-build-for-mingw-w64-ucrt-x86_64-toolchain.patch +0 -40
- data/ext/couchbase/core/columnar/agent.hxx +0 -71
- data/ext/couchbase/core/columnar/agent_config.hxx +0 -59
- data/ext/couchbase/core/columnar/background_bootstrap_listener.hxx +0 -42
- data/ext/couchbase/core/columnar/backoff_calculator.cxx +0 -62
- data/ext/couchbase/core/columnar/columnar_agent.cxx +0 -147
- data/ext/couchbase/core/columnar/columnar_agent_config.cxx +0 -48
- data/ext/couchbase/core/columnar/columnar_error.cxx +0 -51
- data/ext/couchbase/core/columnar/database_management_options.hxx +0 -56
- data/ext/couchbase/core/columnar/error.hxx +0 -51
- data/ext/couchbase/core/columnar/error_codes.cxx +0 -107
- data/ext/couchbase/core/columnar/error_codes.hxx +0 -75
- data/ext/couchbase/core/columnar/management_component.cxx +0 -300
- data/ext/couchbase/core/columnar/management_component.hxx +0 -56
- data/ext/couchbase/core/columnar/query_component.cxx +0 -523
- data/ext/couchbase/core/columnar/query_component.hxx +0 -57
- data/ext/couchbase/core/columnar/query_options.hxx +0 -59
- data/ext/couchbase/core/columnar/query_result.cxx +0 -130
- data/ext/couchbase/core/columnar/query_result.hxx +0 -78
- data/ext/couchbase/core/io/config_tracker.cxx +0 -687
- data/ext/couchbase/core/io/config_tracker.hxx +0 -123
|
@@ -32,8 +32,31 @@ namespace couchbase::core
|
|
|
32
32
|
auto
|
|
33
33
|
make_key_value_error_context(std::error_code ec, const document_id& id) -> key_value_error_context
|
|
34
34
|
{
|
|
35
|
-
return {
|
|
36
|
-
|
|
35
|
+
return make_key_value_error_context(ec, id, 0, {});
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
auto
|
|
39
|
+
make_key_value_error_context(std::error_code ec,
|
|
40
|
+
const document_id& id,
|
|
41
|
+
std::size_t retry_attempts,
|
|
42
|
+
std::set<retry_reason> retry_reasons) -> key_value_error_context
|
|
43
|
+
{
|
|
44
|
+
return key_value_error_context{
|
|
45
|
+
{},
|
|
46
|
+
ec,
|
|
47
|
+
{},
|
|
48
|
+
{},
|
|
49
|
+
retry_attempts,
|
|
50
|
+
std::move(retry_reasons),
|
|
51
|
+
id.key(),
|
|
52
|
+
id.bucket(),
|
|
53
|
+
id.scope(),
|
|
54
|
+
id.collection(),
|
|
55
|
+
0,
|
|
56
|
+
{},
|
|
57
|
+
{},
|
|
58
|
+
{},
|
|
59
|
+
{},
|
|
37
60
|
};
|
|
38
61
|
}
|
|
39
62
|
|
|
@@ -30,9 +30,43 @@
|
|
|
30
30
|
|
|
31
31
|
namespace couchbase::core
|
|
32
32
|
{
|
|
33
|
+
/**
|
|
34
|
+
* Convenience overload that constructs a @ref key_value_error_context with zero retry attempts and
|
|
35
|
+
* an empty retry-reasons set. Delegates to the four-argument overload.
|
|
36
|
+
*
|
|
37
|
+
* @param ec Error code describing the failure.
|
|
38
|
+
* @param id Document identifier carrying bucket/scope/collection/key.
|
|
39
|
+
* @return A fully initialised @ref key_value_error_context.
|
|
40
|
+
*
|
|
41
|
+
* @since 1.0.0
|
|
42
|
+
* @internal
|
|
43
|
+
*/
|
|
33
44
|
auto
|
|
34
45
|
make_key_value_error_context(std::error_code ec, const document_id& id) -> key_value_error_context;
|
|
35
46
|
|
|
47
|
+
/**
|
|
48
|
+
* Constructs a @ref key_value_error_context for a document-not-dispatched error path where the
|
|
49
|
+
* internal retry bookkeeping fields are available directly (e.g. from @ref queue_request), without
|
|
50
|
+
* requiring a Command/Response template instantiation.
|
|
51
|
+
*
|
|
52
|
+
* Fields that belong to the protocol exchange (opaque, status code, CAS, error-map info, extended
|
|
53
|
+
* error info, dispatched addresses) are left empty because no server response was received.
|
|
54
|
+
*
|
|
55
|
+
* @param ec Error code describing the failure.
|
|
56
|
+
* @param id Document identifier carrying bucket/scope/collection/key.
|
|
57
|
+
* @param retry_attempts Number of retry attempts already performed for the request.
|
|
58
|
+
* @param retry_reasons Set of reasons recorded during those retry attempts.
|
|
59
|
+
* @return A fully initialised @ref key_value_error_context.
|
|
60
|
+
*
|
|
61
|
+
* @since 1.0.0
|
|
62
|
+
* @internal
|
|
63
|
+
*/
|
|
64
|
+
auto
|
|
65
|
+
make_key_value_error_context(std::error_code ec,
|
|
66
|
+
const document_id& id,
|
|
67
|
+
std::size_t retry_attempts,
|
|
68
|
+
std::set<retry_reason> retry_reasons) -> key_value_error_context;
|
|
69
|
+
|
|
36
70
|
template<typename Command, typename Response>
|
|
37
71
|
auto
|
|
38
72
|
make_key_value_error_context(std::error_code ec,
|
|
@@ -58,43 +92,36 @@ make_key_value_error_context(std::error_code ec,
|
|
|
58
92
|
auto retry_attempts = command->request.retries.retry_attempts();
|
|
59
93
|
auto retry_reasons = command->request.retries.retry_reasons();
|
|
60
94
|
|
|
61
|
-
// Build node_id from the session that handled this request.
|
|
62
|
-
//
|
|
63
|
-
//
|
|
64
|
-
//
|
|
65
|
-
//
|
|
66
|
-
// Only construct a node_id once the session has actually been bound to a
|
|
67
|
-
// concrete node: either a non-empty UUID, or a non-empty canonical
|
|
68
|
-
// hostname *and* a non-zero canonical KV port. Otherwise the fallback
|
|
69
|
-
// hash of ("", "", 0) would yield a truthy-but-meaningless node_id and
|
|
70
|
-
// break the contract that a default-constructed node_id means "unknown".
|
|
95
|
+
// Build node_id from the session that handled this request. The session
|
|
96
|
+
// carries the node_uuid (empty on pre-8.0 servers), canonical hostname, and
|
|
97
|
+
// KV port — we feed these into internal_node_id::build, which preserves the
|
|
98
|
+
// "falsy = unknown" contract for not-yet-bound sessions by returning a
|
|
99
|
+
// default node_id when the (uuid, host, port) inputs are all empty/zero.
|
|
71
100
|
couchbase::node_id dispatched_to_node_id{};
|
|
72
101
|
if (command->session_) {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
if (!node_uuid.empty() || (!canonical_hostname.empty() && canonical_port != 0)) {
|
|
77
|
-
dispatched_to_node_id =
|
|
78
|
-
internal_node_id::build(node_uuid, canonical_hostname, canonical_port);
|
|
79
|
-
}
|
|
102
|
+
dispatched_to_node_id = internal_node_id::build(command->session_->node_uuid(),
|
|
103
|
+
command->session_->canonical_hostname(),
|
|
104
|
+
command->session_->canonical_port_number());
|
|
80
105
|
}
|
|
81
106
|
|
|
82
|
-
return {
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
107
|
+
return {
|
|
108
|
+
command->id(),
|
|
109
|
+
ec,
|
|
110
|
+
command->last_dispatched_to_,
|
|
111
|
+
command->last_dispatched_from_,
|
|
112
|
+
retry_attempts,
|
|
113
|
+
std::move(retry_reasons),
|
|
114
|
+
std::move(dispatched_to_node_id),
|
|
115
|
+
key,
|
|
116
|
+
bucket,
|
|
117
|
+
scope,
|
|
118
|
+
collection,
|
|
119
|
+
opaque,
|
|
120
|
+
status,
|
|
121
|
+
response.cas(),
|
|
122
|
+
std::move(error_map_info),
|
|
123
|
+
response.error_info(),
|
|
124
|
+
};
|
|
98
125
|
}
|
|
99
126
|
|
|
100
127
|
auto
|
|
@@ -83,21 +83,22 @@ public:
|
|
|
83
83
|
couchbase::cas cas,
|
|
84
84
|
std::optional<key_value_error_map_info> error_map_info,
|
|
85
85
|
std::optional<key_value_extended_error_info> extended_error_info)
|
|
86
|
-
:
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
86
|
+
: key_value_error_context{ std::move(operation_id),
|
|
87
|
+
ec,
|
|
88
|
+
std::move(last_dispatched_to),
|
|
89
|
+
std::move(last_dispatched_from),
|
|
90
|
+
retry_attempts,
|
|
91
|
+
std::move(retry_reasons),
|
|
92
|
+
couchbase::node_id{},
|
|
93
|
+
std::move(id),
|
|
94
|
+
std::move(bucket),
|
|
95
|
+
std::move(scope),
|
|
96
|
+
std::move(collection),
|
|
97
|
+
opaque,
|
|
98
|
+
status_code,
|
|
99
|
+
cas,
|
|
100
|
+
std::move(error_map_info),
|
|
101
|
+
std::move(extended_error_info) }
|
|
101
102
|
{
|
|
102
103
|
}
|
|
103
104
|
|
|
@@ -35,6 +35,11 @@ struct search {
|
|
|
35
35
|
std::string query{};
|
|
36
36
|
std::optional<std::string> parameters{};
|
|
37
37
|
|
|
38
|
+
// The message the service reported, when it reported one. Over couchbase2 this is the gRPC
|
|
39
|
+
// status message, which is the only error detail that transport carries -- http_status and
|
|
40
|
+
// http_body stay empty there.
|
|
41
|
+
std::string first_error_message{};
|
|
42
|
+
|
|
38
43
|
std::string method{};
|
|
39
44
|
std::string path{};
|
|
40
45
|
std::uint32_t http_status{};
|
|
@@ -48,6 +48,9 @@ struct traits<couchbase::core::error_context::search> {
|
|
|
48
48
|
if (const auto& val = ctx.parameters; val.has_value()) {
|
|
49
49
|
v["parameters"] = val.value();
|
|
50
50
|
}
|
|
51
|
+
if (!ctx.first_error_message.empty()) {
|
|
52
|
+
v["first_error_message"] = ctx.first_error_message;
|
|
53
|
+
}
|
|
51
54
|
if (const auto& reasons = ctx.retry_reasons; !reasons.empty()) {
|
|
52
55
|
tao::json::value reasons_json = tao::json::empty_array;
|
|
53
56
|
for (const auto& reason : reasons) {
|
|
@@ -81,24 +81,25 @@ public:
|
|
|
81
81
|
std::optional<std::string> first_error_path,
|
|
82
82
|
std::optional<std::uint64_t> first_error_index,
|
|
83
83
|
bool deleted)
|
|
84
|
-
:
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
84
|
+
: subdocument_error_context{ std::move(operation_id),
|
|
85
|
+
ec,
|
|
86
|
+
std::move(last_dispatched_to),
|
|
87
|
+
std::move(last_dispatched_from),
|
|
88
|
+
retry_attempts,
|
|
89
|
+
std::move(retry_reasons),
|
|
90
|
+
couchbase::node_id{},
|
|
91
|
+
std::move(id),
|
|
92
|
+
std::move(bucket),
|
|
93
|
+
std::move(scope),
|
|
94
|
+
std::move(collection),
|
|
95
|
+
opaque,
|
|
96
|
+
status_code,
|
|
97
|
+
cas,
|
|
98
|
+
std::move(error_map_info),
|
|
99
|
+
std::move(extended_error_info),
|
|
100
|
+
std::move(first_error_path),
|
|
101
|
+
first_error_index,
|
|
102
|
+
deleted }
|
|
102
103
|
{
|
|
103
104
|
}
|
|
104
105
|
|
|
@@ -36,6 +36,11 @@ struct view {
|
|
|
36
36
|
std::string view_name{};
|
|
37
37
|
std::vector<std::string> query_string{};
|
|
38
38
|
|
|
39
|
+
// The message the service reported, when it reported one. Over couchbase2 this is the gRPC
|
|
40
|
+
// status message, which is the only error detail that transport carries -- http_status and
|
|
41
|
+
// http_body stay empty there.
|
|
42
|
+
std::string first_error_message{};
|
|
43
|
+
|
|
39
44
|
std::string method{};
|
|
40
45
|
std::string path{};
|
|
41
46
|
std::uint32_t http_status{};
|
|
@@ -19,16 +19,25 @@
|
|
|
19
19
|
#include "io/http_streaming_response.hxx"
|
|
20
20
|
#include "utils/movable_function.hxx"
|
|
21
21
|
|
|
22
|
+
#include <couchbase/error_codes.hxx>
|
|
23
|
+
|
|
24
|
+
#include <asio/io_context.hpp>
|
|
25
|
+
#include <asio/steady_timer.hpp>
|
|
26
|
+
|
|
27
|
+
#include <chrono>
|
|
28
|
+
|
|
22
29
|
#include <cstddef>
|
|
23
30
|
#include <cstdint>
|
|
24
31
|
#include <memory>
|
|
32
|
+
#include <mutex>
|
|
33
|
+
#include <optional>
|
|
25
34
|
#include <string>
|
|
26
35
|
#include <system_error>
|
|
27
36
|
#include <utility>
|
|
28
37
|
|
|
29
38
|
namespace couchbase::core
|
|
30
39
|
{
|
|
31
|
-
class http_response_impl
|
|
40
|
+
class http_response_impl : public std::enable_shared_from_this<http_response_impl>
|
|
32
41
|
{
|
|
33
42
|
public:
|
|
34
43
|
http_response_impl() = default;
|
|
@@ -38,36 +47,222 @@ public:
|
|
|
38
47
|
{
|
|
39
48
|
}
|
|
40
49
|
|
|
50
|
+
http_response_impl(asio::io_context& io, std::string cached_data, std::size_t cached_chunk_size)
|
|
51
|
+
: cached_body_{ io::http_streaming_response_body{ io,
|
|
52
|
+
nullptr,
|
|
53
|
+
std::move(cached_data),
|
|
54
|
+
true,
|
|
55
|
+
cached_chunk_size } }
|
|
56
|
+
{
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Fault-injecting in-memory body (test seam): see http_response_body::create_in_memory_faulty.
|
|
60
|
+
http_response_impl(asio::io_context& io,
|
|
61
|
+
std::string fault_data,
|
|
62
|
+
std::size_t fault_chunk_size,
|
|
63
|
+
std::error_code fault_terminal_ec,
|
|
64
|
+
bool fault_stall)
|
|
65
|
+
: fault_deadline_{ std::make_shared<asio::steady_timer>(io) }
|
|
66
|
+
, fault_enabled_{ true }
|
|
67
|
+
, fault_data_{ std::move(fault_data) }
|
|
68
|
+
, fault_chunk_size_{ fault_chunk_size }
|
|
69
|
+
, fault_terminal_ec_{ fault_terminal_ec }
|
|
70
|
+
, fault_stall_{ fault_stall }
|
|
71
|
+
{
|
|
72
|
+
}
|
|
73
|
+
|
|
41
74
|
[[nodiscard]] auto endpoint() const -> std::string
|
|
42
75
|
{
|
|
43
|
-
|
|
76
|
+
if (cached_body_ || fault_enabled_) {
|
|
77
|
+
return {};
|
|
78
|
+
}
|
|
79
|
+
return streaming_resp_.dispatch_info().remote_address;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
[[nodiscard]] auto dispatch_info() const -> io::http_dispatch_info
|
|
83
|
+
{
|
|
84
|
+
if (cached_body_ || fault_enabled_) {
|
|
85
|
+
return {};
|
|
86
|
+
}
|
|
87
|
+
return streaming_resp_.dispatch_info();
|
|
44
88
|
}
|
|
45
89
|
|
|
46
90
|
[[nodiscard]] auto status_code() const -> std::uint32_t
|
|
47
91
|
{
|
|
92
|
+
if (cached_body_) {
|
|
93
|
+
return 200;
|
|
94
|
+
}
|
|
48
95
|
return streaming_resp_.status_code();
|
|
49
96
|
}
|
|
50
97
|
|
|
51
98
|
[[nodiscard]] auto content_length() const -> std::size_t
|
|
52
99
|
{
|
|
100
|
+
if (cached_body_) {
|
|
101
|
+
return 0;
|
|
102
|
+
}
|
|
53
103
|
if (streaming_resp_.headers().find("content-length") == streaming_resp_.headers().end()) {
|
|
54
104
|
return 0;
|
|
55
105
|
}
|
|
56
106
|
return std::stoul(streaming_resp_.headers().at("content-length"));
|
|
57
107
|
}
|
|
58
108
|
|
|
59
|
-
void next_body(utils::movable_function<void(std::string, std::error_code)> callback)
|
|
109
|
+
void next_body(utils::movable_function<void(std::string, bool, std::error_code)> callback)
|
|
60
110
|
{
|
|
111
|
+
if (fault_enabled_) {
|
|
112
|
+
// Handlers are invoked after the lock is dropped.
|
|
113
|
+
std::unique_lock<std::mutex> lock{ fault_mutex_ };
|
|
114
|
+
if (fault_cancelled_) {
|
|
115
|
+
const auto ec = fault_closed_ec_;
|
|
116
|
+
lock.unlock();
|
|
117
|
+
return callback({}, false, ec);
|
|
118
|
+
}
|
|
119
|
+
if (!fault_data_.empty()) {
|
|
120
|
+
std::string chunk;
|
|
121
|
+
if (fault_chunk_size_ == 0 || fault_data_.size() <= fault_chunk_size_) {
|
|
122
|
+
std::swap(chunk, fault_data_);
|
|
123
|
+
} else {
|
|
124
|
+
chunk = fault_data_.substr(0, fault_chunk_size_);
|
|
125
|
+
fault_data_.erase(0, fault_chunk_size_);
|
|
126
|
+
}
|
|
127
|
+
// has_more is always true here: whatever comes after the data (a stall, an injected
|
|
128
|
+
// terminal error, or a clean end) is delivered on a subsequent pull.
|
|
129
|
+
lock.unlock();
|
|
130
|
+
return callback(std::move(chunk), true, {});
|
|
131
|
+
}
|
|
132
|
+
if (fault_stall_) {
|
|
133
|
+
// Simulate a server that stopped sending mid-body: park the pull and never complete it
|
|
134
|
+
// until cancel() (close_body) or an expired deadline fires it.
|
|
135
|
+
fault_parked_ = std::move(callback);
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
// Drained: no deadline is accepted from here on. The generation is bumped for the same
|
|
139
|
+
// reason close_body() bumps it -- cancel() does not stop a completion already queued -- so
|
|
140
|
+
// both drain paths supersede one identically rather than relying on fault_finished_ alone.
|
|
141
|
+
fault_finished_ = true;
|
|
142
|
+
++fault_generation_;
|
|
143
|
+
fault_deadline_->cancel();
|
|
144
|
+
const auto ec = fault_terminal_ec_;
|
|
145
|
+
lock.unlock();
|
|
146
|
+
return callback({}, false, ec);
|
|
147
|
+
}
|
|
148
|
+
if (cached_body_) {
|
|
149
|
+
return cached_body_->next(std::move(callback));
|
|
150
|
+
}
|
|
61
151
|
return streaming_resp_.body().next(std::move(callback));
|
|
62
152
|
}
|
|
63
153
|
|
|
154
|
+
void cancel_body_deadline()
|
|
155
|
+
{
|
|
156
|
+
if (fault_enabled_) {
|
|
157
|
+
const std::scoped_lock lock{ fault_mutex_ };
|
|
158
|
+
++fault_generation_;
|
|
159
|
+
fault_deadline_->cancel();
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
if (cached_body_) {
|
|
163
|
+
return cached_body_->cancel_deadline();
|
|
164
|
+
}
|
|
165
|
+
return streaming_resp_.body().cancel_deadline();
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
auto set_body_deadline(std::chrono::time_point<std::chrono::steady_clock> deadline_tp,
|
|
169
|
+
io::deadline_terminal on_expiry) -> io::deadline_state
|
|
170
|
+
{
|
|
171
|
+
if (fault_enabled_) {
|
|
172
|
+
const std::scoped_lock lock{ fault_mutex_ };
|
|
173
|
+
// A seam with no bytes left and no stall is terminal before the drain branch of next_body()
|
|
174
|
+
// has run. The real body answers body_already_ended in the same state -- reading_complete_
|
|
175
|
+
// with an empty cache -- and a seam that armed instead would hold the io_context open until
|
|
176
|
+
// it fired. fault_finished_ is recorded here, so a close_body() after this refusal keeps the
|
|
177
|
+
// configured terminal, as the real body refuses a close once drained.
|
|
178
|
+
if (fault_data_.empty() && !fault_stall_) {
|
|
179
|
+
fault_finished_ = true;
|
|
180
|
+
}
|
|
181
|
+
if (fault_cancelled_ || fault_finished_) {
|
|
182
|
+
return io::deadline_state::body_already_ended;
|
|
183
|
+
}
|
|
184
|
+
const auto generation = ++fault_generation_;
|
|
185
|
+
fault_deadline_->expires_at(deadline_tp);
|
|
186
|
+
fault_deadline_->async_wait([self = shared_from_this(), on_expiry, generation](auto ec) {
|
|
187
|
+
if (ec == asio::error::operation_aborted) {
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
self->close_body_at_deadline(on_expiry, generation);
|
|
191
|
+
});
|
|
192
|
+
return io::deadline_state::armed;
|
|
193
|
+
}
|
|
194
|
+
if (cached_body_) {
|
|
195
|
+
return cached_body_->set_deadline(deadline_tp, on_expiry);
|
|
196
|
+
}
|
|
197
|
+
return streaming_resp_.body().set_deadline(deadline_tp, on_expiry);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
void close_body_at_deadline(io::deadline_terminal on_expiry, std::uint64_t generation)
|
|
201
|
+
{
|
|
202
|
+
utils::movable_function<void(std::string, bool, std::error_code)> parked;
|
|
203
|
+
{
|
|
204
|
+
const std::scoped_lock lock{ fault_mutex_ };
|
|
205
|
+
// expires_at/cancel do not stop a completion already queued; ignore a superseded one.
|
|
206
|
+
if (generation != fault_generation_ || fault_cancelled_ || fault_finished_) {
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
fault_cancelled_ = true;
|
|
210
|
+
fault_closed_ec_ = io::terminal_error_code(on_expiry);
|
|
211
|
+
fault_deadline_->cancel();
|
|
212
|
+
parked = std::move(fault_parked_);
|
|
213
|
+
}
|
|
214
|
+
if (parked) {
|
|
215
|
+
parked({}, false, io::terminal_error_code(on_expiry));
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
64
219
|
void close_body()
|
|
65
220
|
{
|
|
221
|
+
if (fault_enabled_) {
|
|
222
|
+
std::unique_lock<std::mutex> lock{ fault_mutex_ };
|
|
223
|
+
// First terminal wins, as in the real body. set_body_deadline() and
|
|
224
|
+
// close_body_at_deadline() test the same pair; a cancel arriving after the terminal path
|
|
225
|
+
// unlocked would otherwise change later pulls to request_canceled.
|
|
226
|
+
if (fault_cancelled_ || fault_finished_) {
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
fault_cancelled_ = true;
|
|
230
|
+
++fault_generation_;
|
|
231
|
+
fault_deadline_->cancel();
|
|
232
|
+
auto cb = std::move(fault_parked_);
|
|
233
|
+
const auto ec = fault_closed_ec_;
|
|
234
|
+
lock.unlock();
|
|
235
|
+
if (cb) {
|
|
236
|
+
cb({}, false, ec);
|
|
237
|
+
}
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
if (cached_body_) {
|
|
241
|
+
return cached_body_->close();
|
|
242
|
+
}
|
|
66
243
|
return streaming_resp_.body().close();
|
|
67
244
|
}
|
|
68
245
|
|
|
69
246
|
private:
|
|
70
247
|
io::http_streaming_response streaming_resp_;
|
|
248
|
+
std::optional<io::http_streaming_response_body> cached_body_{};
|
|
249
|
+
// fault_mutex_ guards every fault_* member written after construction, including the timer:
|
|
250
|
+
// asio timers are not safe under concurrent use. fault_enabled_ is set once by the
|
|
251
|
+
// constructor and read unlocked. Only the fault seam owns a timer; the other bodies forward to an
|
|
252
|
+
// existing one.
|
|
253
|
+
mutable std::mutex fault_mutex_{};
|
|
254
|
+
std::shared_ptr<asio::steady_timer> fault_deadline_{};
|
|
255
|
+
// Fault-injection test seam (see the fault-injecting ctor and create_in_memory_faulty).
|
|
256
|
+
bool fault_enabled_{ false };
|
|
257
|
+
std::string fault_data_{};
|
|
258
|
+
std::size_t fault_chunk_size_{ 0 };
|
|
259
|
+
std::error_code fault_terminal_ec_{};
|
|
260
|
+
bool fault_stall_{ false };
|
|
261
|
+
bool fault_cancelled_{ false };
|
|
262
|
+
bool fault_finished_{ false };
|
|
263
|
+
std::uint64_t fault_generation_{ 0 };
|
|
264
|
+
std::error_code fault_closed_ec_{ errc::common::request_canceled };
|
|
265
|
+
utils::movable_function<void(std::string, bool, std::error_code)> fault_parked_{};
|
|
71
266
|
};
|
|
72
267
|
|
|
73
268
|
class buffered_http_response_impl
|
|
@@ -116,6 +311,11 @@ http_response::endpoint() const -> std::string
|
|
|
116
311
|
return impl_->endpoint();
|
|
117
312
|
}
|
|
118
313
|
auto
|
|
314
|
+
http_response::dispatch_info() const -> io::http_dispatch_info
|
|
315
|
+
{
|
|
316
|
+
return impl_->dispatch_info();
|
|
317
|
+
}
|
|
318
|
+
auto
|
|
119
319
|
http_response::status_code() const -> std::uint32_t
|
|
120
320
|
{
|
|
121
321
|
return impl_->status_code();
|
|
@@ -143,6 +343,39 @@ http_response_body::http_response_body(std::shared_ptr<http_response_impl> impl)
|
|
|
143
343
|
{
|
|
144
344
|
}
|
|
145
345
|
|
|
346
|
+
auto
|
|
347
|
+
http_response_body::create_in_memory(asio::io_context& io,
|
|
348
|
+
std::string data,
|
|
349
|
+
std::size_t cached_chunk_size) -> http_response_body
|
|
350
|
+
{
|
|
351
|
+
return http_response_body{ std::make_shared<http_response_impl>(
|
|
352
|
+
io, std::move(data), cached_chunk_size) };
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
auto
|
|
356
|
+
http_response_body::create_in_memory_faulty(asio::io_context& io,
|
|
357
|
+
std::string data,
|
|
358
|
+
std::size_t cached_chunk_size,
|
|
359
|
+
std::error_code terminal_ec,
|
|
360
|
+
bool stall) -> http_response_body
|
|
361
|
+
{
|
|
362
|
+
return http_response_body{ std::make_shared<http_response_impl>(
|
|
363
|
+
io, std::move(data), cached_chunk_size, terminal_ec, stall) };
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
auto
|
|
367
|
+
http_response_body::set_deadline(std::chrono::time_point<std::chrono::steady_clock> deadline_tp,
|
|
368
|
+
io::deadline_terminal on_expiry) -> io::deadline_state
|
|
369
|
+
{
|
|
370
|
+
return impl_->set_body_deadline(deadline_tp, on_expiry);
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
void
|
|
374
|
+
http_response_body::cancel_deadline()
|
|
375
|
+
{
|
|
376
|
+
return impl_->cancel_body_deadline();
|
|
377
|
+
}
|
|
378
|
+
|
|
146
379
|
void
|
|
147
380
|
http_response_body::cancel()
|
|
148
381
|
{
|
|
@@ -150,7 +383,7 @@ http_response_body::cancel()
|
|
|
150
383
|
}
|
|
151
384
|
|
|
152
385
|
void
|
|
153
|
-
http_response_body::next(utils::movable_function<void(std::string, std::error_code)> callback)
|
|
386
|
+
http_response_body::next(utils::movable_function<void(std::string, bool, std::error_code)> callback)
|
|
154
387
|
{
|
|
155
388
|
return impl_->next_body(std::move(callback));
|
|
156
389
|
}
|
|
@@ -15,14 +15,14 @@
|
|
|
15
15
|
|
|
16
16
|
#pragma once
|
|
17
17
|
|
|
18
|
-
#include <couchbase/build_config.hxx>
|
|
19
|
-
|
|
20
18
|
#include "core/impl/bootstrap_error.hxx"
|
|
19
|
+
#include "core/io/http_streaming_response.hxx"
|
|
21
20
|
#include "service_type.hxx"
|
|
22
21
|
#include "utils/movable_function.hxx"
|
|
23
22
|
|
|
24
23
|
#include <chrono>
|
|
25
24
|
#include <cinttypes>
|
|
25
|
+
#include <cstddef>
|
|
26
26
|
#include <map>
|
|
27
27
|
#include <memory>
|
|
28
28
|
#include <optional>
|
|
@@ -30,6 +30,11 @@
|
|
|
30
30
|
#include <system_error>
|
|
31
31
|
#include <vector>
|
|
32
32
|
|
|
33
|
+
namespace asio
|
|
34
|
+
{
|
|
35
|
+
class io_context;
|
|
36
|
+
} // namespace asio
|
|
37
|
+
|
|
33
38
|
namespace couchbase
|
|
34
39
|
{
|
|
35
40
|
class retry_strategy;
|
|
@@ -78,9 +83,39 @@ class http_response_body
|
|
|
78
83
|
public:
|
|
79
84
|
explicit http_response_body(std::shared_ptr<http_response_impl> impl);
|
|
80
85
|
|
|
81
|
-
|
|
86
|
+
// cached_chunk_size > 0 makes the in-memory body deliver at most that many bytes per next()
|
|
87
|
+
// call (a test seam simulating a socket that dribbles the response out, so back-pressure can be
|
|
88
|
+
// exercised); 0 delivers the whole body in one chunk.
|
|
89
|
+
static auto create_in_memory(asio::io_context& io,
|
|
90
|
+
std::string data,
|
|
91
|
+
std::size_t cached_chunk_size = 0) -> http_response_body;
|
|
92
|
+
|
|
93
|
+
// Test-only fault-injection seam extending create_in_memory. The body first hands out `data` (in
|
|
94
|
+
// cached_chunk_size-byte slices, 0 = all at once), then once that is drained:
|
|
95
|
+
// * if `stall` is true, the next pull never completes until cancel() or an expired deadline
|
|
96
|
+
// fires it, delivering request_canceled or the deadline's error respectively — this is how
|
|
97
|
+
// the row_streamer idle timer (and its read-only-aware timeout classification) is exercised
|
|
98
|
+
// deterministically; otherwise
|
|
99
|
+
// * the next pull's terminal carries `terminal_ec` (a simulated mid-stream transport error).
|
|
100
|
+
static auto create_in_memory_faulty(asio::io_context& io,
|
|
101
|
+
std::string data,
|
|
102
|
+
std::size_t cached_chunk_size,
|
|
103
|
+
std::error_code terminal_ec,
|
|
104
|
+
bool stall) -> http_response_body;
|
|
105
|
+
|
|
106
|
+
// See io::http_streaming_response_body::next: the bool is `has_more` (false marks end-of-stream).
|
|
107
|
+
// An empty data string with has_more==true is a valid mid-stream chunk, not the terminal.
|
|
108
|
+
void next(utils::movable_function<void(std::string, bool, std::error_code)> callback);
|
|
82
109
|
void cancel();
|
|
83
110
|
|
|
111
|
+
// Closes the body with `on_expiry` at `deadline_tp`, whether or not a pull is outstanding.
|
|
112
|
+
// Optional.
|
|
113
|
+
[[nodiscard]] auto set_deadline(std::chrono::time_point<std::chrono::steady_clock> deadline_tp,
|
|
114
|
+
io::deadline_terminal on_expiry) -> io::deadline_state;
|
|
115
|
+
// See io::http_streaming_response_body::cancel_deadline: supersedes an armed deadline without
|
|
116
|
+
// ending the body.
|
|
117
|
+
void cancel_deadline();
|
|
118
|
+
|
|
84
119
|
private:
|
|
85
120
|
std::shared_ptr<http_response_impl> impl_;
|
|
86
121
|
};
|
|
@@ -92,6 +127,9 @@ public:
|
|
|
92
127
|
explicit http_response(io::http_streaming_response resp);
|
|
93
128
|
|
|
94
129
|
[[nodiscard]] auto endpoint() const -> std::string;
|
|
130
|
+
// Where this response was dispatched. Empty for the in-memory/fault test bodies, which have no
|
|
131
|
+
// session behind them.
|
|
132
|
+
[[nodiscard]] auto dispatch_info() const -> io::http_dispatch_info;
|
|
95
133
|
[[nodiscard]] auto status_code() const -> std::uint32_t;
|
|
96
134
|
[[nodiscard]] auto content_length() const -> std::size_t;
|
|
97
135
|
|
|
@@ -102,13 +140,8 @@ private:
|
|
|
102
140
|
std::shared_ptr<http_response_impl> impl_;
|
|
103
141
|
};
|
|
104
142
|
|
|
105
|
-
#ifdef COUCHBASE_CXX_CLIENT_COLUMNAR
|
|
106
|
-
using free_form_http_request_callback =
|
|
107
|
-
utils::movable_function<void(http_response response, couchbase::core::error_union err)>;
|
|
108
|
-
#else
|
|
109
143
|
using free_form_http_request_callback =
|
|
110
144
|
utils::movable_function<void(http_response response, std::error_code ec)>;
|
|
111
|
-
#endif
|
|
112
145
|
|
|
113
146
|
class buffered_http_response_impl;
|
|
114
147
|
|