From ba5d0ff8bf46fdec53013023425c1cbd11fe5707 Mon Sep 17 00:00:00 2001 From: Dimitris Christodoulou Date: Tue, 7 Nov 2023 16:39:12 +0000 Subject: [PATCH 1/3] Add support for the couchbase2 protocol --- test/protostellar/error_handling_test.rb | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 test/protostellar/error_handling_test.rb diff --git a/test/protostellar/error_handling_test.rb b/test/protostellar/error_handling_test.rb new file mode 100644 index 00000000..1a405582 --- /dev/null +++ b/test/protostellar/error_handling_test.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +require "test_helper" + +require "google/rpc/code_pb" +require "google/rpc/status_pb" +require "google/rpc/error_details_pb" + +module Couchbase + module Protostellar + class ErrorHandlingTest < Minitest::Test + def setup + # Do nothing + end + + def teardown + # Do nothing + end + end + end +end From 0db860a76bf8b0d55036329ffef3a71666164f5e Mon Sep 17 00:00:00 2001 From: Dimitris Christodoulou Date: Tue, 14 Nov 2023 15:10:23 +0000 Subject: [PATCH 2/3] Add tests for the retry orchestrator --- test/protostellar/error_handling_test.rb | 21 --------------------- 1 file changed, 21 deletions(-) delete mode 100644 test/protostellar/error_handling_test.rb diff --git a/test/protostellar/error_handling_test.rb b/test/protostellar/error_handling_test.rb deleted file mode 100644 index 1a405582..00000000 --- a/test/protostellar/error_handling_test.rb +++ /dev/null @@ -1,21 +0,0 @@ -# frozen_string_literal: true - -require "test_helper" - -require "google/rpc/code_pb" -require "google/rpc/status_pb" -require "google/rpc/error_details_pb" - -module Couchbase - module Protostellar - class ErrorHandlingTest < Minitest::Test - def setup - # Do nothing - end - - def teardown - # Do nothing - end - end - end -end From 6df2005067bf6d571e540f0dee373174a5d69186 Mon Sep 17 00:00:00 2001 From: Dimitris Christodoulou Date: Tue, 14 Nov 2023 15:55:32 +0000 Subject: [PATCH 3/3] RCBC-410: Support get all/any replicas in couchbase2 --- lib/couchbase/protostellar/collection.rb | 12 ++++++--- .../protostellar/request_generator/kv.rb | 14 ++++++++++ .../protostellar/response_converter/kv.rb | 27 +++++++++++++++++++ test/crud_test.rb | 18 +++++++++++-- 4 files changed, 65 insertions(+), 6 deletions(-) diff --git a/lib/couchbase/protostellar/collection.rb b/lib/couchbase/protostellar/collection.rb index ace6a29d..ace73fa2 100644 --- a/lib/couchbase/protostellar/collection.rb +++ b/lib/couchbase/protostellar/collection.rb @@ -132,12 +132,16 @@ def mutate_in(id, specs, options = Couchbase::Options::MutateIn::DEFAULT) ResponseConverter::KV.to_mutate_in_result(resp, specs, options) end - def get_any_replica(_id, _options = Couchbase::Options::GetAnyReplica::DEFAULT) - raise Couchbase::Error::FeatureNotAvailable, "The #{Protostellar::NAME} protocol does not support get any replica" + def get_any_replica(id, options = Couchbase::Options::GetAnyReplica::DEFAULT) + req = @kv_request_generator.get_any_replica_request(id, options) + resp = @client.send_request(req) + ResponseConverter::KV.to_get_any_replica_result(resp, options) end - def get_all_replicas(_id, _options = Couchbase::Options::GetAllReplicas::DEFAULT) - raise Couchbase::Error::FeatureNotAvailable, "The #{Protostellar::NAME} protocol does not support get all replicas" + def get_all_replicas(id, options = Couchbase::Options::GetAllReplicas::DEFAULT) + req = @kv_request_generator.get_all_replicas_request(id, options) + resp = @client.send_request(req) + ResponseConverter::KV.to_get_all_replicas_result(resp, options) end def scan(_scan_type, _options = Options::Scan::DEFAULT) diff --git a/lib/couchbase/protostellar/request_generator/kv.rb b/lib/couchbase/protostellar/request_generator/kv.rb index 4a686044..a6206ce0 100644 --- a/lib/couchbase/protostellar/request_generator/kv.rb +++ b/lib/couchbase/protostellar/request_generator/kv.rb @@ -341,6 +341,20 @@ def prepend_request(id, content, options) create_kv_request(proto_req, :prepend, options) end + def get_all_replicas_request(id, options) + proto_req = Generated::KV::V1::GetAllReplicasRequest.new( + key: id, + **location + ) + + create_kv_request(proto_req, :get_all_replicas, options, idempotent: true) + end + + def get_any_replica_request(id, options) + # Uses the GetAllReplicas request and returns the first item from the result + get_all_replicas_request(id, options) + end + private def create_kv_request(proto_request, rpc, options, idempotent: false) diff --git a/lib/couchbase/protostellar/response_converter/kv.rb b/lib/couchbase/protostellar/response_converter/kv.rb index fd3da369..bed9f1e0 100644 --- a/lib/couchbase/protostellar/response_converter/kv.rb +++ b/lib/couchbase/protostellar/response_converter/kv.rb @@ -75,6 +75,33 @@ def self.to_lookup_in_result(resp, specs, options, request) end end + def self.to_get_any_replica_result(resps, options) + begin + entry = resps.next + rescue StopIteration + raise Couchbase::Error::DocumentIrretrievable, "unable to get replica of the document" + end + Couchbase::Collection::GetReplicaResult.new do |res| + res.transcoder = options.transcoder + res.cas = entry.cas + res.flags = entry.content_flags + res.encoded = entry.content + res.is_replica = entry.is_replica + end + end + + def self.to_get_all_replicas_result(resps, options) + resps.map do |entry| + Couchbase::Collection::GetReplicaResult.new do |res| + res.transcoder = options.transcoder + res.cas = entry.cas + res.flags = entry.content_flags + res.encoded = entry.content + res.is_replica = entry.is_replica + end + end + end + def self.to_mutate_in_result(resp, specs, options) Couchbase::Collection::MutateInResult.new do |res| res.cas = resp.cas diff --git a/test/crud_test.rb b/test/crud_test.rb index ab32986c..eeac78c5 100644 --- a/test/crud_test.rb +++ b/test/crud_test.rb @@ -52,8 +52,6 @@ def test_removes_documents end def test_reads_from_replica - skip("#{name}: The #{Couchbase::Protostellar::NAME} protocol does not support replica reads yet") if env.protostellar? - doc_id = uniq_id(:foo) document = {"value" => 42} options = @@ -78,6 +76,22 @@ def test_reads_from_replica end end + def test_reads_from_replica_does_not_exist + doc_id = uniq_id(:foo) + + assert_raises(Couchbase::Error::DocumentIrretrievable) do + @collection.get_any_replica(doc_id) + end + + if env.protostellar? + assert_empty @collection.get_all_replicas(doc_id) + else + assert_raises(Couchbase::Error::DocumentNotFound) do + @collection.get_all_replicas(doc_id) + end + end + end + def test_touch_sets_expiration document = {"value" => 42} doc_id = uniq_id(:foo)