libcouchbase-mapo 1.4.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.
Files changed (104) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +20 -0
  3. data/.gitmodules +3 -0
  4. data/.rspec +1 -0
  5. data/.travis.yml +38 -0
  6. data/Gemfile +4 -0
  7. data/LICENSE +24 -0
  8. data/README.md +445 -0
  9. data/Rakefile +76 -0
  10. data/ext/README.md +6 -0
  11. data/ext/Rakefile +19 -0
  12. data/lib/libcouchbase.rb +40 -0
  13. data/lib/libcouchbase/bucket.rb +825 -0
  14. data/lib/libcouchbase/callbacks.rb +69 -0
  15. data/lib/libcouchbase/connection.rb +886 -0
  16. data/lib/libcouchbase/design_docs.rb +92 -0
  17. data/lib/libcouchbase/error.rb +68 -0
  18. data/lib/libcouchbase/ext/libcouchbase.rb +1175 -0
  19. data/lib/libcouchbase/ext/libcouchbase/cmdbase.rb +23 -0
  20. data/lib/libcouchbase/ext/libcouchbase/cmdcounter.rb +36 -0
  21. data/lib/libcouchbase/ext/libcouchbase/cmdendure.rb +26 -0
  22. data/lib/libcouchbase/ext/libcouchbase/cmdfts.rb +24 -0
  23. data/lib/libcouchbase/ext/libcouchbase/cmdget.rb +30 -0
  24. data/lib/libcouchbase/ext/libcouchbase/cmdgetreplica.rb +49 -0
  25. data/lib/libcouchbase/ext/libcouchbase/cmdhttp.rb +58 -0
  26. data/lib/libcouchbase/ext/libcouchbase/cmdn1ql.rb +40 -0
  27. data/lib/libcouchbase/ext/libcouchbase/cmdobseqno.rb +33 -0
  28. data/lib/libcouchbase/ext/libcouchbase/cmdobserve.rb +30 -0
  29. data/lib/libcouchbase/ext/libcouchbase/cmdstore.rb +40 -0
  30. data/lib/libcouchbase/ext/libcouchbase/cmdstoredur.rb +45 -0
  31. data/lib/libcouchbase/ext/libcouchbase/cmdsubdoc.rb +61 -0
  32. data/lib/libcouchbase/ext/libcouchbase/cmdverbosity.rb +29 -0
  33. data/lib/libcouchbase/ext/libcouchbase/cmdviewquery.rb +61 -0
  34. data/lib/libcouchbase/ext/libcouchbase/contigbuf.rb +14 -0
  35. data/lib/libcouchbase/ext/libcouchbase/create_st.rb +15 -0
  36. data/lib/libcouchbase/ext/libcouchbase/create_st0.rb +23 -0
  37. data/lib/libcouchbase/ext/libcouchbase/create_st1.rb +26 -0
  38. data/lib/libcouchbase/ext/libcouchbase/create_st2.rb +32 -0
  39. data/lib/libcouchbase/ext/libcouchbase/create_st3.rb +26 -0
  40. data/lib/libcouchbase/ext/libcouchbase/crst_u.rb +20 -0
  41. data/lib/libcouchbase/ext/libcouchbase/durability_opts_st_v.rb +11 -0
  42. data/lib/libcouchbase/ext/libcouchbase/durability_opts_t.rb +14 -0
  43. data/lib/libcouchbase/ext/libcouchbase/durabilityopt_sv0.rb +63 -0
  44. data/lib/libcouchbase/ext/libcouchbase/enums.rb +1007 -0
  45. data/lib/libcouchbase/ext/libcouchbase/fragbuf.rb +18 -0
  46. data/lib/libcouchbase/ext/libcouchbase/ftshandle.rb +7 -0
  47. data/lib/libcouchbase/ext/libcouchbase/histogram.rb +34 -0
  48. data/lib/libcouchbase/ext/libcouchbase/http_request_t.rb +7 -0
  49. data/lib/libcouchbase/ext/libcouchbase/keybuf.rb +20 -0
  50. data/lib/libcouchbase/ext/libcouchbase/multicmd_ctx.rb +30 -0
  51. data/lib/libcouchbase/ext/libcouchbase/mutation_token.rb +17 -0
  52. data/lib/libcouchbase/ext/libcouchbase/n1qlhandle.rb +7 -0
  53. data/lib/libcouchbase/ext/libcouchbase/n1qlparams.rb +7 -0
  54. data/lib/libcouchbase/ext/libcouchbase/respbase.rb +29 -0
  55. data/lib/libcouchbase/ext/libcouchbase/respcounter.rb +32 -0
  56. data/lib/libcouchbase/ext/libcouchbase/respendure.rb +49 -0
  57. data/lib/libcouchbase/ext/libcouchbase/respfts.rb +40 -0
  58. data/lib/libcouchbase/ext/libcouchbase/respget.rb +44 -0
  59. data/lib/libcouchbase/ext/libcouchbase/resphttp.rb +48 -0
  60. data/lib/libcouchbase/ext/libcouchbase/respmcversion.rb +38 -0
  61. data/lib/libcouchbase/ext/libcouchbase/respn1ql.rb +41 -0
  62. data/lib/libcouchbase/ext/libcouchbase/respobseqno.rb +52 -0
  63. data/lib/libcouchbase/ext/libcouchbase/respobserve.rb +41 -0
  64. data/lib/libcouchbase/ext/libcouchbase/respserverbase.rb +32 -0
  65. data/lib/libcouchbase/ext/libcouchbase/respstats.rb +38 -0
  66. data/lib/libcouchbase/ext/libcouchbase/respstore.rb +32 -0
  67. data/lib/libcouchbase/ext/libcouchbase/respstoredur.rb +38 -0
  68. data/lib/libcouchbase/ext/libcouchbase/respsubdoc.rb +35 -0
  69. data/lib/libcouchbase/ext/libcouchbase/respviewquery.rb +67 -0
  70. data/lib/libcouchbase/ext/libcouchbase/sdentry.rb +22 -0
  71. data/lib/libcouchbase/ext/libcouchbase/sdspec.rb +31 -0
  72. data/lib/libcouchbase/ext/libcouchbase/t.rb +7 -0
  73. data/lib/libcouchbase/ext/libcouchbase/valbuf.rb +22 -0
  74. data/lib/libcouchbase/ext/libcouchbase/valbuf_u_buf.rb +14 -0
  75. data/lib/libcouchbase/ext/libcouchbase/viewhandle.rb +7 -0
  76. data/lib/libcouchbase/ext/libcouchbase_libuv.rb +22 -0
  77. data/lib/libcouchbase/ext/tasks.rb +39 -0
  78. data/lib/libcouchbase/n1ql.rb +78 -0
  79. data/lib/libcouchbase/query_full_text.rb +147 -0
  80. data/lib/libcouchbase/query_n1ql.rb +123 -0
  81. data/lib/libcouchbase/query_view.rb +135 -0
  82. data/lib/libcouchbase/results_fiber.rb +281 -0
  83. data/lib/libcouchbase/results_native.rb +220 -0
  84. data/lib/libcouchbase/subdoc_request.rb +139 -0
  85. data/lib/libcouchbase/version.rb +5 -0
  86. data/libcouchbase.gemspec +68 -0
  87. data/spec/bucket_spec.rb +290 -0
  88. data/spec/connection_spec.rb +257 -0
  89. data/spec/design_docs_spec.rb +31 -0
  90. data/spec/error_spec.rb +26 -0
  91. data/spec/fts_spec.rb +135 -0
  92. data/spec/n1ql_spec.rb +206 -0
  93. data/spec/results_libuv_spec.rb +244 -0
  94. data/spec/results_native_spec.rb +259 -0
  95. data/spec/seed/2016-10-25T043505Z/2016-10-25T043505Z-full/bucket-default/design.json +1 -0
  96. data/spec/seed/2016-10-25T043505Z/2016-10-25T043505Z-full/bucket-default/node-127.0.0.1%3A8091/data-0000.cbb +0 -0
  97. data/spec/seed/2016-10-25T043505Z/2016-10-25T043505Z-full/bucket-default/node-127.0.0.1%3A8091/failover.json +1 -0
  98. data/spec/seed/2016-10-25T043505Z/2016-10-25T043505Z-full/bucket-default/node-127.0.0.1%3A8091/meta.json +1 -0
  99. data/spec/seed/2016-10-25T043505Z/2016-10-25T043505Z-full/bucket-default/node-127.0.0.1%3A8091/seqno.json +1 -0
  100. data/spec/seed/2016-10-25T043505Z/2016-10-25T043505Z-full/bucket-default/node-127.0.0.1%3A8091/snapshot_markers.json +1 -0
  101. data/spec/subdoc_spec.rb +192 -0
  102. data/spec/view_spec.rb +201 -0
  103. data/windows_build.md +36 -0
  104. metadata +265 -0
@@ -0,0 +1,22 @@
1
+ module Libcouchbase::Ext
2
+ # (Not documented)
3
+ #
4
+ # ## Fields:
5
+ # :vtype ::
6
+ # (KVBUFTYPE) Value request type. This may be one of:
7
+ # - LCB_KV_COPY: Copy over the value into LCB's own buffers
8
+ # Use the 'contig' field to supply the information.
9
+ #
10
+ # - LCB_KV_CONTIG: The buffer is a contiguous chunk of value data.
11
+ # Use the 'contig' field to supply the information.
12
+ #
13
+ # - LCB_KV_IOV: The buffer is a series of IOV elements. Use the 'multi'
14
+ # field to supply the information.
15
+ # :u_buf ::
16
+ # (VALBUFUBuf)
17
+ class VALBUF < FFI::Struct
18
+ layout :vtype, KVBUFTYPE,
19
+ :u_buf, VALBUFUBuf.by_value
20
+ end
21
+
22
+ end
@@ -0,0 +1,14 @@
1
+ module Libcouchbase::Ext
2
+ # (Not documented)
3
+ #
4
+ # ## Fields:
5
+ # :contig ::
6
+ # (CONTIGBUF)
7
+ # :multi ::
8
+ # (FRAGBUF)
9
+ class VALBUFUBuf < FFI::Union
10
+ layout :contig, CONTIGBUF.by_value,
11
+ :multi, FRAGBUF.by_value
12
+ end
13
+
14
+ end
@@ -0,0 +1,7 @@
1
+ module Libcouchbase::Ext
2
+ # (Not documented)
3
+ class VIEWHANDLE < FFI::Struct
4
+ layout :dummy, :char
5
+ end
6
+
7
+ end
@@ -0,0 +1,22 @@
1
+
2
+ # This file contains all the structures required to configure libcouchbase to use
3
+ # Libuv as the primary event loop
4
+
5
+ module Libcouchbase::Ext::Libuv
6
+ extend FFI::Library
7
+ if FFI::Platform.windows?
8
+ ffi_lib ::File.expand_path("../../../../ext/libcouchbase_libuv.dll", __FILE__)
9
+ else
10
+ ffi_lib ::File.expand_path("../../../../ext/libcouchbase/build/lib/libcouchbase_libuv.#{FFI::Platform::LIBSUFFIX}", __FILE__)
11
+ end
12
+
13
+ # ref: http://docs.couchbase.com/sdk-api/couchbase-c-client-2.4.8/group__lcb-libuv.html
14
+ class UVOptions < FFI::Struct
15
+ layout :version, :int,
16
+ :loop, :pointer,
17
+ :start_stop_noop,:int
18
+ end
19
+
20
+ # pointer param returns IO opts structure
21
+ attach_function :create_libuv_io_opts, :lcb_create_libuv_io_opts, [:int, :pointer, UVOptions.by_ref], ::Libcouchbase::Ext::ErrorT
22
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true, encoding: ASCII-8BIT
2
+
3
+ require 'fileutils'
4
+ require 'libuv'
5
+
6
+ module FFI::Platform
7
+ def self.ia32?
8
+ ARCH == "i386"
9
+ end
10
+
11
+ def self.x64?
12
+ ARCH == "x86_64"
13
+ end
14
+ end
15
+
16
+ # Ensure the submodule is cloned
17
+ file 'ext/libcouchbase/include' do
18
+ system 'git', 'submodule', 'update', '--init'
19
+ end
20
+
21
+ file 'ext/libcouchbase/build' => 'ext/libcouchbase/include' do
22
+ FileUtils.mkdir('ext/libcouchbase/build')
23
+ end
24
+
25
+ file 'ext/libcouchbase/build/makefile' => 'ext/libcouchbase/build' do
26
+ result = nil
27
+ Dir.chdir("ext/libcouchbase") do |path|
28
+ result = system './cmake/configure', '-disable-couchbasemock', '-with-libuv', ::File.expand_path('../../', ::Libuv::Ext.path_to_internal_libuv)
29
+ end
30
+ raise 'could not find cmake on path' unless result
31
+ end
32
+
33
+ file "ext/libcouchbase/build/lib/libcouchbase_libuv.#{FFI::Platform::LIBSUFFIX}" => 'ext/libcouchbase/build/makefile' do
34
+ result = nil
35
+ Dir.chdir('ext/libcouchbase/build') do |path|
36
+ result = system 'make'
37
+ end
38
+ raise 'make failed' unless result
39
+ end
@@ -0,0 +1,78 @@
1
+ # frozen_string_literal: true, encoding: ASCII-8BIT
2
+
3
+ module Libcouchbase
4
+ class N1QL
5
+ Ordering = [
6
+ :build_index, :create_index, :drop_index, :create_primary_index,
7
+ :drop_primary_index, :grant, :on, :to, :infer, :select, :insert_into,
8
+ :delete_from, :update, :from, :with, :use_keys, :unnest, :join, :where,
9
+ :group_by, :order_by, :limit, :offset, :upsert_into, :merge_into
10
+ ]
11
+
12
+ def initialize(bucket, explain: false, **options)
13
+ @bucket = bucket
14
+ @connection = bucket.connection
15
+ @explain = !!explain
16
+ options.each do |key, value|
17
+ if self.respond_to? key
18
+ self.public_send key, value
19
+ end
20
+ end
21
+ end
22
+
23
+ attr_accessor *Ordering
24
+ attr_accessor :explain
25
+ attr_reader :bucket, :connection
26
+
27
+ def explain(val = nil)
28
+ return @explain if val.nil?
29
+ @explain = !!val
30
+ self
31
+ end
32
+
33
+ Ordering.each do |helper|
34
+ define_method helper do |*args|
35
+ return instance_variable_get :"@#{helper}" if args.empty?
36
+ if args.length == 1
37
+ instance_variable_set :"@#{helper}", args[0]
38
+ else
39
+ instance_variable_set :"@#{helper}", args
40
+ end
41
+ self
42
+ end
43
+ end
44
+
45
+ def to_s
46
+ res = String.new
47
+ res << "EXPLAIN\n" if @explain
48
+ Ordering.each do |statement|
49
+ val = public_send statement
50
+ unless val.nil?
51
+ res << "#{statement.to_s.gsub('_', ' ').upcase} "
52
+
53
+ if val.is_a? Array
54
+ res << val.collect { |obj| obj.to_s }.join(', ')
55
+ else
56
+ res << val.to_s
57
+ end
58
+
59
+ res << "\n"
60
+ end
61
+ end
62
+ res
63
+ end
64
+
65
+ def results(&row_modifier)
66
+ n1ql_view = @connection.n1ql_query(self)
67
+
68
+ current = ::Libuv::Reactor.current
69
+ if current && current.running?
70
+ ResultsLibuv.new(n1ql_view, current, &row_modifier)
71
+ elsif Object.const_defined?(:EventMachine) && EM.reactor_thread?
72
+ ResultsEM.new(n1ql_view, &row_modifier)
73
+ else
74
+ ResultsNative.new(n1ql_view, &row_modifier)
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,147 @@
1
+ # frozen_string_literal: true, encoding: ASCII-8BIT
2
+
3
+ module Libcouchbase
4
+ class QueryFullText
5
+ def initialize(connection, reactor, include_docs: true, **opts)
6
+ @connection = connection
7
+ @reactor = reactor
8
+
9
+ @options = opts
10
+ @include_docs = include_docs
11
+ @request_handle = FFI::MemoryPointer.new :pointer, 1
12
+ end
13
+
14
+ attr_reader :options, :connection
15
+ attr_accessor :include_docs
16
+
17
+ def index
18
+ @options[:indexName]
19
+ end
20
+
21
+ def get_count(metadata)
22
+ metadata[:total_hits]
23
+ end
24
+
25
+ def perform(limit: nil, **options, &blk)
26
+ raise 'not connected' unless @connection.handle
27
+ raise 'query already in progress' if @query_cstr
28
+ raise 'callback required' unless block_given?
29
+
30
+ # customise the size based on the request being made
31
+ orig_size = @options[:size] || 10 # 10 is the couchbase default
32
+ new_size = limit || orig_size
33
+ begin
34
+ @options[:size] = new_size if orig_size > new_size
35
+ @query_text = JSON.generate(@options)
36
+ @query_cstr = FFI::MemoryPointer.from_string(@query_text)
37
+ rescue
38
+ @query_cstr = nil
39
+ @query_text = nil
40
+ raise
41
+ ensure
42
+ @options[:size] = orig_size
43
+ end
44
+
45
+ @reactor.schedule {
46
+ @error = nil
47
+ @doc_count = 0
48
+ @callback = blk
49
+
50
+ @cmd = Ext::CMDFTS.new
51
+ @cmd[:query] = @query_cstr
52
+ @cmd[:nquery] = @query_text.bytesize
53
+ @cmd[:callback] = @connection.get_callback(:fts_callback)
54
+ @cmd[:handle] = @request_handle
55
+
56
+ pointer = @cmd.to_ptr
57
+ @connection.requests[pointer.address] = self
58
+
59
+ err = Ext.fts_query(@connection.handle, pointer, @cmd)
60
+ if err != :success
61
+ error(Error.lookup(err).new('full text search not scheduled'))
62
+ end
63
+ }
64
+ end
65
+
66
+ # Example Row:
67
+ # {:index=>"default_3f230bec977a680e_b7ff6b68", :id=>"dep_1-18", :score=>1.3540229098345296,
68
+ # :locations=>{:class_name=>{:toshiba=>[{:pos=>1, :start=>2, :end=>9, :array_positions=>nil}]},
69
+ # :name=>{:toshiba=>[{:pos=>1, :start=>0, :end=>7, :array_positions=>nil}]}}}
70
+ def received(row)
71
+ return if @error
72
+
73
+ resp = Response.new(:fts_callback, row[:id])
74
+ resp.metadata = row
75
+
76
+ # TODO:: this could cause results to be returned out of order
77
+ if @include_docs
78
+ @doc_count += 1
79
+ doc = @connection.get(resp.key).value
80
+ resp.value = doc.value
81
+ resp.cas = doc.cas
82
+ resp.metadata.merge! doc.metadata
83
+ end
84
+
85
+ @callback.call(false, resp)
86
+ rescue => e
87
+ @error = e
88
+ cancel
89
+ ensure
90
+ if @include_docs
91
+ @doc_count -= 1
92
+ process_final if @metadata && @doc_count == 0
93
+ end
94
+ end
95
+
96
+ # Example metadata
97
+ # {:status=>{:total=>2, :failed=>0, :successful=>2}, :request=>{:query=>{:query=>"Toshiba", :boost=>1},
98
+ # :size=>10, :from=>0, :highlight=>nil, :fields=>nil, :facets=>nil, :explain=>false}, :hits=>[],
99
+ # :total_hits=>4, :max_score=>1.6405488681166451, :took=>10182765, :facets=>{}}
100
+ def received_final(metadata)
101
+ @metadata = metadata
102
+ process_final unless @doc_count > 0
103
+ end
104
+
105
+ def error(obj)
106
+ @error = obj
107
+ # This sets metadata to true, however it'll be ignored as error is set
108
+ # We set it to true as we may be fetching documents in parallel and need to wait
109
+ received_final(true)
110
+ end
111
+
112
+ def cancel
113
+ @error = :cancelled unless @error
114
+ @reactor.schedule {
115
+ if @connection.handle && @cmd
116
+ Ext.fts_cancel(@connection.handle, @handle_ptr.get_pointer(0))
117
+ received_final(true)
118
+ end
119
+ }
120
+ end
121
+
122
+
123
+ protected
124
+
125
+
126
+ def process_final
127
+ metadata = @metadata
128
+ @metadata = nil
129
+
130
+ @query_cstr = nil
131
+ @query_text = nil
132
+
133
+ @connection.requests.delete(@cmd.to_ptr.address)
134
+ @cmd = nil
135
+
136
+ if @error
137
+ if @error == :cancelled
138
+ @callback.call(:final, metadata)
139
+ else
140
+ @callback.call(:error, @error)
141
+ end
142
+ else
143
+ @callback.call(:final, metadata)
144
+ end
145
+ end
146
+ end
147
+ end
@@ -0,0 +1,123 @@
1
+ # frozen_string_literal: true, encoding: ASCII-8BIT
2
+
3
+ module Libcouchbase
4
+ class QueryN1QL
5
+ N1P_QUERY_STATEMENT = 1
6
+ N1P_CONSISTENCY_REQUEST = 2
7
+
8
+ def initialize(connection, reactor, n1ql, **opts)
9
+ @connection = connection
10
+ @reactor = reactor
11
+
12
+ @n1ql = n1ql
13
+ @request_handle = FFI::MemoryPointer.new :pointer, 1
14
+ end
15
+
16
+ attr_reader :connection, :n1ql
17
+
18
+ def get_count(metadata)
19
+ metadata[:metrics][:resultCount]
20
+ end
21
+
22
+ def perform(limit: nil, **options, &blk)
23
+ raise 'not connected' unless @connection.handle
24
+ raise 'query already in progress' if @query_text
25
+ raise 'callback required' unless block_given?
26
+
27
+ # customise the size based on the request being made
28
+ orig_limit = @n1ql.limit
29
+ begin
30
+ if orig_limit && limit
31
+ @n1ql.limit = limit if orig_limit > limit
32
+ end
33
+ @query_text = @n1ql.to_s
34
+ rescue
35
+ @query_text = nil
36
+ raise
37
+ ensure
38
+ @n1ql.limit = orig_limit
39
+ end
40
+
41
+ @reactor.schedule {
42
+ @error = nil
43
+ @callback = blk
44
+
45
+ @cmd = Ext::CMDN1QL.new
46
+ @params = Ext.n1p_new
47
+ err = Ext.n1p_setconsistency(@params, N1P_CONSISTENCY_REQUEST)
48
+ if err == :success
49
+ err = Ext.n1p_setquery(@params, @query_text, @query_text.bytesize, N1P_QUERY_STATEMENT)
50
+ if err == :success
51
+
52
+ err = Ext.n1p_mkcmd(@params, @cmd)
53
+ if err == :success
54
+ pointer = @cmd.to_ptr
55
+ @connection.requests[pointer.address] = self
56
+
57
+ @cmd[:callback] = @connection.get_callback(:n1ql_callback)
58
+ @cmd[:handle] = @request_handle
59
+
60
+ err = Ext.n1ql_query(@connection.handle, pointer, @cmd)
61
+ if err != :success
62
+ error(Error.lookup(err).new('full text search not scheduled'))
63
+ end
64
+ else
65
+ error(Error.lookup(err).new('failed to build full text search command'))
66
+ end
67
+ else
68
+ error(Error.lookup(err).new('failed to build full text search query structure'))
69
+ end
70
+ else
71
+ error(Error.lookup(err).new('failed set consistency value'))
72
+ end
73
+ }
74
+ end
75
+
76
+ # Row is JSON value representing the result
77
+ def received(row)
78
+ return if @error
79
+ @callback.call(false, row)
80
+ rescue => e
81
+ @error = e
82
+ cancel
83
+ end
84
+
85
+ # Example metadata
86
+ # {:requestID=>"36162fce-ef39-4821-bf03-449e4073185d", :signature=>{:*=>"*"}, :results=>[], :status=>"success",
87
+ # :metrics=>{:elapsedTime=>"15.298243ms", :executionTime=>"15.256975ms", :resultCount=>12, :resultSize=>8964}}
88
+ def received_final(metadata)
89
+ @query_text = nil
90
+
91
+ @connection.requests.delete(@cmd.to_ptr.address)
92
+ @cmd = nil
93
+
94
+ Ext.n1p_free(@params)
95
+ @params = nil
96
+
97
+ if @error
98
+ if @error == :cancelled
99
+ @callback.call(:final, metadata)
100
+ else
101
+ @callback.call(:error, @error)
102
+ end
103
+ else
104
+ @callback.call(:final, metadata)
105
+ end
106
+ end
107
+
108
+ def error(obj)
109
+ @error = obj
110
+ received_final(nil)
111
+ end
112
+
113
+ def cancel
114
+ @error = :cancelled unless @error
115
+ @reactor.schedule {
116
+ if @connection.handle && @cmd
117
+ Ext.n1ql_cancel(@connection.handle, @handle_ptr.get_pointer(0))
118
+ received_final(nil)
119
+ end
120
+ }
121
+ end
122
+ end
123
+ end