Class: Libcouchbase::Bucket
- Inherits:
-
Object
- Object
- Libcouchbase::Bucket
- Extended by:
- Forwardable
- Defined in:
- lib/libcouchbase/bucket.rb
Constant Summary collapse
- AddDefaults =
{operation: :add}.freeze
- ReplaceDefaults =
{operation: :replace}.freeze
- ViewDefaults =
{ on_error: :stop, stale: false }
- FtsDefaults =
{ include_docs: true, size: 10000, # Max result size from: 0, explain: false }
Instance Attribute Summary collapse
-
#connection ⇒ Object
readonly
Returns the value of attribute connection.
-
#quiet ⇒ Object
Returns the value of attribute quiet.
Class Method Summary collapse
-
.finalize(connection) ⇒ Object
Finalizer done right www.mikeperham.com/2010/02/24/the-trouble-with-ruby-finalizers/.
Instance Method Summary collapse
-
#[](key) ⇒ Object
Quietly obtain an object stored in Couchbase by given key.
-
#add(key, value, async: false, **opts) ⇒ Libcouchbase::Result
Add the item to the database, but fail if the object exists already.
-
#compare_and_swap(key, **opts) {|value| ... } ⇒ Libcouchbase::Response
(also: #cas)
Compare and swap value.
-
#decr(key, by = 1, **opts) ⇒ Object
Decrement the value of an existing numeric key.
-
#delete(key, async: false, quiet: true, **opts) ⇒ true, false
Delete the specified key.
-
#delete_design_doc(id, rev = nil, async: false) ⇒ Object
Delete design doc with given id and optional revision.
-
#design_docs(**opts) ⇒ Libcouchbase::DesignDocs
Fetch design docs stored in current bucket.
-
#fetch(key, value = nil, async: false, **opts) ⇒ Object
A helper method for returning a default value if one doesn’t exist for the key.
-
#flush(async: false) ⇒ Libcouchbase::Response
Delete contents of the bucket.
-
#full_text_search(index, query, **opts, &row_modifier) ⇒ Libcouchbase::Results
Returns an enumerable for the results in a full text search.
-
#get(key, *keys, extended: false, async: false, quiet: @quiet, assemble_hash: false, **opts) ⇒ Object, ...
Obtain an object stored in Couchbase by given key.
-
#get_num_nodes ⇒ Integer
The numbers of nodes in the cluster.
-
#get_num_replicas ⇒ Integer
The numbers of the replicas for each node in the cluster.
-
#incr(key, by = 1, create: false, extended: false, async: false, **opts) ⇒ Integer
Increment the value of an existing numeric key.
-
#initialize(**options) ⇒ Bucket
constructor
A new instance of Bucket.
-
#n1ql(**options) ⇒ Libcouchbase::N1QL
Returns an n1ql query builder.
-
#replace(key, value, async: false, **opts) ⇒ Libcouchbase::Result
Replace the existing object in the database.
-
#save_design_doc(data, id = nil, async: false) ⇒ Object
Update or create design doc with supplied views.
-
#set(key, value, async: false, **opts) ⇒ Libcouchbase::Result
(also: #[]=)
Unconditionally store the object in the Couchbase.
-
#subdoc(key, quiet: @quiet, **opts) {|the| ... } ⇒ Object
Perform subdocument operations on a key.
- #subdoc_execute!(sd, extended: false, async: false, **opts) ⇒ Object
-
#touch(key, async: false, **opts) ⇒ Object
Touch a key, changing its CAS and optionally setting a timeout.
-
#view(design, view, include_docs: true, is_spatial: false, **opts, &row_modifier) ⇒ Libcouchbase::Results
Returns an enumerable for the results in a view.
-
#wait_results(*results) ⇒ Array
Waits for all the async operations to complete and returns the results.
Constructor Details
#initialize(**options) ⇒ Bucket
Returns a new instance of Bucket.
21 22 23 24 25 26 27 28 29 30 31 32 |
# File 'lib/libcouchbase/bucket.rb', line 21 def initialize(**) @connection_options = @connection = Connection.new(**) connect # This obtains the connections reactor @reactor = reactor @quiet = false # clean up the connection once this object is garbage collected ObjectSpace.define_finalizer( self, self.class.finalize(@connection) ) end |
Instance Attribute Details
#connection ⇒ Object (readonly)
Returns the value of attribute connection.
35 36 37 |
# File 'lib/libcouchbase/bucket.rb', line 35 def connection @connection end |
#quiet ⇒ Object
Returns the value of attribute quiet.
36 37 38 |
# File 'lib/libcouchbase/bucket.rb', line 36 def quiet @quiet end |
Class Method Details
.finalize(connection) ⇒ Object
Finalizer done right www.mikeperham.com/2010/02/24/the-trouble-with-ruby-finalizers/
13 14 15 16 17 18 19 |
# File 'lib/libcouchbase/bucket.rb', line 13 def self.finalize(connection) proc { connection.destroy.finally do connection.reactor.unref end } end |
Instance Method Details
#[](key) ⇒ Object
Quietly obtain an object stored in Couchbase by given key.
161 162 163 |
# File 'lib/libcouchbase/bucket.rb', line 161 def [](key) get(key, quiet: true) end |
#add(key, value, async: false, **opts) ⇒ Libcouchbase::Result
Add the item to the database, but fail if the object exists already
210 211 212 |
# File 'lib/libcouchbase/bucket.rb', line 210 def add(key, value, async: false, **opts) result @connection.store(key, value, **AddDefaults.merge(opts)), async end |
#compare_and_swap(key, **opts) {|value| ... } ⇒ Libcouchbase::Response Also known as: cas
Compare and swap value.
Reads a key’s value from the server and yields it to a block. Replaces the key’s value with the result of the block as long as the key hasn’t been updated in the meantime, otherwise raises Error::KeyExists.
Setting the :retry
option to a positive number will cause this method to rescue the Error::KeyExists error that happens when an update collision is detected, and automatically get a fresh copy of the value and retry the block. This will repeat as long as there continues to be conflicts, up to the maximum number of retries specified.
634 635 636 637 638 639 640 641 642 643 644 645 646 647 |
# File 'lib/libcouchbase/bucket.rb', line 634 def compare_and_swap(key, **opts) retries = opts.delete(:retry) || 0 begin current = result(@connection.get(key)) new_value = yield current.value, opts opts[:cas] = current.cas set(key, new_value, **opts) rescue Libcouchbase::Error::KeyExists retries -= 1 retry if retries >= 0 raise end end |
#decr(key, by = 1, **opts) ⇒ Object
Decrement the value of an existing numeric key
Helper method, see incr
368 369 370 |
# File 'lib/libcouchbase/bucket.rb', line 368 def decr(key, by = 1, **opts) incr(key, -by, **opts) end |
#delete(key, async: false, quiet: true, **opts) ⇒ true, false
Delete the specified key
408 409 410 411 412 413 414 415 416 417 418 419 420 |
# File 'lib/libcouchbase/bucket.rb', line 408 def delete(key, async: false, quiet: true, **opts) promise = @connection.remove(key, **opts).then { true } if quiet promise = promise.catch { |error| if error.is_a? Libcouchbase::Error::KeyNotFound false else ::Libuv::Q.reject(@reactor, error) end } end result promise, async end |
#delete_design_doc(id, rev = nil, async: false) ⇒ Object
Delete design doc with given id and optional revision.
593 594 595 596 597 |
# File 'lib/libcouchbase/bucket.rb', line 593 def delete_design_doc(id, rev = nil, async: false) id = id.to_s.sub(/^_design\//, '') rev = "?rev=#{rev}" if rev result @connection.http("/_design/#{id}#{rev}", method: :delete, type: :view), async end |
#design_docs(**opts) ⇒ Libcouchbase::DesignDocs
Fetch design docs stored in current bucket
487 488 489 |
# File 'lib/libcouchbase/bucket.rb', line 487 def design_docs(**opts) DesignDocs.new(self, @connection, proc { |promise, async| result(promise, async) }, **opts) end |
#fetch(key, value = nil, async: false, **opts) ⇒ Object
A helper method for returning a default value if one doesn’t exist for the key
166 167 168 169 170 171 172 |
# File 'lib/libcouchbase/bucket.rb', line 166 def fetch(key, value = nil, async: false, **opts) cached_obj = get(key, quiet: true, async: false, extended: false) return cached_obj if cached_obj value = value || yield set(key, value, opts.merge(async: false, extended: false)) value end |
#flush(async: false) ⇒ Libcouchbase::Response
Delete contents of the bucket
433 434 435 |
# File 'lib/libcouchbase/bucket.rb', line 433 def flush(async: false) result @connection.flush, async end |
#full_text_search(index, query, **opts, &row_modifier) ⇒ Libcouchbase::Results
Returns an enumerable for the results in a full text search.
Results are lazily loaded when an operation is performed on the enum
521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 |
# File 'lib/libcouchbase/bucket.rb', line 521 def full_text_search(index, query, **opts, &row_modifier) if query.is_a? Hash opts[:query] = query else opts[:query] = {query: query} end fts = @connection.full_text_search(index, **FtsDefaults.merge(opts)) current = ::Libuv::Reactor.current if current && current.running? ResultsLibuv.new(fts, current, &row_modifier) elsif Object.const_defined?(:EventMachine) && EM.reactor_thread? ResultsEM.new(fts, &row_modifier) else ResultsNative.new(fts, &row_modifier) end end |
#get(key, *keys, extended: false, async: false, quiet: @quiet, assemble_hash: false, **opts) ⇒ Object, ...
Obtain an object stored in Couchbase by given key.
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 |
# File 'lib/libcouchbase/bucket.rb', line 86 def get(key, *keys, extended: false, async: false, quiet: @quiet, assemble_hash: false, **opts) was_array = key.respond_to?(:to_a) || keys.length > 0 keys.unshift Array(key) # Convert enumerables keys.flatten! # Ensure we're left with a list of keys if keys.length == 1 promise = @connection.get(keys[0], **opts) unless extended promise = promise.then(proc { |resp| resp.value }) end if quiet promise = promise.catch { |err| if err.is_a? Libcouchbase::Error::KeyNotFound nil else ::Libuv::Q.reject(@reactor, err) end } end if assemble_hash promise = promise.then(proc { |val| hash = defined?(::HashWithIndifferentAccess) ? ::HashWithIndifferentAccess.new : {} hash[keys[0]] = val hash }) elsif was_array promise = promise.then(proc { |val| Array(val) }) end result(promise, async) else promises = keys.collect { |key| @connection.get(key, **opts) } if quiet promises.map! { |prom| prom.catch { |err| if err.is_a? Libcouchbase::Error::KeyNotFound nil else ::Libuv::Q.reject(@reactor, err) end } } end result(@reactor.all(*promises).then(proc { |results| if extended results.compact! else results.collect! { |resp| resp.value if resp } end if assemble_hash hash = defined?(::HashWithIndifferentAccess) ? ::HashWithIndifferentAccess.new : {} keys.each_with_index do |key, index| hash[key] = results[index] end hash else results end }), async) end end |
#get_num_nodes ⇒ Integer
The numbers of nodes in the cluster
658 659 660 |
# File 'lib/libcouchbase/bucket.rb', line 658 def get_num_nodes result @connection.get_num_nodes end |
#get_num_replicas ⇒ Integer
The numbers of the replicas for each node in the cluster
652 653 654 |
# File 'lib/libcouchbase/bucket.rb', line 652 def get_num_replicas result @connection.get_num_replicas end |
#incr(key, by = 1, create: false, extended: false, async: false, **opts) ⇒ Integer
Increment the value of an existing numeric key
The increment method allow you to increase or decrease a given stored integer value. Updating the value of a key if it can be parsed to an integer. The update operation occurs on the server and is provided at the protocol level. This simplifies what would otherwise be a two-stage get and set operation.
355 356 357 358 359 360 361 362 363 |
# File 'lib/libcouchbase/bucket.rb', line 355 def incr(key, by = 1, create: false, extended: false, async: false, **opts) opts[:delta] ||= by opts[:initial] = 0 if create promise = @connection.counter(key, **opts) if not extended promise = promise.then { |resp| resp.value } end result promise, async end |
#n1ql(**options) ⇒ Libcouchbase::N1QL
Returns an n1ql query builder.
548 549 550 |
# File 'lib/libcouchbase/bucket.rb', line 548 def n1ql(**) N1QL.new(self, **) end |
#replace(key, value, async: false, **opts) ⇒ Libcouchbase::Result
Replace the existing object in the database
302 303 304 |
# File 'lib/libcouchbase/bucket.rb', line 302 def replace(key, value, async: false, **opts) result @connection.store(key, value, **ReplaceDefaults.merge(opts)), async end |
#save_design_doc(data, id = nil, async: false) ⇒ Object
Update or create design doc with supplied views
558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 |
# File 'lib/libcouchbase/bucket.rb', line 558 def save_design_doc(data, id = nil, async: false) attrs = case data when String JSON.parse(data, Connection::DECODE_OPTIONS) when IO JSON.parse(data.read, Connection::DECODE_OPTIONS) when Hash data else raise ArgumentError, "Document should be Hash, String or IO instance" end attrs[:language] ||= :javascript id ||= attrs.delete(:_id) id = id.to_s.sub(/^_design\//, '') prom = @connection.http("/_design/#{id}", method: :put, body: attrs, type: :view ).then { |res| # Seems to require a moment before the view is usable @reactor.sleep 100 res } result prom, async end |
#set(key, value, async: false, **opts) ⇒ Libcouchbase::Result Also known as: []=
Unconditionally store the object in the Couchbase
258 259 260 261 |
# File 'lib/libcouchbase/bucket.rb', line 258 def set(key, value, async: false, **opts) # default operation is set result @connection.store(key, value, **opts), async end |
#subdoc(key, quiet: @quiet, **opts) {|the| ... } ⇒ Object
Perform subdocument operations on a key.
Yields a request builder to a block and applies the operations performed
466 467 468 469 470 471 472 473 474 |
# File 'lib/libcouchbase/bucket.rb', line 466 def subdoc(key, quiet: @quiet, **opts) if block_given? sd = SubdocRequest.new(key, quiet) yield sd subdoc_execute!(sd, opts) else SubdocRequest.new(key, quiet, bucket: self, exec_opts: opts) end end |
#subdoc_execute!(sd, extended: false, async: false, **opts) ⇒ Object
476 477 478 479 480 481 482 |
# File 'lib/libcouchbase/bucket.rb', line 476 def subdoc_execute!(sd, extended: false, async: false, **opts) promise = @connection.subdoc(sd, opts).then { |resp| raise resp.value if resp.value.is_a?(::Exception) extended ? resp : resp.value } result promise, async end |
#touch(key, async: false, **opts) ⇒ Object
Touch a key, changing its CAS and optionally setting a timeout
438 439 440 |
# File 'lib/libcouchbase/bucket.rb', line 438 def touch(key, async: false, **opts) result @connection.touch(key, **opts), async end |
#view(design, view, include_docs: true, is_spatial: false, **opts, &row_modifier) ⇒ Libcouchbase::Results
Returns an enumerable for the results in a view.
Results are lazily loaded when an operation is performed on the enum
496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 |
# File 'lib/libcouchbase/bucket.rb', line 496 def view(design, view, include_docs: true, is_spatial: false, **opts, &row_modifier) view = @connection.query_view(design, view, **ViewDefaults.merge(opts)) view.include_docs = include_docs view.is_spatial = is_spatial current = ::Libuv::Reactor.current if current && current.running? ResultsLibuv.new(view, current, &row_modifier) elsif Object.const_defined?(:EventMachine) && EM.reactor_thread? ResultsEM.new(view, &row_modifier) else ResultsNative.new(view, &row_modifier) end end |
#wait_results(*results) ⇒ Array
Waits for all the async operations to complete and returns the results
665 666 667 |
# File 'lib/libcouchbase/bucket.rb', line 665 def wait_results(*results) result ::Libuv::Q.all(@reactor, *results.flatten) end |