Skip to content

Commit 2a19f12

Browse files
authored
RCBC-410: Support get all/any replicas in couchbase2 (#127)
1 parent 3622357 commit 2a19f12

File tree

4 files changed

+65
-6
lines changed

4 files changed

+65
-6
lines changed

lib/couchbase/protostellar/collection.rb

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -132,12 +132,16 @@ def mutate_in(id, specs, options = Couchbase::Options::MutateIn::DEFAULT)
132132
ResponseConverter::KV.to_mutate_in_result(resp, specs, options)
133133
end
134134

135-
def get_any_replica(_id, _options = Couchbase::Options::GetAnyReplica::DEFAULT)
136-
raise Couchbase::Error::FeatureNotAvailable, "The #{Protostellar::NAME} protocol does not support get any replica"
135+
def get_any_replica(id, options = Couchbase::Options::GetAnyReplica::DEFAULT)
136+
req = @kv_request_generator.get_any_replica_request(id, options)
137+
resp = @client.send_request(req)
138+
ResponseConverter::KV.to_get_any_replica_result(resp, options)
137139
end
138140

139-
def get_all_replicas(_id, _options = Couchbase::Options::GetAllReplicas::DEFAULT)
140-
raise Couchbase::Error::FeatureNotAvailable, "The #{Protostellar::NAME} protocol does not support get all replicas"
141+
def get_all_replicas(id, options = Couchbase::Options::GetAllReplicas::DEFAULT)
142+
req = @kv_request_generator.get_all_replicas_request(id, options)
143+
resp = @client.send_request(req)
144+
ResponseConverter::KV.to_get_all_replicas_result(resp, options)
141145
end
142146

143147
def scan(_scan_type, _options = Options::Scan::DEFAULT)

lib/couchbase/protostellar/request_generator/kv.rb

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,20 @@ def prepend_request(id, content, options)
341341
create_kv_request(proto_req, :prepend, options)
342342
end
343343

344+
def get_all_replicas_request(id, options)
345+
proto_req = Generated::KV::V1::GetAllReplicasRequest.new(
346+
key: id,
347+
**location
348+
)
349+
350+
create_kv_request(proto_req, :get_all_replicas, options, idempotent: true)
351+
end
352+
353+
def get_any_replica_request(id, options)
354+
# Uses the GetAllReplicas request and returns the first item from the result
355+
get_all_replicas_request(id, options)
356+
end
357+
344358
private
345359

346360
def create_kv_request(proto_request, rpc, options, idempotent: false)

lib/couchbase/protostellar/response_converter/kv.rb

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,33 @@ def self.to_lookup_in_result(resp, specs, options, request)
7575
end
7676
end
7777

78+
def self.to_get_any_replica_result(resps, options)
79+
begin
80+
entry = resps.next
81+
rescue StopIteration
82+
raise Couchbase::Error::DocumentIrretrievable, "unable to get replica of the document"
83+
end
84+
Couchbase::Collection::GetReplicaResult.new do |res|
85+
res.transcoder = options.transcoder
86+
res.cas = entry.cas
87+
res.flags = entry.content_flags
88+
res.encoded = entry.content
89+
res.is_replica = entry.is_replica
90+
end
91+
end
92+
93+
def self.to_get_all_replicas_result(resps, options)
94+
resps.map do |entry|
95+
Couchbase::Collection::GetReplicaResult.new do |res|
96+
res.transcoder = options.transcoder
97+
res.cas = entry.cas
98+
res.flags = entry.content_flags
99+
res.encoded = entry.content
100+
res.is_replica = entry.is_replica
101+
end
102+
end
103+
end
104+
78105
def self.to_mutate_in_result(resp, specs, options)
79106
Couchbase::Collection::MutateInResult.new do |res|
80107
res.cas = resp.cas

test/crud_test.rb

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,6 @@ def test_removes_documents
5252
end
5353

5454
def test_reads_from_replica
55-
skip("#{name}: The #{Couchbase::Protostellar::NAME} protocol does not support replica reads yet") if env.protostellar?
56-
5755
doc_id = uniq_id(:foo)
5856
document = {"value" => 42}
5957
options =
@@ -78,6 +76,22 @@ def test_reads_from_replica
7876
end
7977
end
8078

79+
def test_reads_from_replica_does_not_exist
80+
doc_id = uniq_id(:foo)
81+
82+
assert_raises(Couchbase::Error::DocumentIrretrievable) do
83+
@collection.get_any_replica(doc_id)
84+
end
85+
86+
if env.protostellar?
87+
assert_empty @collection.get_all_replicas(doc_id)
88+
else
89+
assert_raises(Couchbase::Error::DocumentNotFound) do
90+
@collection.get_all_replicas(doc_id)
91+
end
92+
end
93+
end
94+
8195
def test_touch_sets_expiration
8296
document = {"value" => 42}
8397
doc_id = uniq_id(:foo)

0 commit comments

Comments
 (0)