couchbase 3.8.2 → 3.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/ext/CMakeLists.txt +16 -1
- data/ext/cache/cpm/{CPM_0.42.0.cmake → CPM_0.43.1.cmake} +18 -2
- data/ext/cache/extconf_include.rb +6 -6
- data/ext/cache/mozilla-ca-bundle.crt +121 -55
- data/ext/cache/mozilla-ca-bundle.sha256 +1 -1
- data/ext/couchbase/CMakeLists.txt +136 -23
- data/ext/couchbase/cmake/APKBUILD.in +25 -4
- data/ext/couchbase/cmake/Bundler.cmake +143 -34
- data/ext/couchbase/cmake/CPM.cmake +126 -12
- data/ext/couchbase/cmake/Cache.cmake +7 -1
- data/ext/couchbase/cmake/CompilerOptions.cmake +1 -1
- data/ext/couchbase/cmake/CompilerWarnings.cmake +17 -6
- data/ext/couchbase/cmake/GrpcProtobuf.cmake +481 -0
- data/ext/couchbase/cmake/OpenSSL.cmake +82 -7
- data/ext/couchbase/cmake/Packaging.cmake +519 -65
- data/ext/couchbase/cmake/Protostellar.cmake +250 -0
- data/ext/couchbase/cmake/Sanitizers.cmake +61 -50
- data/ext/couchbase/cmake/StaticAnalyzers.cmake +16 -5
- data/ext/couchbase/cmake/TestFramework.cmake +283 -0
- data/ext/couchbase/cmake/TestFrameworkAddTests.cmake +51 -0
- data/ext/couchbase/cmake/Testing.cmake +27 -9
- data/ext/couchbase/cmake/ThirdPartyDependencies.cmake +141 -8
- data/ext/couchbase/cmake/VersionInfo.cmake +50 -0
- data/ext/couchbase/cmake/build_config.hxx.in +2 -1
- data/ext/couchbase/cmake/couchbase-cxx-client.spec.in +101 -23
- data/ext/couchbase/cmake/couchbase_cxx_client_static-config.cmake.in +7 -0
- data/ext/couchbase/cmake/couchbase_cxx_client_static.pc.in +2 -0
- data/ext/couchbase/cmake/gRPC_Generate.cmake +58 -0
- data/ext/couchbase/cmake/protobuf_Generate.cmake +69 -0
- data/ext/couchbase/cmake/require-git-checkout.cmake +25 -0
- data/ext/couchbase/cmake/tarball_glob.txt +49 -0
- data/ext/couchbase/core/agent_group.cxx +0 -8
- data/ext/couchbase/core/agent_group.hxx +0 -4
- data/ext/couchbase/core/analytics_stream.cxx +314 -0
- data/ext/couchbase/core/analytics_stream.hxx +129 -0
- data/ext/couchbase/core/analytics_stream_component.cxx +245 -0
- data/ext/couchbase/core/analytics_stream_component.hxx +67 -0
- data/ext/couchbase/core/app_telemetry_meter.cxx +25 -3
- data/ext/couchbase/core/app_telemetry_meter.hxx +77 -0
- data/ext/couchbase/core/app_telemetry_reporter.cxx +7 -6
- data/ext/couchbase/core/bucket.cxx +381 -87
- data/ext/couchbase/core/bucket.hxx +105 -25
- data/ext/couchbase/core/bucket_unit_test_api.hxx +57 -0
- data/ext/couchbase/core/capella.hxx +91 -0
- data/ext/couchbase/core/cluster.cxx +1551 -397
- data/ext/couchbase/core/cluster.hxx +39 -8
- data/ext/couchbase/core/cluster_agent.cxx +0 -8
- data/ext/couchbase/core/cluster_agent.hxx +0 -4
- data/ext/couchbase/core/cluster_options.hxx +26 -3
- data/ext/couchbase/core/collections_component.cxx +39 -15
- data/ext/couchbase/core/config_profiles.cxx +1 -1
- data/ext/couchbase/core/crud_component.cxx +2 -2
- data/ext/couchbase/core/crud_options.hxx +34 -0
- data/ext/couchbase/core/crypto/cbcrypto.cc +18 -13
- data/ext/couchbase/core/document_id_redaction.hxx +81 -0
- data/ext/couchbase/core/error_context/base_error_context.hxx +7 -6
- data/ext/couchbase/core/error_context/key_value.cxx +25 -2
- data/ext/couchbase/core/error_context/key_value.hxx +60 -33
- data/ext/couchbase/core/error_context/key_value_error_context.hxx +16 -15
- data/ext/couchbase/core/error_context/search.hxx +5 -0
- data/ext/couchbase/core/error_context/search_json.hxx +3 -0
- data/ext/couchbase/core/error_context/subdocument_error_context.hxx +19 -18
- data/ext/couchbase/core/error_context/view.hxx +5 -0
- data/ext/couchbase/core/free_form_http_request.cxx +237 -4
- data/ext/couchbase/core/free_form_http_request.hxx +41 -8
- data/ext/couchbase/core/http_component.cxx +300 -284
- data/ext/couchbase/core/http_component.hxx +0 -4
- data/ext/couchbase/core/impl/analytics.cxx +38 -5
- data/ext/couchbase/core/impl/analytics.hxx +34 -0
- data/ext/couchbase/core/impl/bootstrap_error.hxx +0 -3
- data/ext/couchbase/core/impl/collection.cxx +215 -202
- data/ext/couchbase/core/impl/collection_manager.cxx +1 -1
- data/ext/couchbase/core/impl/dns_srv_tracker.cxx +45 -18
- data/ext/couchbase/core/impl/error.cxx +22 -2
- data/ext/couchbase/core/impl/internal_analytics_stream_result.hxx +111 -0
- data/ext/couchbase/core/impl/internal_query_stream_result.hxx +110 -0
- data/ext/couchbase/core/impl/invoke_with_node_id.hxx +15 -7
- data/ext/couchbase/core/impl/key_value_error_category.cxx +6 -0
- data/ext/couchbase/core/impl/lookup_in_replica.cxx +10 -10
- data/ext/couchbase/core/impl/lookup_in_replica.hxx +4 -4
- data/ext/couchbase/core/impl/node_id.cxx +49 -13
- data/ext/couchbase/core/impl/observability_recorder.cxx +12 -2
- data/ext/couchbase/core/impl/observe_poll.cxx +63 -23
- data/ext/couchbase/core/impl/public_analytics_stream_result.cxx +372 -0
- data/ext/couchbase/core/impl/public_bucket.cxx +48 -2
- data/ext/couchbase/core/impl/public_cluster.cxx +229 -42
- data/ext/couchbase/core/impl/public_query_stream_result.cxx +380 -0
- data/ext/couchbase/core/impl/public_transaction_get_multi_replicas_from_preferred_server_group_result.cxx +42 -0
- data/ext/couchbase/core/impl/public_transaction_get_multi_result.cxx +42 -0
- data/ext/couchbase/core/impl/query.cxx +76 -7
- data/ext/couchbase/core/impl/query.hxx +36 -0
- data/ext/couchbase/core/impl/query_index_manager.cxx +54 -1
- data/ext/couchbase/core/impl/replica_utils.cxx +101 -0
- data/ext/couchbase/core/impl/replica_utils.hxx +64 -0
- data/ext/couchbase/core/impl/resolve_node_id.hxx +125 -0
- data/ext/couchbase/core/impl/scope.cxx +70 -0
- data/ext/couchbase/core/impl/search.cxx +31 -1
- data/ext/couchbase/core/impl/transactions.cxx +130 -0
- data/ext/couchbase/core/impl/wait_until_ready.cxx +439 -0
- data/ext/couchbase/core/impl/wait_until_ready.hxx +110 -0
- data/ext/couchbase/core/impl/with_bucket_config_or_timeout.hxx +180 -0
- data/ext/couchbase/core/impl/with_cancellation.hxx +11 -3
- data/ext/couchbase/core/io/configuration_belongs_to_session.hxx +1 -2
- data/ext/couchbase/core/io/dns_client.cxx +122 -45
- data/ext/couchbase/core/io/dns_codec.hxx +21 -21
- data/ext/couchbase/core/io/dns_config.cxx +21 -6
- data/ext/couchbase/core/io/http_command.hxx +149 -121
- data/ext/couchbase/core/io/http_error.hxx +107 -0
- data/ext/couchbase/core/io/http_parser.cxx +4 -0
- data/ext/couchbase/core/io/http_session.cxx +606 -154
- data/ext/couchbase/core/io/http_session.hxx +147 -30
- data/ext/couchbase/core/io/http_session_manager.hxx +329 -382
- data/ext/couchbase/core/io/http_streaming_parser.cxx +4 -0
- data/ext/couchbase/core/io/http_streaming_response.cxx +328 -43
- data/ext/couchbase/core/io/http_streaming_response.hxx +37 -3
- data/ext/couchbase/core/io/mcbp_buffer_pool.hxx +122 -0
- data/ext/couchbase/core/io/mcbp_command.hxx +150 -51
- data/ext/couchbase/core/io/mcbp_command_id.hxx +45 -0
- data/ext/couchbase/core/io/mcbp_message.cxx +9 -1
- data/ext/couchbase/core/io/mcbp_message.hxx +19 -0
- data/ext/couchbase/core/io/mcbp_output_queue.hxx +150 -0
- data/ext/couchbase/core/io/mcbp_parser.cxx +24 -7
- data/ext/couchbase/core/io/mcbp_session.cxx +309 -301
- data/ext/couchbase/core/io/mcbp_session.hxx +27 -18
- data/ext/couchbase/core/io/opaque_ring_table.hxx +145 -0
- data/ext/couchbase/core/io/retry_orchestrator.hxx +6 -5
- data/ext/couchbase/core/io/stream_deadline.hxx +50 -0
- data/ext/couchbase/core/io/streams.cxx +151 -21
- data/ext/couchbase/core/io/streams.hxx +48 -1
- data/ext/couchbase/core/logger/logger.cxx +36 -0
- data/ext/couchbase/core/logger/logger.hxx +46 -6
- data/ext/couchbase/core/logger/redaction.hxx +503 -0
- data/ext/couchbase/core/management/eventing_status.hxx +10 -0
- data/ext/couchbase/core/management/eventing_status_json.hxx +4 -0
- data/ext/couchbase/core/mcbp/big_endian.cxx +1 -1
- data/ext/couchbase/core/mcbp/codec.cxx +27 -18
- data/ext/couchbase/core/mcbp/operation_queue.cxx +2 -2
- data/ext/couchbase/core/mcbp/packet.hxx +2 -2
- data/ext/couchbase/core/mcbp/queue_request.cxx +23 -6
- data/ext/couchbase/core/mcbp/queue_request.hxx +21 -0
- data/ext/couchbase/core/meta/features.hxx +13 -0
- data/ext/couchbase/core/meta/version.cxx +6 -3
- data/ext/couchbase/core/metrics/logging_meter.cxx +5 -10
- data/ext/couchbase/core/metrics/meter_wrapper.cxx +63 -33
- data/ext/couchbase/core/metrics/meter_wrapper.hxx +55 -3
- data/ext/couchbase/core/operations/analytics_response_parsing.cxx +177 -0
- data/ext/couchbase/core/operations/analytics_response_parsing.hxx +55 -0
- data/ext/couchbase/core/operations/document_analytics.cxx +48 -130
- data/ext/couchbase/core/operations/document_analytics.hxx +14 -2
- data/ext/couchbase/core/operations/document_get_all_replicas.hxx +15 -7
- data/ext/couchbase/core/operations/document_get_any_replica.hxx +19 -8
- data/ext/couchbase/core/operations/document_get_projected.cxx +1 -1
- data/ext/couchbase/core/{impl/get_replica.cxx → operations/document_get_replica.cxx} +21 -3
- data/ext/couchbase/core/{impl/get_replica.hxx → operations/document_get_replica.hxx} +31 -4
- data/ext/couchbase/core/operations/document_lookup_in.cxx +10 -10
- data/ext/couchbase/core/operations/document_lookup_in_all_replicas.hxx +228 -198
- data/ext/couchbase/core/operations/document_lookup_in_any_replica.hxx +215 -217
- data/ext/couchbase/core/operations/document_query.cxx +108 -221
- data/ext/couchbase/core/operations/document_query.hxx +18 -4
- data/ext/couchbase/core/operations/document_search.cxx +52 -8
- data/ext/couchbase/core/operations/document_search.hxx +3 -0
- data/ext/couchbase/core/operations/document_view.cxx +3 -3
- data/ext/couchbase/core/operations/management/analytics_dataset_create.cxx +15 -8
- data/ext/couchbase/core/operations/management/analytics_dataset_create.hxx +4 -0
- data/ext/couchbase/core/operations/management/analytics_dataset_drop.cxx +11 -6
- data/ext/couchbase/core/operations/management/analytics_dataset_get_all.cxx +3 -2
- data/ext/couchbase/core/operations/management/analytics_dataverse_create.cxx +10 -5
- data/ext/couchbase/core/operations/management/analytics_dataverse_drop.cxx +10 -5
- data/ext/couchbase/core/operations/management/analytics_get_pending_mutations.cxx +2 -1
- data/ext/couchbase/core/operations/management/analytics_index_create.cxx +33 -8
- data/ext/couchbase/core/operations/management/analytics_index_drop.cxx +12 -7
- data/ext/couchbase/core/operations/management/analytics_index_get_all.cxx +3 -2
- data/ext/couchbase/core/operations/management/analytics_link_connect.cxx +11 -6
- data/ext/couchbase/core/operations/management/analytics_link_create.cxx +3 -3
- data/ext/couchbase/core/operations/management/analytics_link_disconnect.cxx +10 -4
- data/ext/couchbase/core/operations/management/analytics_link_drop.cxx +6 -4
- data/ext/couchbase/core/operations/management/analytics_link_get_all.cxx +4 -3
- data/ext/couchbase/core/operations/management/analytics_link_replace.cxx +3 -3
- data/ext/couchbase/core/operations/management/analytics_link_utils.hxx +1 -1
- data/ext/couchbase/core/operations/management/change_password.cxx +2 -0
- data/ext/couchbase/core/operations/management/collection_drop.cxx +5 -1
- data/ext/couchbase/core/operations/management/error_utils.cxx +60 -6
- data/ext/couchbase/core/operations/management/error_utils.hxx +29 -1
- data/ext/couchbase/core/operations/management/eventing_deploy_function.cxx +9 -3
- data/ext/couchbase/core/operations/management/eventing_drop_function.cxx +8 -3
- data/ext/couchbase/core/operations/management/eventing_get_all_functions.cxx +4 -2
- data/ext/couchbase/core/operations/management/eventing_get_function.cxx +5 -3
- data/ext/couchbase/core/operations/management/eventing_get_status.cxx +4 -2
- data/ext/couchbase/core/operations/management/eventing_pause_function.cxx +9 -3
- data/ext/couchbase/core/operations/management/eventing_resume_function.cxx +9 -3
- data/ext/couchbase/core/operations/management/eventing_undeploy_function.cxx +9 -3
- data/ext/couchbase/core/operations/management/eventing_upsert_function.cxx +9 -3
- data/ext/couchbase/core/operations/management/group_drop.cxx +3 -1
- data/ext/couchbase/core/operations/management/group_get.cxx +3 -1
- data/ext/couchbase/core/operations/management/group_upsert.cxx +11 -8
- data/ext/couchbase/core/operations/management/query_index_build.cxx +5 -2
- data/ext/couchbase/core/operations/management/query_index_create.cxx +9 -3
- data/ext/couchbase/core/operations/management/query_index_drop.cxx +11 -4
- data/ext/couchbase/core/operations/management/query_index_get_all.cxx +1 -1
- data/ext/couchbase/core/operations/management/query_index_get_all_deferred.cxx +1 -1
- data/ext/couchbase/core/operations/management/scope_drop.cxx +5 -1
- data/ext/couchbase/core/operations/management/scope_get_all.cxx +6 -1
- data/ext/couchbase/core/operations/management/search_get_stats.cxx +10 -0
- data/ext/couchbase/core/operations/management/search_index_analyze_document.cxx +3 -2
- data/ext/couchbase/core/operations/management/search_index_control_ingest.cxx +4 -3
- data/ext/couchbase/core/operations/management/search_index_control_plan_freeze.cxx +4 -3
- data/ext/couchbase/core/operations/management/search_index_control_query.cxx +4 -3
- data/ext/couchbase/core/operations/management/search_index_drop.cxx +2 -2
- data/ext/couchbase/core/operations/management/search_index_get.cxx +2 -2
- data/ext/couchbase/core/operations/management/search_index_get_documents_count.cxx +3 -2
- data/ext/couchbase/core/operations/management/search_index_get_stats.cxx +3 -1
- data/ext/couchbase/core/operations/management/search_index_upsert.cxx +2 -2
- data/ext/couchbase/core/operations/management/user_drop.cxx +3 -1
- data/ext/couchbase/core/operations/management/user_get.cxx +3 -1
- data/ext/couchbase/core/operations/management/user_upsert.cxx +12 -9
- data/ext/couchbase/core/operations/management/view_index_drop.cxx +1 -1
- data/ext/couchbase/core/operations/management/view_index_get.cxx +1 -1
- data/ext/couchbase/core/operations/management/view_index_upsert.cxx +1 -1
- data/ext/couchbase/core/operations/operation_traits.hxx +18 -0
- data/ext/couchbase/core/operations/query_response_parsing.cxx +211 -0
- data/ext/couchbase/core/operations/query_response_parsing.hxx +60 -0
- data/ext/couchbase/core/operations_fwd.hxx +3 -3
- data/ext/couchbase/core/origin.cxx +54 -26
- data/ext/couchbase/core/origin.hxx +12 -0
- data/ext/couchbase/core/orphan_reporter.cxx +2 -1
- data/ext/couchbase/core/platform/random.cc +7 -7
- data/ext/couchbase/core/protocol/client_request.cxx +2 -2
- data/ext/couchbase/core/protocol/client_request.hxx +38 -21
- data/ext/couchbase/core/protocol/client_response.cxx +11 -3
- data/ext/couchbase/core/protocol/client_response.hxx +27 -6
- data/ext/couchbase/core/protocol/cmd_append.cxx +2 -2
- data/ext/couchbase/core/protocol/cmd_cluster_map_change_notification.cxx +2 -2
- data/ext/couchbase/core/protocol/cmd_decrement.cxx +6 -6
- data/ext/couchbase/core/protocol/cmd_get.cxx +1 -1
- data/ext/couchbase/core/protocol/cmd_get_and_lock.cxx +2 -2
- data/ext/couchbase/core/protocol/cmd_get_and_touch.cxx +2 -2
- data/ext/couchbase/core/protocol/cmd_get_cluster_config.cxx +6 -4
- data/ext/couchbase/core/protocol/cmd_get_collection_id.cxx +2 -2
- data/ext/couchbase/core/protocol/cmd_get_error_map.cxx +1 -1
- data/ext/couchbase/core/protocol/cmd_get_meta.cxx +4 -4
- data/ext/couchbase/core/protocol/cmd_get_replica.cxx +1 -1
- data/ext/couchbase/core/protocol/cmd_hello.cxx +1 -1
- data/ext/couchbase/core/protocol/cmd_increment.cxx +6 -6
- data/ext/couchbase/core/protocol/cmd_insert.cxx +4 -4
- data/ext/couchbase/core/protocol/cmd_lookup_in.cxx +4 -3
- data/ext/couchbase/core/protocol/cmd_lookup_in_replica.cxx +4 -3
- data/ext/couchbase/core/protocol/cmd_mutate_in.cxx +10 -9
- data/ext/couchbase/core/protocol/cmd_mutate_in.hxx +10 -10
- data/ext/couchbase/core/protocol/cmd_observe_seqno.cxx +7 -7
- data/ext/couchbase/core/protocol/cmd_prepend.cxx +2 -2
- data/ext/couchbase/core/protocol/cmd_remove.cxx +2 -2
- data/ext/couchbase/core/protocol/cmd_replace.cxx +4 -4
- data/ext/couchbase/core/protocol/cmd_touch.cxx +1 -1
- data/ext/couchbase/core/protocol/cmd_upsert.cxx +4 -4
- data/ext/couchbase/core/protocol/datatype.hxx +118 -1
- data/ext/couchbase/core/protocol/frame_info_utils.cxx +1 -1
- data/ext/couchbase/core/protocol/magic.hxx +4 -0
- data/ext/couchbase/core/protocol/magic_fmt.hxx +3 -0
- data/ext/couchbase/core/protocol/server_request.hxx +3 -1
- data/ext/couchbase/core/protocol/status.cxx +1 -1
- data/ext/couchbase/core/protostellar/analytics_converter.hxx +171 -0
- data/ext/couchbase/core/protostellar/bucket_admin_converter.hxx +301 -0
- data/ext/couchbase/core/protostellar/collection_admin_converter.hxx +92 -0
- data/ext/couchbase/core/protostellar/component.cxx +2445 -0
- data/ext/couchbase/core/protostellar/component.hxx +391 -0
- data/ext/couchbase/core/{columnar/bootstrap_notification_subscriber.hxx → protostellar/compression_settings.hxx} +11 -10
- data/ext/couchbase/core/protostellar/credentials.cxx +233 -0
- data/ext/couchbase/core/protostellar/credentials.hxx +88 -0
- data/ext/couchbase/core/protostellar/dispatcher.cxx +57 -0
- data/ext/couchbase/core/protostellar/dispatcher.hxx +482 -0
- data/ext/couchbase/core/protostellar/error_utils.cxx +293 -0
- data/ext/couchbase/core/protostellar/error_utils.hxx +97 -0
- data/ext/couchbase/core/protostellar/json_payload.hxx +49 -0
- data/ext/couchbase/core/protostellar/kv_converter.cxx +70 -0
- data/ext/couchbase/core/protostellar/kv_converter.hxx +600 -0
- data/ext/couchbase/core/protostellar/query_converter.hxx +265 -0
- data/ext/couchbase/core/protostellar/query_index_admin_converter.hxx +291 -0
- data/ext/couchbase/core/protostellar/query_proto.hxx +73 -0
- data/ext/couchbase/core/protostellar/search_converter.hxx +244 -0
- data/ext/couchbase/core/protostellar/search_index_admin_converter.hxx +156 -0
- data/ext/couchbase/core/protostellar/view_converter.hxx +158 -0
- data/ext/couchbase/core/query_stream.cxx +447 -0
- data/ext/couchbase/core/query_stream.hxx +141 -0
- data/ext/couchbase/core/query_stream_component.cxx +243 -0
- data/ext/couchbase/core/query_stream_component.hxx +68 -0
- data/ext/couchbase/core/range_scan_load_balancer.cxx +15 -8
- data/ext/couchbase/core/range_scan_orchestrator.cxx +15 -3
- data/ext/couchbase/core/response_handler.hxx +41 -4
- data/ext/couchbase/core/row_streamer.cxx +332 -46
- data/ext/couchbase/core/row_streamer.hxx +31 -1
- data/ext/couchbase/core/row_streamer_options.hxx +55 -0
- data/ext/couchbase/core/sasl/client.h +3 -0
- data/ext/couchbase/core/search_scoring.hxx +66 -0
- data/ext/couchbase/core/stream_error_details.hxx +69 -0
- data/ext/couchbase/core/timeout_defaults.hxx +0 -1
- data/ext/couchbase/core/topology/capabilities.hxx +6 -0
- data/ext/couchbase/core/topology/capabilities_fmt.hxx +3 -0
- data/ext/couchbase/core/topology/configuration.cxx +21 -6
- data/ext/couchbase/core/topology/configuration.hxx +29 -8
- data/ext/couchbase/core/topology/configuration_json.hxx +3 -0
- data/ext/couchbase/core/topology/error_map_json.hxx +3 -1
- data/ext/couchbase/core/tracing/threshold_logging_tracer.cxx +70 -4
- data/ext/couchbase/core/tracing/threshold_logging_tracer.hxx +10 -0
- data/ext/couchbase/core/transactions/active_transaction_record.cxx +0 -34
- data/ext/couchbase/core/transactions/attempt_context_impl.cxx +108 -63
- data/ext/couchbase/core/transactions/attempt_context_impl.hxx +19 -2
- data/ext/couchbase/core/transactions/error_list.hxx +2 -2
- data/ext/couchbase/core/transactions/get_multi_fetch.hxx +160 -0
- data/ext/couchbase/core/transactions/get_multi_orchestrator.cxx +326 -125
- data/ext/couchbase/core/transactions/get_multi_transaction_id.hxx +62 -0
- data/ext/couchbase/core/transactions/internal/atr_entry.hxx +22 -2
- data/ext/couchbase/core/transactions/internal/transaction_context.hxx +2 -2
- data/ext/couchbase/core/transactions/internal/transactions_cleanup.hxx +23 -1
- data/ext/couchbase/core/transactions/internal/utils.hxx +50 -14
- data/ext/couchbase/core/transactions/staged_mutation.cxx +23 -18
- data/ext/couchbase/core/transactions/staged_mutation.hxx +15 -4
- data/ext/couchbase/core/transactions/transaction_context.cxx +55 -40
- data/ext/couchbase/core/transactions/transaction_get_result.hxx +16 -0
- data/ext/couchbase/core/transactions/transactions.cxx +3 -55
- data/ext/couchbase/core/transactions/transactions_cleanup.cxx +165 -72
- data/ext/couchbase/core/transactions/transactions_config.cxx +0 -11
- data/ext/couchbase/core/transactions/utils.cxx +10 -0
- data/ext/couchbase/core/transactions/waitable_op_list.hxx +2 -2
- data/ext/couchbase/core/transactions.hxx +9 -9
- data/ext/couchbase/core/utils/byteswap.hxx +166 -9
- data/ext/couchbase/core/utils/connection_string.cxx +50 -85
- data/ext/couchbase/core/utils/connection_string.hxx +15 -0
- data/ext/couchbase/core/{columnar/backoff_calculator.hxx → utils/deadline.hxx} +13 -13
- data/ext/couchbase/core/utils/duration_parser.cxx +1 -1
- data/ext/couchbase/core/utils/json_streaming_lexer.cxx +48 -5
- data/ext/couchbase/core/utils/json_streaming_lexer.hxx +4 -1
- data/ext/couchbase/core/utils/movable_function.hxx +301 -52
- data/ext/couchbase/core/utils/name_codec.hxx +154 -11
- data/ext/couchbase/core/{columnar/retry_info.hxx → utils/process_id.hxx} +18 -13
- data/ext/couchbase/core/utils/url_codec.cxx +12 -51
- data/ext/couchbase/core/websocket_codec.cxx +13 -37
- data/ext/couchbase/couchbase/analytics_options.hxx +21 -10
- data/ext/couchbase/couchbase/analytics_row.hxx +105 -0
- data/ext/couchbase/couchbase/analytics_stream_result.hxx +266 -0
- data/ext/couchbase/couchbase/boolean_query.hxx +3 -3
- data/ext/couchbase/couchbase/bucket.hxx +57 -0
- data/ext/couchbase/couchbase/cluster.hxx +183 -5
- data/ext/couchbase/{core/columnar/security_options.hxx → couchbase/cluster_state.hxx} +18 -14
- data/ext/couchbase/couchbase/codec/lenient_json_transcoder.hxx +69 -0
- data/ext/couchbase/couchbase/collection.hxx +234 -14
- data/ext/couchbase/couchbase/common_durability_options.hxx +18 -3
- data/ext/couchbase/couchbase/conjunction_query.hxx +1 -1
- data/ext/couchbase/couchbase/create_dataset_analytics_options.hxx +6 -1
- data/ext/couchbase/couchbase/date_range_query.hxx +2 -2
- data/ext/couchbase/couchbase/decrement_options.hxx +1 -1
- data/ext/couchbase/couchbase/disjunction_query.hxx +1 -1
- data/ext/couchbase/couchbase/error.hxx +32 -0
- data/ext/couchbase/couchbase/error_codes.hxx +33 -1
- data/ext/couchbase/couchbase/geo_bounding_box_query.hxx +1 -1
- data/ext/couchbase/couchbase/geo_distance_query.hxx +1 -1
- data/ext/couchbase/couchbase/geo_polygon_query.hxx +1 -1
- data/ext/couchbase/couchbase/get_replica_options.hxx +68 -0
- data/ext/couchbase/couchbase/get_replica_result.hxx +5 -3
- data/ext/couchbase/couchbase/get_replica_strategy.hxx +161 -0
- data/ext/couchbase/couchbase/get_result.hxx +1 -0
- data/ext/couchbase/couchbase/increment_options.hxx +1 -1
- data/ext/couchbase/couchbase/insert_options.hxx +1 -1
- data/ext/couchbase/couchbase/match_phrase_query.hxx +1 -1
- data/ext/couchbase/couchbase/match_query.hxx +1 -1
- data/ext/couchbase/couchbase/mutate_in_options.hxx +3 -3
- data/ext/couchbase/couchbase/network_options.hxx +1 -1
- data/ext/couchbase/couchbase/node_id.hxx +42 -14
- data/ext/couchbase/couchbase/node_id_for_options.hxx +7 -1
- data/ext/couchbase/couchbase/node_ids_options.hxx +8 -2
- data/ext/couchbase/couchbase/numeric_range_query.hxx +1 -1
- data/ext/couchbase/couchbase/phrase_query.hxx +1 -1
- data/ext/couchbase/couchbase/prefix_query.hxx +1 -1
- data/ext/couchbase/couchbase/query_options.hxx +23 -12
- data/ext/couchbase/couchbase/query_row.hxx +111 -0
- data/ext/couchbase/couchbase/query_stream_result.hxx +302 -0
- data/ext/couchbase/couchbase/query_string_query.hxx +3 -3
- data/ext/couchbase/couchbase/regexp_query.hxx +1 -1
- data/ext/couchbase/couchbase/replace_options.hxx +3 -3
- data/ext/couchbase/couchbase/result.hxx +14 -3
- data/ext/couchbase/couchbase/scan_result_item.hxx +1 -0
- data/ext/couchbase/couchbase/scope.hxx +85 -2
- data/ext/couchbase/couchbase/search_options.hxx +58 -8
- data/ext/couchbase/couchbase/search_scoring.hxx +94 -0
- data/ext/couchbase/couchbase/search_scoring_none.hxx +51 -0
- data/ext/couchbase/couchbase/search_scoring_reciprocal_rank_fusion.hxx +88 -0
- data/ext/couchbase/couchbase/search_scoring_relative_score_fusion.hxx +70 -0
- data/ext/couchbase/couchbase/term_range_query.hxx +1 -1
- data/ext/couchbase/couchbase/tracing/request_span.hxx +46 -0
- data/ext/couchbase/couchbase/transactions/transaction_get_multi_replicas_from_preferred_server_group_result.hxx +23 -21
- data/ext/couchbase/couchbase/transactions/transaction_get_multi_result.hxx +24 -19
- data/ext/couchbase/couchbase/transactions/transaction_get_result.hxx +17 -3
- data/ext/couchbase/couchbase/transactions/transactions_config.hxx +4 -2
- data/ext/couchbase/couchbase/transactions.hxx +27 -18
- data/ext/couchbase/couchbase/upsert_options.hxx +3 -3
- data/ext/couchbase/couchbase/vector_query.hxx +1 -1
- data/ext/couchbase/couchbase/wait_until_ready_options.hxx +111 -0
- data/ext/couchbase/couchbase/wildcard_query.hxx +1 -1
- data/ext/extconf.rb +15 -10
- data/ext/rcb_analytics.cxx +82 -102
- data/ext/rcb_backend.cxx +42 -36
- data/ext/rcb_backend.hxx +2 -0
- data/ext/rcb_buckets.cxx +47 -59
- data/ext/rcb_collections.cxx +42 -52
- data/ext/rcb_crud.cxx +345 -224
- data/ext/rcb_diagnostics.cxx +117 -27
- data/ext/rcb_exceptions.cxx +152 -99
- data/ext/rcb_exceptions.hxx +25 -0
- data/ext/rcb_extras.cxx +18 -19
- data/ext/rcb_hdr_histogram.cxx +19 -4
- data/ext/rcb_logger.cxx +202 -27
- data/ext/rcb_logger.hxx +12 -0
- data/ext/rcb_multi.cxx +40 -40
- data/ext/rcb_observability.cxx +7 -5
- data/ext/rcb_query.cxx +99 -142
- data/ext/rcb_range_scan.cxx +41 -35
- data/ext/rcb_search.cxx +98 -99
- data/ext/rcb_users.cxx +36 -56
- data/ext/rcb_utils.cxx +100 -37
- data/ext/rcb_utils.hxx +287 -33
- data/ext/rcb_version.cxx +1 -1
- data/ext/rcb_views.cxx +55 -51
- data/lib/active_support/cache/couchbase_store.rb +77 -12
- data/lib/couchbase/bucket.rb +20 -0
- data/lib/couchbase/cluster.rb +17 -0
- data/lib/couchbase/collection.rb +36 -1
- data/lib/couchbase/errors.rb +18 -0
- data/lib/couchbase/fork_hooks.rb +16 -7
- data/lib/couchbase/get_replica_strategy.rb +89 -0
- data/lib/couchbase/logger.rb +1 -1
- data/lib/couchbase/management/analytics_index_manager.rb +15 -15
- data/lib/couchbase/management/bucket_manager.rb +6 -6
- data/lib/couchbase/management/collection_manager.rb +6 -6
- data/lib/couchbase/management/query_index_manager.rb +7 -7
- data/lib/couchbase/management/search_index_manager.rb +13 -13
- data/lib/couchbase/management/user_manager.rb +10 -10
- data/lib/couchbase/management/view_index_manager.rb +5 -5
- data/lib/couchbase/options.rb +174 -42
- data/lib/couchbase/protostellar/bucket.rb +4 -0
- data/lib/couchbase/protostellar/cluster.rb +4 -0
- data/lib/couchbase/protostellar/collection.rb +4 -0
- data/lib/couchbase/protostellar/error_handling.rb +2 -1
- data/lib/couchbase/protostellar/request.rb +1 -0
- data/lib/couchbase/protostellar/request_generator/kv.rb +16 -2
- data/lib/couchbase/protostellar/request_generator/search.rb +17 -1
- data/lib/couchbase/protostellar/retry/orchestrator.rb +3 -2
- data/lib/couchbase/protostellar/retry/strategies/fail_fast.rb +33 -0
- data/lib/couchbase/protostellar/retry/strategies.rb +1 -0
- data/lib/couchbase/search_options.rb +95 -6
- data/lib/couchbase/version.rb +1 -1
- metadata +91 -33
- data/ext/0001-fix-build-for-mingw-w64-ucrt-x86_64-toolchain.patch +0 -40
- data/ext/couchbase/core/columnar/agent.hxx +0 -71
- data/ext/couchbase/core/columnar/agent_config.hxx +0 -59
- data/ext/couchbase/core/columnar/background_bootstrap_listener.hxx +0 -42
- data/ext/couchbase/core/columnar/backoff_calculator.cxx +0 -62
- data/ext/couchbase/core/columnar/columnar_agent.cxx +0 -147
- data/ext/couchbase/core/columnar/columnar_agent_config.cxx +0 -48
- data/ext/couchbase/core/columnar/columnar_error.cxx +0 -51
- data/ext/couchbase/core/columnar/database_management_options.hxx +0 -56
- data/ext/couchbase/core/columnar/error.hxx +0 -51
- data/ext/couchbase/core/columnar/error_codes.cxx +0 -107
- data/ext/couchbase/core/columnar/error_codes.hxx +0 -75
- data/ext/couchbase/core/columnar/management_component.cxx +0 -300
- data/ext/couchbase/core/columnar/management_component.hxx +0 -56
- data/ext/couchbase/core/columnar/query_component.cxx +0 -523
- data/ext/couchbase/core/columnar/query_component.hxx +0 -57
- data/ext/couchbase/core/columnar/query_options.hxx +0 -59
- data/ext/couchbase/core/columnar/query_result.cxx +0 -130
- data/ext/couchbase/core/columnar/query_result.hxx +0 -78
- data/ext/couchbase/core/io/config_tracker.cxx +0 -687
- data/ext/couchbase/core/io/config_tracker.hxx +0 -123
|
@@ -0,0 +1,293 @@
|
|
|
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 "core/protostellar/error_utils.hxx"
|
|
19
|
+
|
|
20
|
+
#include "core/document_id.hxx"
|
|
21
|
+
#include "core/error_context/key_value_error_context.hxx"
|
|
22
|
+
|
|
23
|
+
#include <couchbase/error_codes.hxx>
|
|
24
|
+
|
|
25
|
+
#include <google/rpc/error_details.pb.h>
|
|
26
|
+
#include <google/rpc/status.pb.h>
|
|
27
|
+
|
|
28
|
+
#include <optional>
|
|
29
|
+
#include <string>
|
|
30
|
+
|
|
31
|
+
namespace couchbase::core::protostellar
|
|
32
|
+
{
|
|
33
|
+
namespace
|
|
34
|
+
{
|
|
35
|
+
// Returns the first detail block of type T packed into the rich status, if any. Per RFC 77 ("Other
|
|
36
|
+
// errors") only the first applicable block is considered.
|
|
37
|
+
template<typename T>
|
|
38
|
+
auto
|
|
39
|
+
find_detail(const google::rpc::Status& rich) -> std::optional<T>
|
|
40
|
+
{
|
|
41
|
+
for (const auto& any : rich.details()) {
|
|
42
|
+
T message;
|
|
43
|
+
if (any.UnpackTo(&message)) {
|
|
44
|
+
return message;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return std::nullopt;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// FAILED_PRECONDITION -> the specific KV error carried by PreconditionFailure.type
|
|
51
|
+
// (errorhandler.go).
|
|
52
|
+
auto
|
|
53
|
+
map_precondition(const std::string& type) -> std::error_code
|
|
54
|
+
{
|
|
55
|
+
if (type == "LOCKED") {
|
|
56
|
+
return errc::key_value::document_locked;
|
|
57
|
+
}
|
|
58
|
+
if (type == "NOT_LOCKED") {
|
|
59
|
+
return errc::key_value::document_not_locked;
|
|
60
|
+
}
|
|
61
|
+
if (type == "DOC_TOO_DEEP") {
|
|
62
|
+
return errc::key_value::value_too_deep;
|
|
63
|
+
}
|
|
64
|
+
if (type == "DOC_NOT_JSON") {
|
|
65
|
+
return errc::key_value::document_not_json;
|
|
66
|
+
}
|
|
67
|
+
if (type == "PATH_MISMATCH") {
|
|
68
|
+
return errc::key_value::path_mismatch;
|
|
69
|
+
}
|
|
70
|
+
if (type == "VALUE_OUT_OF_RANGE") {
|
|
71
|
+
return errc::key_value::value_invalid;
|
|
72
|
+
}
|
|
73
|
+
if (type == "PATH_VALUE_OUT_OF_RANGE") {
|
|
74
|
+
return errc::key_value::number_too_big;
|
|
75
|
+
}
|
|
76
|
+
if (type == "VALUE_TOO_LARGE") {
|
|
77
|
+
return errc::key_value::value_too_large;
|
|
78
|
+
}
|
|
79
|
+
if (type == "DOC_NOT_NUMERIC") {
|
|
80
|
+
// Increment/Decrement against a document that is not a counter. Only those two operations can
|
|
81
|
+
// produce it, and without this it arrives as internal_server_failure -- telling the caller the
|
|
82
|
+
// cluster is broken when their document simply is not a number.
|
|
83
|
+
return errc::key_value::delta_invalid;
|
|
84
|
+
}
|
|
85
|
+
if (type == "FLUSH_DISABLED") {
|
|
86
|
+
// The one management precondition the gateway raises. Without it a flush against a bucket that
|
|
87
|
+
// simply has flush turned off reports internal_server_failure, where the caller can act on
|
|
88
|
+
// knowing that flush is disabled.
|
|
89
|
+
return errc::management::bucket_not_flushable;
|
|
90
|
+
}
|
|
91
|
+
if (type == "DURABILITY_IMPOSSIBLE") {
|
|
92
|
+
// Fewer live nodes than the requested durability needs. Actionable by the caller (ask for less,
|
|
93
|
+
// or grow the cluster), so it must not be flattened into a generic server failure either.
|
|
94
|
+
return errc::key_value::durability_impossible;
|
|
95
|
+
}
|
|
96
|
+
// POISONED_CAS deliberately falls through: the gateway can emit it, but the SDK has no error for
|
|
97
|
+
// a CAS that the server considers corrupt, and inventing one here would be a guess. Revisit if
|
|
98
|
+
// couchbase::errc grows a member for it.
|
|
99
|
+
return errc::common::internal_server_failure;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// NOT_FOUND/ALREADY_EXISTS carry a ResourceInfo whose type selects the specific SDK error.
|
|
103
|
+
auto
|
|
104
|
+
map_not_found(const std::string& resource_type) -> std::error_code
|
|
105
|
+
{
|
|
106
|
+
if (resource_type == "bucket") {
|
|
107
|
+
return errc::common::bucket_not_found;
|
|
108
|
+
}
|
|
109
|
+
if (resource_type == "scope") {
|
|
110
|
+
return errc::common::scope_not_found;
|
|
111
|
+
}
|
|
112
|
+
if (resource_type == "collection") {
|
|
113
|
+
return errc::common::collection_not_found;
|
|
114
|
+
}
|
|
115
|
+
if (resource_type == "queryindex" || resource_type == "searchindex") {
|
|
116
|
+
return errc::common::index_not_found;
|
|
117
|
+
}
|
|
118
|
+
if (resource_type == "path") {
|
|
119
|
+
return errc::key_value::path_not_found;
|
|
120
|
+
}
|
|
121
|
+
return errc::key_value::document_not_found;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
auto
|
|
125
|
+
map_already_exists(const std::string& resource_type) -> std::error_code
|
|
126
|
+
{
|
|
127
|
+
if (resource_type == "bucket") {
|
|
128
|
+
return errc::management::bucket_exists;
|
|
129
|
+
}
|
|
130
|
+
if (resource_type == "scope") {
|
|
131
|
+
return errc::management::scope_exists;
|
|
132
|
+
}
|
|
133
|
+
if (resource_type == "collection") {
|
|
134
|
+
return errc::management::collection_exists;
|
|
135
|
+
}
|
|
136
|
+
if (resource_type == "queryindex" || resource_type == "searchindex") {
|
|
137
|
+
return errc::common::index_exists;
|
|
138
|
+
}
|
|
139
|
+
if (resource_type == "path") {
|
|
140
|
+
return errc::key_value::path_exists;
|
|
141
|
+
}
|
|
142
|
+
return errc::key_value::document_exists;
|
|
143
|
+
}
|
|
144
|
+
} // namespace
|
|
145
|
+
|
|
146
|
+
auto
|
|
147
|
+
map_status_code(grpc::StatusCode code, operation_kind kind) -> std::error_code
|
|
148
|
+
{
|
|
149
|
+
switch (code) {
|
|
150
|
+
case grpc::StatusCode::OK:
|
|
151
|
+
return {};
|
|
152
|
+
case grpc::StatusCode::NOT_FOUND:
|
|
153
|
+
return errc::key_value::document_not_found;
|
|
154
|
+
case grpc::StatusCode::ALREADY_EXISTS:
|
|
155
|
+
return errc::key_value::document_exists;
|
|
156
|
+
case grpc::StatusCode::ABORTED:
|
|
157
|
+
// gRPC ABORTED is the canonical concurrency-conflict code; for KV that is a CAS mismatch.
|
|
158
|
+
return errc::common::cas_mismatch;
|
|
159
|
+
case grpc::StatusCode::DEADLINE_EXCEEDED:
|
|
160
|
+
// A deadline on a mutation is genuinely ambiguous -- the write may already have been applied
|
|
161
|
+
// server-side -- so it must not tell the retry layer it is safe to replay a
|
|
162
|
+
// possibly-non-idempotent operation. A read changed nothing by definition, so reporting it
|
|
163
|
+
// as ambiguous would be strictly wrong: it claims the operation may have mutated state that
|
|
164
|
+
// it cannot have touched, and a caller that declines to retry ambiguous operations would
|
|
165
|
+
// give up on an operation that is perfectly safe to repeat.
|
|
166
|
+
return kind == operation_kind::read_only ? errc::common::unambiguous_timeout
|
|
167
|
+
: errc::common::ambiguous_timeout;
|
|
168
|
+
case grpc::StatusCode::CANCELLED:
|
|
169
|
+
return errc::common::request_canceled;
|
|
170
|
+
case grpc::StatusCode::UNAUTHENTICATED:
|
|
171
|
+
case grpc::StatusCode::PERMISSION_DENIED:
|
|
172
|
+
return errc::common::authentication_failure;
|
|
173
|
+
case grpc::StatusCode::INVALID_ARGUMENT:
|
|
174
|
+
case grpc::StatusCode::OUT_OF_RANGE:
|
|
175
|
+
return errc::common::invalid_argument;
|
|
176
|
+
case grpc::StatusCode::UNIMPLEMENTED:
|
|
177
|
+
return errc::common::feature_not_available;
|
|
178
|
+
case grpc::StatusCode::UNAVAILABLE:
|
|
179
|
+
return errc::common::temporary_failure;
|
|
180
|
+
case grpc::StatusCode::RESOURCE_EXHAUSTED:
|
|
181
|
+
return errc::common::rate_limited;
|
|
182
|
+
case grpc::StatusCode::INTERNAL:
|
|
183
|
+
case grpc::StatusCode::UNKNOWN:
|
|
184
|
+
case grpc::StatusCode::DATA_LOSS:
|
|
185
|
+
case grpc::StatusCode::FAILED_PRECONDITION:
|
|
186
|
+
default:
|
|
187
|
+
return errc::common::internal_server_failure;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
auto
|
|
192
|
+
map_status(const grpc::Status& status, operation_kind kind) -> std::error_code
|
|
193
|
+
{
|
|
194
|
+
const auto code = status.error_code();
|
|
195
|
+
|
|
196
|
+
// The typed google.rpc.Status details refine three codes into specific SDK errors (RFC 77 "Other
|
|
197
|
+
// errors" + errorhandler.go). Everything else is keyed on the bare gRPC code, plus `kind` for
|
|
198
|
+
// DEADLINE_EXCEEDED (see map_status_code).
|
|
199
|
+
google::rpc::Status rich;
|
|
200
|
+
const bool have_rich =
|
|
201
|
+
!status.error_details().empty() && rich.ParseFromString(status.error_details());
|
|
202
|
+
|
|
203
|
+
switch (code) {
|
|
204
|
+
case grpc::StatusCode::FAILED_PRECONDITION:
|
|
205
|
+
if (have_rich) {
|
|
206
|
+
if (auto failure = find_detail<google::rpc::PreconditionFailure>(rich);
|
|
207
|
+
failure && failure->violations_size() > 0) {
|
|
208
|
+
return map_precondition(failure->violations(0).type());
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
return errc::common::internal_server_failure;
|
|
212
|
+
case grpc::StatusCode::NOT_FOUND:
|
|
213
|
+
if (have_rich) {
|
|
214
|
+
if (auto info = find_detail<google::rpc::ResourceInfo>(rich)) {
|
|
215
|
+
return map_not_found(info->resource_type());
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
return errc::key_value::document_not_found;
|
|
219
|
+
case grpc::StatusCode::ALREADY_EXISTS:
|
|
220
|
+
if (have_rich) {
|
|
221
|
+
if (auto info = find_detail<google::rpc::ResourceInfo>(rich)) {
|
|
222
|
+
return map_already_exists(info->resource_type());
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
return errc::key_value::document_exists;
|
|
226
|
+
default:
|
|
227
|
+
return map_status_code(code, kind);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
auto
|
|
232
|
+
error_message(const grpc::Status& status) -> std::string
|
|
233
|
+
{
|
|
234
|
+
if (const auto& details = status.error_details(); !details.empty()) {
|
|
235
|
+
google::rpc::Status rich;
|
|
236
|
+
if (rich.ParseFromString(details) && !rich.message().empty()) {
|
|
237
|
+
return rich.message();
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
return status.error_message();
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
auto
|
|
244
|
+
retry_reason_for(std::error_code ec) -> std::optional<couchbase::retry_reason>
|
|
245
|
+
{
|
|
246
|
+
// UNAVAILABLE maps to temporary_failure (error_utils map_status_code): the call did not reach a
|
|
247
|
+
// healthy server, so it is safe to retry (even for mutations — the strategy's
|
|
248
|
+
// allows_non_idempotent_retry(service_not_available) permits it). Everything else is terminal at
|
|
249
|
+
// the transport: timeouts consumed the budget, cas_mismatch/auth/not_found are semantic.
|
|
250
|
+
if (ec == errc::common::temporary_failure) {
|
|
251
|
+
return couchbase::retry_reason::service_not_available;
|
|
252
|
+
}
|
|
253
|
+
// A locked document (FAILED_PRECONDITION "LOCKED") is retried with backoff per RFC 77.
|
|
254
|
+
if (ec == errc::key_value::document_locked) {
|
|
255
|
+
return couchbase::retry_reason::key_value_locked;
|
|
256
|
+
}
|
|
257
|
+
return std::nullopt;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
auto
|
|
261
|
+
make_error_context(const grpc::Status& status,
|
|
262
|
+
const document_id& id,
|
|
263
|
+
operation_kind kind,
|
|
264
|
+
std::size_t retry_attempts,
|
|
265
|
+
std::set<couchbase::retry_reason> retry_reasons) -> key_value_error_context
|
|
266
|
+
{
|
|
267
|
+
const auto ec = map_status(status, kind);
|
|
268
|
+
std::optional<key_value_extended_error_info> extended{};
|
|
269
|
+
if (!status.ok()) {
|
|
270
|
+
if (auto message = error_message(status); !message.empty()) {
|
|
271
|
+
extended.emplace(std::string{}, std::move(message));
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
return key_value_error_context{
|
|
275
|
+
{},
|
|
276
|
+
ec,
|
|
277
|
+
{},
|
|
278
|
+
{},
|
|
279
|
+
retry_attempts,
|
|
280
|
+
std::move(retry_reasons),
|
|
281
|
+
id.key(),
|
|
282
|
+
id.bucket(),
|
|
283
|
+
id.scope(),
|
|
284
|
+
id.collection(),
|
|
285
|
+
0,
|
|
286
|
+
{},
|
|
287
|
+
couchbase::cas{},
|
|
288
|
+
{},
|
|
289
|
+
std::move(extended),
|
|
290
|
+
};
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
} // namespace couchbase::core::protostellar
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
|
|
2
|
+
/*
|
|
3
|
+
* Copyright 2026. Couchbase, Inc.
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
#pragma once
|
|
19
|
+
|
|
20
|
+
#include <couchbase/retry_reason.hxx>
|
|
21
|
+
|
|
22
|
+
#include <grpcpp/grpcpp.h>
|
|
23
|
+
|
|
24
|
+
#include <cstddef>
|
|
25
|
+
#include <optional>
|
|
26
|
+
#include <set>
|
|
27
|
+
#include <string>
|
|
28
|
+
#include <system_error>
|
|
29
|
+
|
|
30
|
+
namespace couchbase::core
|
|
31
|
+
{
|
|
32
|
+
struct document_id;
|
|
33
|
+
class key_value_error_context;
|
|
34
|
+
} // namespace couchbase::core
|
|
35
|
+
|
|
36
|
+
namespace couchbase::core::protostellar
|
|
37
|
+
{
|
|
38
|
+
|
|
39
|
+
// Whether the operation whose failure is being mapped can have changed server state. This is the
|
|
40
|
+
// bit RFC 77 keys the DEADLINE_EXCEEDED mapping on, in its "Other errors" table:
|
|
41
|
+
//
|
|
42
|
+
// "Readonly ops: UnambiguousTimeoutException Otherwise: AmbiguousTimeoutException [...] Remember
|
|
43
|
+
// the 'Ambiguous' refers to whether the operation may have mutated state. This needs to be based
|
|
44
|
+
// on a readonly status, not an idempotent status. An upsert op is idempotent but mutates state."
|
|
45
|
+
//
|
|
46
|
+
// So it is deliberately not idempotency: the two disagree exactly where it matters, and keying on
|
|
47
|
+
// idempotency would report a timed-out upsert as unambiguous -- telling the caller a write
|
|
48
|
+
// definitely did not happen when it may well have.
|
|
49
|
+
//
|
|
50
|
+
// It is also not "returns a value to the user". get_and_lock and get_and_touch read a document but
|
|
51
|
+
// take a lock / rewrite the expiry as they do, so they are `mutating` here despite reading.
|
|
52
|
+
enum class operation_kind {
|
|
53
|
+
read_only,
|
|
54
|
+
mutating,
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
// Map a bare gRPC status code to a couchbase error_code. OK yields a default-constructed
|
|
58
|
+
// (success) error_code. Exposed separately from map_status so it can be unit-tested directly.
|
|
59
|
+
[[nodiscard]] auto
|
|
60
|
+
map_status_code(grpc::StatusCode code, operation_kind kind) -> std::error_code;
|
|
61
|
+
|
|
62
|
+
// Map a gRPC status to a couchbase error_code. Keyed on the status code, with the typed
|
|
63
|
+
// google.rpc.Status details (see error_message) refining FAILED_PRECONDITION, NOT_FOUND, and
|
|
64
|
+
// ALREADY_EXISTS into specific KV/management errors.
|
|
65
|
+
[[nodiscard]] auto
|
|
66
|
+
map_status(const grpc::Status& status, operation_kind kind) -> std::error_code;
|
|
67
|
+
|
|
68
|
+
// Human-readable message for a failed status: the message from the attached google.rpc.Status
|
|
69
|
+
// rich-error details when present, otherwise the plain gRPC status message.
|
|
70
|
+
[[nodiscard]] auto
|
|
71
|
+
error_message(const grpc::Status& status) -> std::string;
|
|
72
|
+
|
|
73
|
+
// Build a KV error context from a gRPC status: maps the status code to an error_code and, on
|
|
74
|
+
// failure, attaches the server-provided message (see error_message) as the context's
|
|
75
|
+
// human-readable explanation so callers see why the gateway rejected the operation.
|
|
76
|
+
//
|
|
77
|
+
// The retry counters are parameters rather than fixed at zero because only the caller knows them:
|
|
78
|
+
// the retry loop lives in cluster_impl and accumulates them across attempts, while this function
|
|
79
|
+
// sees one attempt at a time. RFC 77 makes them part of the error context, so a couchbase2
|
|
80
|
+
// operation that was retried has to report it the way the classic transport does
|
|
81
|
+
// (core/error_context/key_value.cxx carries the same pair for the same reason).
|
|
82
|
+
[[nodiscard]] auto
|
|
83
|
+
make_error_context(const grpc::Status& status,
|
|
84
|
+
const document_id& id,
|
|
85
|
+
operation_kind kind,
|
|
86
|
+
std::size_t retry_attempts = 0,
|
|
87
|
+
std::set<couchbase::retry_reason> retry_reasons = {}) -> key_value_error_context;
|
|
88
|
+
|
|
89
|
+
// Classify a mapped error_code for the couchbase2 retry loop: returns the retry_reason to feed the
|
|
90
|
+
// retry strategy, or nullopt when the error is not retryable at the transport. Transport-level
|
|
91
|
+
// unavailability (UNAVAILABLE -> temporary_failure) and a locked document (document_locked ->
|
|
92
|
+
// key_value_locked, RFC 77) retry; timeouts, cas mismatches, auth, etc. are terminal. Idempotency
|
|
93
|
+
// is enforced downstream by the retry strategy, not here.
|
|
94
|
+
[[nodiscard]] auto
|
|
95
|
+
retry_reason_for(std::error_code ec) -> std::optional<couchbase::retry_reason>;
|
|
96
|
+
|
|
97
|
+
} // namespace couchbase::core::protostellar
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
|
|
2
|
+
/*
|
|
3
|
+
* Copyright 2026. Couchbase, Inc.
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
#pragma once
|
|
19
|
+
|
|
20
|
+
#include "core/json_string.hxx"
|
|
21
|
+
|
|
22
|
+
#include <string>
|
|
23
|
+
|
|
24
|
+
namespace couchbase::core::protostellar
|
|
25
|
+
{
|
|
26
|
+
// The JSON a json_string carries, whichever variant arm holds it.
|
|
27
|
+
//
|
|
28
|
+
// json_string is a variant over nullptr/std::string/std::vector<std::byte>, and str() returns a
|
|
29
|
+
// reference to a static empty string unless the std::string arm is active. Statement parameters
|
|
30
|
+
// never use that arm: the public options types declare them as std::vector<codec::binary> (see
|
|
31
|
+
// couchbase/query_options.hxx) and core/impl/query.cxx moves each one in, which selects the binary
|
|
32
|
+
// arm -- so reading them with str() alone sends every parameter as "".
|
|
33
|
+
//
|
|
34
|
+
// Returning the bytes as they came in also avoids a parse-and-regenerate round trip, since the
|
|
35
|
+
// proto fields these feed are `bytes` rather than structured messages.
|
|
36
|
+
//
|
|
37
|
+
// Lives here rather than in one converter because every service whose request carries
|
|
38
|
+
// caller-supplied JSON needs it, and a per-converter copy is how the query defect reached the
|
|
39
|
+
// analytics converter in the first place.
|
|
40
|
+
[[nodiscard]] inline auto
|
|
41
|
+
json_payload(const core::json_string& value) -> std::string
|
|
42
|
+
{
|
|
43
|
+
if (value.is_binary()) {
|
|
44
|
+
const auto& bytes = value.bytes();
|
|
45
|
+
return { reinterpret_cast<const char*>(bytes.data()), bytes.size() };
|
|
46
|
+
}
|
|
47
|
+
return value.str();
|
|
48
|
+
}
|
|
49
|
+
} // namespace couchbase::core::protostellar
|
|
@@ -0,0 +1,70 @@
|
|
|
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
|
+
// snappy compression for the couchbase2 KV converter, kept out of kv_converter.hxx so the header
|
|
19
|
+
// (included by white-box tests) does not leak a dependency on <snappy.h> / the snappy library.
|
|
20
|
+
|
|
21
|
+
#include "core/protostellar/kv_converter.hxx"
|
|
22
|
+
|
|
23
|
+
#include "core/protostellar/dispatcher.hxx"
|
|
24
|
+
|
|
25
|
+
#include <snappy.h>
|
|
26
|
+
|
|
27
|
+
#include <cstddef>
|
|
28
|
+
|
|
29
|
+
namespace couchbase::core::protostellar::kv
|
|
30
|
+
{
|
|
31
|
+
auto
|
|
32
|
+
maybe_compress(const std::vector<std::byte>& value, const compression_settings& compression)
|
|
33
|
+
-> std::optional<std::string>
|
|
34
|
+
{
|
|
35
|
+
if (!compression.enabled || value.size() < compression.min_size) {
|
|
36
|
+
return std::nullopt;
|
|
37
|
+
}
|
|
38
|
+
const auto raw = utils::to_string(value);
|
|
39
|
+
std::string compressed;
|
|
40
|
+
snappy::Compress(raw.data(), raw.size(), &compressed);
|
|
41
|
+
// Only worth sending compressed when it shrinks to at most min_ratio of the original; a value
|
|
42
|
+
// landing exactly on the ratio is sent compressed, as it is in the other SDKs.
|
|
43
|
+
if (static_cast<double>(compressed.size()) <=
|
|
44
|
+
static_cast<double>(raw.size()) * compression.min_ratio) {
|
|
45
|
+
return compressed;
|
|
46
|
+
}
|
|
47
|
+
return std::nullopt;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
auto
|
|
51
|
+
snappy_uncompress(const std::string& compressed) -> std::optional<std::string>
|
|
52
|
+
{
|
|
53
|
+
// snappy::Uncompress resizes its output to the length declared in the frame header before it
|
|
54
|
+
// validates the body, so a few bytes can ask for a multi-gigabyte allocation. Read the declared
|
|
55
|
+
// length first and refuse anything the transport could not have carried: the resulting
|
|
56
|
+
// std::bad_alloc would be thrown inside a gRPC completion and take the process with it.
|
|
57
|
+
std::size_t length{};
|
|
58
|
+
if (!snappy::GetUncompressedLength(compressed.data(), compressed.size(), &length)) {
|
|
59
|
+
return std::nullopt;
|
|
60
|
+
}
|
|
61
|
+
if (length > max_receive_message_size) {
|
|
62
|
+
return std::nullopt;
|
|
63
|
+
}
|
|
64
|
+
std::string uncompressed;
|
|
65
|
+
if (snappy::Uncompress(compressed.data(), compressed.size(), &uncompressed)) {
|
|
66
|
+
return uncompressed;
|
|
67
|
+
}
|
|
68
|
+
return std::nullopt;
|
|
69
|
+
}
|
|
70
|
+
} // namespace couchbase::core::protostellar::kv
|