libcouchbase-mapo 1.4.1

Sign up to get free protection for your applications and to get access to all the features.
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,135 @@
1
+ # frozen_string_literal: true, encoding: ASCII-8BIT
2
+
3
+ module Libcouchbase
4
+ class QueryView
5
+ # Set this flag to execute an actual get with each response
6
+ F_INCLUDE_DOCS = 1 << 16
7
+
8
+ # Set this flag to only parse the top level row, and not its constituent
9
+ # parts. Note this is incompatible with `F_INCLUDE_DOCS`
10
+ F_NOROWPARSE = 1 << 17
11
+
12
+ # This view is spatial. Modifies how the final view path will be constructed
13
+ F_SPATIAL = 1 << 18
14
+
15
+
16
+ def initialize(connection, reactor, design, view, **opts)
17
+ @connection = connection
18
+ @reactor = reactor
19
+
20
+ @design = design
21
+ @view = view
22
+ @options = opts
23
+
24
+ @include_docs = true
25
+ @is_spatial = false
26
+ end
27
+
28
+ attr_reader :options, :design, :view, :connection
29
+ attr_accessor :include_docs, :is_spatial
30
+
31
+ def get_count(metadata)
32
+ metadata[:total_rows]
33
+ end
34
+
35
+ def perform(**options, &blk)
36
+ raise 'not connected' unless @connection.handle
37
+ raise 'query already in progress' if @cmd
38
+ raise 'callback required' unless block_given?
39
+
40
+ options = @options.merge(options)
41
+ # We should never exceed the users results limit
42
+ orig_limit = @options[:limit]
43
+ limit = options[:limit]
44
+ if orig_limit && limit
45
+ options[:limit] = orig_limit if limit > orig_limit
46
+ end
47
+
48
+ pairs = []
49
+ options.each { |key, val|
50
+ if key.to_s.include?('key') && val[0] != "["
51
+ pairs << "#{key}=#{[val].to_json[1...-1]}"
52
+ else
53
+ pairs << "#{key}=#{val}"
54
+ end
55
+ }
56
+ opts = pairs.join('&')
57
+
58
+ @reactor.schedule {
59
+ @error = nil
60
+ @callback = blk
61
+
62
+ @cmd = Ext::CMDVIEWQUERY.new
63
+ Ext.view_query_initcmd(@cmd, @design.to_s, @view.to_s, opts, @connection.get_callback(:viewquery_callback))
64
+ @cmd[:cmdflags] |= F_INCLUDE_DOCS if include_docs
65
+ @cmd[:cmdflags] |= F_SPATIAL if is_spatial
66
+
67
+ pointer = @cmd.to_ptr
68
+
69
+ @connection.requests[pointer.address] = self
70
+ err = Ext.view_query(@connection.handle, pointer, @cmd)
71
+ if err != :success
72
+ error(Error.lookup(err).new('view request not scheduled'))
73
+ end
74
+ }
75
+ end
76
+
77
+ def received(row)
78
+ return if @error
79
+
80
+ key = row[:key].read_string(row[:nkey])
81
+ cas = row[:cas]
82
+ emitted = row[:value].read_string(row[:nvalue]) if row[:nvalue] > 0
83
+ geometry = row[:geometry].read_string(row[:ngeometry]) if row[:ngeometry] > 0
84
+ doc_id = row[:docid].read_string(row[:ndocid]) if row[:ndocid] > 0
85
+
86
+ meta = {
87
+ emitted: emitted,
88
+ geometry: geometry,
89
+ key: key
90
+ }
91
+
92
+ resp = Response.new(:viewquery_callback, doc_id, cas)
93
+ resp.metadata = meta
94
+
95
+ # check for included document here
96
+ if @include_docs && row[:docresp]
97
+ doc = row[:docresp]
98
+ raw_string = doc[:value].null? ? '' : doc[:value].read_string(doc[:nvalue])
99
+ resp.value = @connection.parse_document(raw_string)
100
+ meta[:flags] = doc[:itmflags]
101
+ end
102
+
103
+ @callback.call(false, resp)
104
+ rescue => e
105
+ @error = e
106
+ end
107
+
108
+ def received_final(metadata)
109
+ @connection.requests.delete(@cmd.to_ptr.address)
110
+ @cmd = nil
111
+
112
+ if @error
113
+ if @error == :cancelled
114
+ @callback.call(:final, metadata)
115
+ else
116
+ @callback.call(:error, @error)
117
+ end
118
+ else
119
+ @callback.call(:final, metadata)
120
+ end
121
+ end
122
+
123
+ def error(obj)
124
+ @error = obj
125
+ received_final(nil)
126
+ end
127
+
128
+ # We don't ever actually cancel a request here.
129
+ # There is an API however it indicates that @connection.handle might be destroyed
130
+ # Testing also indicated that @connection.handle was destroyed with seg faults
131
+ def cancel
132
+ @error = :cancelled
133
+ end
134
+ end
135
+ end
@@ -0,0 +1,281 @@
1
+ # frozen_string_literal: true, encoding: ASCII-8BIT
2
+
3
+ require 'set'
4
+
5
+ module Libcouchbase
6
+ class ResultsFiber < Results
7
+ def initialize(query, &row_modifier)
8
+ @query_in_progress = false
9
+ @query_completed = false
10
+ @complete_result_set = false
11
+
12
+ @results = []
13
+ @fiber = nil
14
+
15
+ # We don't want to resume a fiber that is waiting
16
+ # in a yield to user code as then the Fiber might
17
+ # end before we've finished processing and this is
18
+ # very much not desirable - dead fiber errors
19
+ @resume_results = true
20
+
21
+ # This could be a view or n1ql query
22
+ @query = query
23
+ @row_modifier = row_modifier
24
+ end
25
+
26
+ def options(**opts)
27
+ reset
28
+ @query.options.merge!(opts)
29
+ end
30
+
31
+
32
+ def stream(&blk)
33
+ if @complete_result_set
34
+ @results.each &blk
35
+ else
36
+ perform is_complete: false
37
+ @fiber = Fiber.current
38
+
39
+ begin
40
+ remaining = @results.length > 0
41
+ while !@query_completed || remaining do
42
+ if remaining
43
+ @resume_results = false
44
+ yield @results.shift
45
+ else
46
+ @resume_results = true
47
+ resume
48
+ end
49
+
50
+ remaining = @results.length > 0
51
+ end
52
+ ensure
53
+ # cancel is executed on break or error
54
+ @resume_results = true
55
+ cancel unless @query_completed
56
+ @fiber = nil
57
+ end
58
+ end
59
+ self
60
+ end
61
+
62
+ def reset
63
+ raise 'query in progress' if @query_in_progress
64
+ @query_in_progress = false
65
+ @complete_result_set = false
66
+ @results.clear
67
+ end
68
+
69
+ def each(&blk)
70
+ # return a valid enumerator
71
+ return load_all.each unless block_given?
72
+
73
+ if @complete_result_set
74
+ @results.each &blk
75
+ else
76
+ perform
77
+ @fiber = Fiber.current
78
+
79
+ begin
80
+ index = 0
81
+ remaining = index < @results.length
82
+ while !@query_completed || remaining do
83
+ if remaining
84
+ @resume_results = false
85
+ yield @results[index]
86
+ index += 1
87
+ else
88
+ @resume_results = true
89
+ resume
90
+ end
91
+
92
+ remaining = index < @results.length
93
+ end
94
+ ensure
95
+ # cancel is executed on break or error
96
+ @resume_results = true
97
+ cancel unless @query_completed
98
+ @fiber = nil
99
+ end
100
+ end
101
+ self
102
+ end
103
+
104
+ def first
105
+ if @complete_result_set || @results.length > 0
106
+ @results[0]
107
+ else
108
+ perform is_complete: false, limit: 1
109
+
110
+ @fiber = Fiber.current
111
+ begin
112
+ while not @query_completed do
113
+ resume
114
+ end
115
+ ensure
116
+ @fiber = nil
117
+ end
118
+
119
+ result = @results[0]
120
+ result
121
+ end
122
+ end
123
+
124
+ def count
125
+ first unless @metadata
126
+ @query.get_count @metadata
127
+ end
128
+
129
+ def take(num)
130
+ if @complete_result_set || @results.length >= num
131
+ @results[0...num]
132
+ else
133
+ perform is_complete: false, limit: num
134
+ @fiber = Fiber.current
135
+ result = []
136
+
137
+ begin
138
+ index = 0
139
+ remaining = index < @results.length && index < num
140
+ while !@query_completed || remaining do
141
+ if remaining
142
+ result << @results[index]
143
+ index += 1
144
+ else
145
+ resume
146
+ end
147
+
148
+ remaining = index < @results.length && index < num
149
+ end
150
+ ensure
151
+ @fiber = nil
152
+ end
153
+
154
+ result
155
+ end
156
+ end
157
+
158
+ def cancel
159
+ @cancelled = true
160
+ @query.cancel
161
+ resume
162
+ end
163
+
164
+
165
+ protected
166
+
167
+
168
+ def load_all
169
+ return @results if @complete_result_set
170
+ perform
171
+
172
+ @fiber = Fiber.current
173
+ begin
174
+ while not @query_completed do; resume; end
175
+ ensure
176
+ @fiber = nil
177
+ end
178
+ @results
179
+ end
180
+
181
+ def perform(is_complete: true, **opts)
182
+ return if @query_in_progress
183
+ @query_in_progress = true
184
+ @query_completed = false
185
+
186
+ # This flag is required to prevent race conditions
187
+ @cancelled = false
188
+ @results.clear
189
+
190
+ # This performs the query against the server
191
+ @query.perform(**opts) { |final, item|
192
+ on_thread(is_complete, final, item)
193
+ }
194
+ end
195
+
196
+ def process_response(is_complete, final, item)
197
+ # Has the operation completed?
198
+ if final
199
+ if final == :error
200
+ @error = item unless @cancelled
201
+ @complete_result_set = false
202
+ elsif @cancelled
203
+ @metadata = item
204
+ @complete_result_set = false
205
+ else
206
+ @metadata = item
207
+ @complete_result_set = is_complete
208
+ end
209
+ @query_completed = true
210
+ @query_in_progress = false
211
+
212
+ # Do we want to transform the results
213
+ elsif @row_modifier
214
+ begin
215
+ @results << @row_modifier.call(item)
216
+ rescue Exception => e
217
+ @error = e
218
+ end
219
+ else
220
+ @results << item
221
+ end
222
+
223
+ # Resume processing
224
+ @fiber.resume if @fiber && @resume_results && (!@cancelled || final)
225
+ end
226
+ end
227
+
228
+ class ResultsLibuv < ResultsFiber
229
+ def initialize(query, thread = reactor, &row_modifier)
230
+ super(query, &row_modifier)
231
+ @reactor = thread
232
+ end
233
+
234
+
235
+ protected
236
+
237
+
238
+ def on_thread(is_complete, final, item)
239
+ @reactor.schedule {
240
+ process_response(is_complete, final, item)
241
+ }
242
+ end
243
+
244
+ def resume
245
+ @reactor = reactor
246
+
247
+ # Prevent the reactor from stopping
248
+ @reactor.ref
249
+ Fiber.yield
250
+ @reactor.unref
251
+
252
+ # Clear and raise the error
253
+ if @error
254
+ err = @error
255
+ @error = nil
256
+ raise err unless @cancelled
257
+ end
258
+ end
259
+ end
260
+
261
+ class ResultsEM < ResultsFiber
262
+ protected
263
+
264
+ def on_thread(is_complete, final, item)
265
+ EM.next_tick {
266
+ process_response(is_complete, final, item)
267
+ }
268
+ end
269
+
270
+ def resume
271
+ Fiber.yield
272
+
273
+ # Clear and raise the error
274
+ if @error
275
+ err = @error
276
+ @error = nil
277
+ raise err unless @cancelled
278
+ end
279
+ end
280
+ end
281
+ end
@@ -0,0 +1,220 @@
1
+ # frozen_string_literal: true, encoding: ASCII-8BIT
2
+
3
+ require 'set'
4
+
5
+ module Libcouchbase
6
+ class ResultsNative < Results
7
+ def initialize(query, &row_modifier)
8
+ @query_in_progress = false
9
+ @query_completed = false
10
+ @complete_result_set = false
11
+
12
+ @results = []
13
+
14
+ # This could be a view or n1ql query
15
+ @query = query
16
+ @row_modifier = row_modifier
17
+ end
18
+
19
+ def options(**opts)
20
+ reset
21
+ @query.options.merge!(opts)
22
+ end
23
+
24
+ def stream(&blk)
25
+ if @complete_result_set
26
+ @results.each &blk
27
+ else
28
+ perform is_complete: false
29
+ begin
30
+ remaining = @results.length > 0
31
+ while !@query_completed || remaining do
32
+ if remaining
33
+ yield @results.shift
34
+ else
35
+ process_next_item
36
+ end
37
+
38
+ remaining = @results.length > 0
39
+ end
40
+ ensure
41
+ # cancel is executed on break or error
42
+ cancel unless @query_completed
43
+ end
44
+
45
+ raise @error if @error
46
+ end
47
+ self
48
+ end
49
+
50
+ def reset
51
+ raise 'query in progress' if @query_in_progress
52
+ @query_in_progress = false
53
+ @complete_result_set = false
54
+ @results.clear
55
+ end
56
+
57
+ def each(&blk)
58
+ # return a valid enumerator
59
+ return load_all.each unless block_given?
60
+
61
+ if @complete_result_set
62
+ @results.each &blk
63
+ else
64
+ perform
65
+
66
+ begin
67
+ index = 0
68
+ remaining = index < @results.length
69
+ while !@query_completed || remaining do
70
+ if remaining
71
+ yield @results[index]
72
+ index += 1
73
+ else
74
+ process_next_item
75
+ end
76
+
77
+ remaining = index < @results.length
78
+ end
79
+ ensure
80
+ # cancel is executed on break or error
81
+ cancel unless @query_completed
82
+ end
83
+
84
+ raise @error if @error
85
+ end
86
+ self
87
+ end
88
+
89
+ def first
90
+ if @complete_result_set || @results.length > 0
91
+ @results[0]
92
+ else
93
+ perform is_complete: false, limit: 1
94
+
95
+ while not @query_completed do
96
+ process_next_item
97
+ end
98
+ raise @error if @error
99
+
100
+ result = @results[0]
101
+ result
102
+ end
103
+ end
104
+
105
+ def count
106
+ first unless @metadata
107
+ @query.get_count @metadata
108
+ end
109
+
110
+ def take(num)
111
+ if @complete_result_set || @results.length >= num
112
+ @results[0...num]
113
+ else
114
+ perform is_complete: false, limit: num
115
+
116
+ index = 0
117
+ result = []
118
+ remaining = index < @results.length && index < num
119
+ while !@query_completed || remaining do
120
+ if remaining
121
+ result << @results[index]
122
+ index += 1
123
+ else
124
+ process_next_item
125
+ end
126
+
127
+ remaining = index < @results.length && index < num
128
+ end
129
+
130
+ raise @error if @error
131
+ result
132
+ end
133
+ end
134
+
135
+ def cancel
136
+ return if @cancelled
137
+ @cancelled = true
138
+ @query.cancel
139
+ process_next_item
140
+ end
141
+
142
+
143
+ protected
144
+
145
+
146
+ def process_next_item(can_loop = true)
147
+ return if @query_completed
148
+ final, item = @queue.pop
149
+
150
+ if final
151
+ if final == :error
152
+ @error = item unless @cancelled
153
+ @complete_result_set = false
154
+ elsif @cancelled
155
+ @metadata = item
156
+ @complete_result_set = false
157
+ else
158
+ @metadata = item
159
+ @complete_result_set = @is_complete
160
+ end
161
+ @query_completed = true
162
+ @query_in_progress = false
163
+
164
+ elsif not @cancelled
165
+ # Do we want to transform the results
166
+ if @row_modifier
167
+ begin
168
+ @results << @row_modifier.call(item)
169
+ rescue Exception => e
170
+ @error = e
171
+ @cancelled = true
172
+ @query.cancel
173
+ end
174
+ else
175
+ @results << item
176
+ end
177
+ end
178
+
179
+ # This prevents the stack from blowing out
180
+ if can_loop
181
+ while !@queue.empty? || (@cancelled && !final) do
182
+ final = process_next_item(false)
183
+ end
184
+ end
185
+
186
+ final
187
+ end
188
+
189
+ def load_all
190
+ return @results if @complete_result_set
191
+ perform
192
+
193
+ while not @query_completed do
194
+ process_next_item
195
+ end
196
+ raise @error if @error
197
+
198
+ @results
199
+ end
200
+
201
+ def perform(is_complete: true, **opts)
202
+ return if @query_in_progress
203
+ @query_in_progress = true
204
+ @query_completed = false
205
+ @is_complete = is_complete
206
+ @cancelled = false
207
+ @error = nil
208
+
209
+ # This flag is required so we don't
210
+ @results.clear
211
+ @queue = Queue.new
212
+
213
+ # This performs the query against the server
214
+ # The callback will always be on another thread
215
+ @query.perform(**opts) { |final, item|
216
+ @queue.push([final, item])
217
+ }
218
+ end
219
+ end
220
+ end