Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 85 additions & 2 deletions lib/couchbase/options.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1029,10 +1029,38 @@ def to_backend
# Options for {BinaryCollection#append}
class Append < Base
attr_accessor :cas # @return [Integer]
attr_accessor :durability_level # @return [Symbol]
attr_accessor :replicate_to # @return [Symbol]
attr_accessor :persist_to # @return [Symbol]

# Creates an instance of options for {BinaryCollection#append}
#
# @param [Integer] cas The default CAS used (0 means no CAS in this context)
# @param [Symbol] durability_level level of durability
# +:none+::
# no enhanced durability required for the mutation
# +:majority+::
# the mutation must be replicated to a majority of the Data Service nodes
# (that is, held in the memory allocated to the bucket)
# +:majority_and_persist_to_active+::
# The mutation must be replicated to a majority of the Data Service nodes.
# Additionally, it must be persisted (that is, written and synchronised to disk) on the
# node hosting the active partition (vBucket) for the data.
# +:persist_to_majority+::
# The mutation must be persisted to a majority of the Data Service nodes.
# Accordingly, it will be written to disk on those nodes.
# @param [Symbol] replicate_to number of nodes to replicate
# +:none+:: do not apply any replication requirements.
# +:one+:: wait for replication to at least one node.
# +:two+:: wait for replication to at least two nodes.
# +:three+:: wait for replication to at least three nodes.
# @param [Symbol] persist_to number of nodes to persist
# +:none+:: do not apply any persistence requirements.
# +:active+:: wait for persistence to active node
# +:one+:: wait for persistence to at least one node.
# +:two+:: wait for persistence to at least two nodes.
# +:three+:: wait for persistence to at least three nodes.
# +:four+:: wait for persistence to four nodes (active and replicas).
#
# @param [Integer, #in_milliseconds, nil] timeout
# @param [Proc, nil] retry_strategy the custom retry strategy, if set
Expand All @@ -1041,12 +1069,23 @@ class Append < Base
#
# @yieldparam [Append] self
def initialize(cas: nil,
durability_level: :none,
replicate_to: :none,
persist_to: :none,
timeout: nil,
retry_strategy: nil,
client_context: nil,
parent_span: nil)
super(timeout: timeout, retry_strategy: retry_strategy, client_context: client_context, parent_span: parent_span)
@cas = cas

if durability_level != :none && (replicate_to != :none || persist_to != :none)
raise ArgumentError, "durability_level conflicts with replicate_to and persist_to options"
end

@durability_level = durability_level
@replicate_to = replicate_to
@persist_to = persist_to
yield self if block_given?
end

Expand All @@ -1055,6 +1094,9 @@ def to_backend
{
timeout: Utils::Time.extract_duration(@timeout),
cas: @cas,
durability_level: @durability_level,
persist_to: @persist_to,
replicate_to: @replicate_to,
}
end

Expand All @@ -1064,12 +1106,39 @@ def to_backend

# Options for {BinaryCollection#prepend}
class Prepend < Base
# @return [Integer] The default CAS used (0 means no CAS in this context)
attr_accessor :cas
attr_accessor :cas # @return [Integer]
attr_accessor :durability_level # @return [Symbol]
attr_accessor :replicate_to # @return [Symbol]
attr_accessor :persist_to # @return [Symbol]

# Creates an instance of options for {BinaryCollection#prepend}
#
# @param [Integer] cas The default CAS used (0 means no CAS in this context)
# @param [Symbol] durability_level level of durability
# +:none+::
# no enhanced durability required for the mutation
# +:majority+::
# the mutation must be replicated to a majority of the Data Service nodes
# (that is, held in the memory allocated to the bucket)
# +:majority_and_persist_to_active+::
# The mutation must be replicated to a majority of the Data Service nodes.
# Additionally, it must be persisted (that is, written and synchronised to disk) on the
# node hosting the active partition (vBucket) for the data.
# +:persist_to_majority+::
# The mutation must be persisted to a majority of the Data Service nodes.
# Accordingly, it will be written to disk on those nodes.
# @param [Symbol] replicate_to number of nodes to replicate
# +:none+:: do not apply any replication requirements.
# +:one+:: wait for replication to at least one node.
# +:two+:: wait for replication to at least two nodes.
# +:three+:: wait for replication to at least three nodes.
# @param [Symbol] persist_to number of nodes to persist
# +:none+:: do not apply any persistence requirements.
# +:active+:: wait for persistence to active node
# +:one+:: wait for persistence to at least one node.
# +:two+:: wait for persistence to at least two nodes.
# +:three+:: wait for persistence to at least three nodes.
# +:four+:: wait for persistence to four nodes (active and replicas).
#
# @param [Integer, #in_milliseconds, nil] timeout
# @param [Proc, nil] retry_strategy the custom retry strategy, if set
Expand All @@ -1078,12 +1147,23 @@ class Prepend < Base
#
# @yieldparam [Prepend] self
def initialize(cas: nil,
durability_level: :none,
replicate_to: :none,
persist_to: :none,
timeout: nil,
retry_strategy: nil,
client_context: nil,
parent_span: nil)
super(timeout: timeout, retry_strategy: retry_strategy, client_context: client_context, parent_span: parent_span)
@cas = cas

if durability_level != :none && (replicate_to != :none || persist_to != :none)
raise ArgumentError, "durability_level conflicts with replicate_to and persist_to options"
end

@durability_level = durability_level
@replicate_to = replicate_to
@persist_to = persist_to
yield self if block_given?
end

Expand All @@ -1092,6 +1172,9 @@ def to_backend
{
timeout: Utils::Time.extract_duration(@timeout),
cas: @cas,
durability_level: @durability_level,
persist_to: @persist_to,
replicate_to: @replicate_to,
}
end

Expand Down
40 changes: 36 additions & 4 deletions test/crud_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -694,7 +694,7 @@ def test_collection_retry
def test_append
doc_id = uniq_id(:append)

res = @collection.upsert(doc_id, "foo")
res = @collection.upsert(doc_id, "foo", Options::Upsert(transcoder: nil))

refute_equal 0, res.cas

Expand All @@ -704,13 +704,13 @@ def test_append

res = @collection.get(doc_id, Options::Get(transcoder: nil))

refute_equal "foobar", res.content
assert_equal "foobar", res.content
end

def test_prepend
doc_id = uniq_id(:append)

res = @collection.upsert(doc_id, "foo")
res = @collection.upsert(doc_id, "foo", Options::Upsert(transcoder: nil))

refute_equal 0, res.cas

Expand All @@ -720,7 +720,39 @@ def test_prepend

res = @collection.get(doc_id, Options::Get(transcoder: nil))

refute_equal "barfoo", res.content
assert_equal "barfoo", res.content
end

def test_append_with_durability
doc_id = uniq_id(:append)

res = @collection.upsert(doc_id, "foo", Options::Upsert(transcoder: nil))

refute_equal 0, res.cas

res = @collection.binary.append(doc_id, "bar", Options::Append(durability_level: :majority))

refute_equal 0, res.cas

res = @collection.get(doc_id, Options::Get(transcoder: nil))

assert_equal "foobar", res.content
end

def test_prepend_with_durability
doc_id = uniq_id(:append)

res = @collection.upsert(doc_id, "foo", Options::Upsert(transcoder: nil))

refute_equal 0, res.cas

res = @collection.binary.prepend(doc_id, "bar", Options::Prepend(durability_level: :majority))

refute_equal 0, res.cas

res = @collection.get(doc_id, Options::Get(transcoder: nil))

assert_equal "barfoo", res.content
end

def test_multi_ops
Expand Down