aerospike 2.22.0 → 2.23.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +9 -1
  3. data/lib/aerospike/atomic/atomic.rb +1 -1
  4. data/lib/aerospike/cdt/context.rb +7 -7
  5. data/lib/aerospike/cdt/list_return_type.rb +4 -0
  6. data/lib/aerospike/cdt/map_operation.rb +6 -6
  7. data/lib/aerospike/cdt/map_return_type.rb +4 -0
  8. data/lib/aerospike/client.rb +34 -59
  9. data/lib/aerospike/command/admin_command.rb +1 -1
  10. data/lib/aerospike/command/batch_index_node.rb +1 -1
  11. data/lib/aerospike/command/batch_item.rb +1 -1
  12. data/lib/aerospike/command/command.rb +62 -24
  13. data/lib/aerospike/command/field_type.rb +3 -0
  14. data/lib/aerospike/command/login_command.rb +4 -4
  15. data/lib/aerospike/command/multi_command.rb +8 -2
  16. data/lib/aerospike/command/read_command.rb +2 -2
  17. data/lib/aerospike/connection/authenticate.rb +3 -3
  18. data/lib/aerospike/features.rb +9 -9
  19. data/lib/aerospike/host/parse.rb +2 -2
  20. data/lib/aerospike/key.rb +10 -1
  21. data/lib/aerospike/node/refresh/info.rb +1 -1
  22. data/lib/aerospike/node/verify/name.rb +1 -1
  23. data/lib/aerospike/node/verify/partition_generation.rb +1 -1
  24. data/lib/aerospike/node/verify/peers_generation.rb +1 -1
  25. data/lib/aerospike/node/verify/rebalance_generation.rb +1 -1
  26. data/lib/aerospike/policy/policy.rb +4 -1
  27. data/lib/aerospike/policy/scan_policy.rb +20 -1
  28. data/lib/aerospike/privilege.rb +1 -1
  29. data/lib/aerospike/query/node_partitions.rb +39 -0
  30. data/lib/aerospike/query/partition_filter.rb +66 -0
  31. data/lib/aerospike/query/partition_status.rb +36 -0
  32. data/lib/aerospike/query/partition_tracker.rb +347 -0
  33. data/lib/aerospike/query/scan_command.rb +3 -3
  34. data/lib/aerospike/query/scan_executor.rb +69 -0
  35. data/lib/aerospike/query/scan_partition_command.rb +49 -0
  36. data/lib/aerospike/query/statement.rb +1 -1
  37. data/lib/aerospike/query/stream_command.rb +14 -1
  38. data/lib/aerospike/result_code.rb +79 -4
  39. data/lib/aerospike/role.rb +2 -2
  40. data/lib/aerospike/task/execute_task.rb +2 -2
  41. data/lib/aerospike/task/index_task.rb +1 -1
  42. data/lib/aerospike/user_role.rb +1 -1
  43. data/lib/aerospike/utils/buffer.rb +6 -0
  44. data/lib/aerospike/utils/pool.rb +1 -1
  45. data/lib/aerospike/value/value.rb +6 -6
  46. data/lib/aerospike/version.rb +1 -1
  47. data/lib/aerospike.rb +6 -0
  48. metadata +11 -5
@@ -23,7 +23,7 @@ module Aerospike
23
23
 
24
24
  class ScanCommand < StreamCommand #:nodoc:
25
25
 
26
- def initialize(node, policy, namespace, set_name, bin_names, recordset, partitions)
26
+ def initialize(node, policy, namespace, set_name, bin_names, recordset, node_partitions)
27
27
  super(node)
28
28
 
29
29
  @policy = policy
@@ -31,11 +31,11 @@ module Aerospike
31
31
  @set_name = set_name
32
32
  @bin_names = bin_names
33
33
  @recordset = recordset
34
- @partitions = partitions
34
+ @node_partitions = node_partitions
35
35
  end
36
36
 
37
37
  def write_buffer
38
- set_scan(@policy, @namespace, @set_name, @bin_names, @partitions)
38
+ set_scan(@policy, @namespace, @set_name, @bin_names, @node_partitions)
39
39
  end
40
40
 
41
41
  end # class
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2014-2020 Aerospike, Inc.
4
+ #
5
+ # Portions may be licensed to Aerospike, Inc. under one or more contributor
6
+ # license agreements.
7
+ #
8
+ # Licensed under the Apache License, Version 2.0 (the "License"); you may not
9
+ # use this file except in compliance with the License. You may obtain a copy of
10
+ # the License at http:#www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
15
+ # License for the specific language governing permissions and limitations under
16
+ # the License.
17
+
18
+ module Aerospike
19
+ class ScanExecutor # :nodoc:
20
+
21
+ def self.scan_partitions(policy, cluster, tracker, namespace, set_name, recordset, bin_names = nil)
22
+ interval = policy.sleep_between_retries
23
+
24
+ should_retry = false
25
+
26
+ loop do
27
+ list = tracker.assign_partitions_to_nodes(cluster, namespace)
28
+
29
+ if policy.concurrent_nodes
30
+ threads = []
31
+ # Use a thread per node
32
+ list.each do |node_partition|
33
+
34
+ threads << Thread.new do
35
+ Thread.current.abort_on_exception = true
36
+ command = ScanPartitionCommand.new(policy, tracker, node_partition, namespace, set_name, bin_names, recordset)
37
+ begin
38
+ command.execute
39
+ rescue => e
40
+ should_retry ||= command.should_retry(e)
41
+ Aerospike.logger.error(e.backtrace.join("\n")) unless e == SCAN_TERMINATED_EXCEPTION
42
+ end
43
+ end
44
+ end
45
+ threads.each(&:join)
46
+ else
47
+ # Use a single thread for all nodes for all node
48
+ list.each do |node_partition|
49
+ command = ScanPartitionCommand.new(policy, tracker, node_partition, namespace, set_name, bin_names, recordset)
50
+ begin
51
+ command.execute
52
+ rescue => e
53
+ should_retry ||= command.should_retry(e)
54
+ Aerospike.logger.error(e.backtrace.join("\n")) unless e == SCAN_TERMINATED_EXCEPTION
55
+ end
56
+ end
57
+ end
58
+
59
+ if tracker.complete?(@cluster, policy) || !should_retry
60
+ recordset.thread_finished
61
+ return
62
+ end
63
+ sleep(interval) if policy.sleep_between_retries > 0
64
+ end
65
+ end
66
+
67
+ end
68
+
69
+ end
@@ -0,0 +1,49 @@
1
+ # encoding: utf-8
2
+ # Copyright 2014-2020 Aerospike, Inc.
3
+ #
4
+ # Portions may be licensed to Aerospike, Inc. under one or more contributor
5
+ # license agreements.
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License"); you may not
8
+ # use this file except in compliance with the License. You may obtain a copy of
9
+ # the License at http:#www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14
+ # License for the specific language governing permissions and limitations under
15
+ # the License.
16
+
17
+ require 'aerospike/query/stream_command'
18
+ require 'aerospike/query/recordset'
19
+
20
+ module Aerospike
21
+
22
+ private
23
+
24
+ class ScanPartitionCommand < StreamCommand #:nodoc:
25
+
26
+ def initialize(policy, tracker, node_partitions, namespace, set_name, bin_names, recordset)
27
+ super(node_partitions.node)
28
+
29
+ @policy = policy
30
+ @namespace = namespace
31
+ @set_name = set_name
32
+ @bin_names = bin_names
33
+ @recordset = recordset
34
+ @node_partitions = node_partitions
35
+ @tracker = tracker
36
+ end
37
+
38
+ def write_buffer
39
+ set_scan(@policy, @namespace, @set_name, @bin_names, @node_partitions)
40
+ end
41
+
42
+ def should_retry(e)
43
+ # !! converts nil to false
44
+ !!@tracker&.should_retry(@node_partitions, e)
45
+ end
46
+
47
+ end # class
48
+
49
+ end # module
@@ -49,7 +49,7 @@ module Aerospike
49
49
  # This method is redundant because PredExp can now be set in the base Policy for
50
50
  # any transaction (including queries).
51
51
  #
52
- # NOTE : Policy.predexp takes precedence to this value. This value will be
52
+ # NOTE : Policy.predexp takes precedence to this value. This value will be
53
53
  # deprecated in the future.
54
54
  @predexp = nil
55
55
 
@@ -39,6 +39,8 @@ module Aerospike
39
39
  case result_code
40
40
  when Aerospike::ResultCode::OK
41
41
  # noop
42
+ when Aerospike::ResultCode::PARTITION_UNAVAILABLE
43
+ # noop
42
44
  when Aerospike::ResultCode::KEY_NOT_FOUND_ERROR
43
45
  # consume the rest of the input buffer from the socket
44
46
  read_bytes(receive_size - @data_offset) if @data_offset < receive_size
@@ -59,7 +61,16 @@ module Aerospike
59
61
  key = parse_key(field_count)
60
62
 
61
63
  # If cmd is the end marker of the response, do not proceed further
62
- return true if (info3 & INFO3_PARTITION_DONE) != 0
64
+ if (info3 & INFO3_PARTITION_DONE) != 0
65
+ # When an error code is received, mark partition as unavailable
66
+ # for the current round. Unavailable partitions will be retried
67
+ # in the next round. Generation is overloaded as partitionId.
68
+ if result_code != 0
69
+ @tracker&.partition_unavailable(@node_partitions, generation)
70
+ end
71
+
72
+ next
73
+ end
63
74
 
64
75
  if result_code == 0
65
76
  if @recordset.active?
@@ -68,6 +79,8 @@ module Aerospike
68
79
  expn = @recordset.is_scan? ? SCAN_TERMINATED_EXCEPTION : QUERY_TERMINATED_EXCEPTION
69
80
  raise expn
70
81
  end
82
+
83
+ @tracker&.set_last(@node_partitions, key, key.bval)
71
84
  end
72
85
  end # while
73
86
 
@@ -20,6 +20,42 @@ module Aerospike
20
20
 
21
21
  attr_reader :code
22
22
 
23
+ # One or more keys failed in a batch.
24
+ BATCH_FAILED = -20
25
+
26
+ # No response was received from the server.
27
+ NO_RESPONSE = -19
28
+
29
+ # A network error. Checked the wrapped error for detail.
30
+ NETWORK_ERROR = -18
31
+
32
+ # A common, none-aerospike error. Checked the wrapped error for detail.
33
+ COMMON_ERROR = -17
34
+
35
+ # Max retries limit reached.
36
+ MAX_RETRIES_EXCEEDED = -16
37
+
38
+ # Max errors limit reached.
39
+ MAX_ERROR_RATE = -15
40
+
41
+ # Requested Rack for node/namespace was not defined in the cluster.
42
+ RACK_NOT_DEFINED = -13
43
+
44
+ # Cluster has an invalid partition map, usually due to bad configuration.
45
+ INVALID_CLUSTER_PARTITION_MAP = -12
46
+
47
+ # Server is not accepting requests.
48
+ SERVER_NOT_AVAILABLE = -11
49
+
50
+ # Cluster Name does not match the ClientPolicy.ClusterName value.
51
+ CLUSTER_NAME_MISMATCH_ERROR = -10
52
+
53
+ # Recordset has already been closed or cancelled
54
+ RECORDSET_CLOSED = -9
55
+
56
+ # There were no connections available to the node in the pool, and the pool was limited
57
+ NO_AVAILABLE_CONNECTIONS_TO_NODE = -8
58
+
23
59
  # Value type not supported by Aerospike server
24
60
  TYPE_NOT_SUPPORTED = -7
25
61
 
@@ -76,8 +112,8 @@ module Aerospike
76
112
  # XDS product is not available.
77
113
  NO_XDS = 10
78
114
 
79
- # Server is not accepting requests.
80
- SERVER_NOT_AVAILABLE = 11
115
+ # Partition is unavailable.
116
+ PARTITION_UNAVAILABLE = 11
81
117
 
82
118
  # Operation is not supported with configured bin type (single-bin or
83
119
  # multi-bin).
@@ -265,6 +301,45 @@ module Aerospike
265
301
 
266
302
  def self.message(code)
267
303
  case code
304
+ when BATCH_FAILED
305
+ "one or more keys failed in a batch"
306
+
307
+ when NO_RESPONSE
308
+ "no response was received from the server"
309
+
310
+ when NETWORK_ERROR
311
+ "network error. Checked the wrapped error for detail"
312
+
313
+ when COMMON_ERROR
314
+ "common, none-aerospike error. Checked the wrapped error for detail"
315
+
316
+ when MAX_RETRIES_EXCEEDED
317
+ "Max retries exceeded"
318
+
319
+ when MAX_ERROR_RATE
320
+ "Max errors limit reached for node"
321
+
322
+ when RACK_NOT_DEFINED
323
+ "Requested Rack for node/namespace was not defined in the cluster."
324
+
325
+ when INVALID_CLUSTER_PARTITION_MAP
326
+ "Cluster has an invalid partition map, usually due to bad configuration."
327
+
328
+ when SERVER_NOT_AVAILABLE
329
+ "Server is not accepting requests."
330
+
331
+ when CLUSTER_NAME_MISMATCH_ERROR
332
+ "Cluster Name does not match the ClientPolicy.ClusterName value"
333
+
334
+ when RECORDSET_CLOSED
335
+ "Recordset has already been closed or cancelled."
336
+
337
+ when NO_AVAILABLE_CONNECTIONS_TO_NODE
338
+ "No available connections to the node. Connection Pool was empty, and limited to certain number of connections."
339
+
340
+ when TYPE_NOT_SUPPORTED
341
+ "Type cannot be converted to Value Type."
342
+
268
343
  when COMMAND_REJECTED
269
344
  "Command rejected"
270
345
 
@@ -316,8 +391,8 @@ module Aerospike
316
391
  when NO_XDS
317
392
  "XDS not available"
318
393
 
319
- when SERVER_NOT_AVAILABLE
320
- "Server not available"
394
+ when PARTITION_UNAVAILABLE
395
+ "Partition not available"
321
396
 
322
397
  when BIN_TYPE_ERROR
323
398
  "Bin type error"
@@ -49,7 +49,7 @@ module Aerospike
49
49
  def to_s
50
50
  "Role [name=#{@name}, privileges=#{@privileges}, allowlist=#{@allowlist}, readQuota=#{@read_quota}, writeQuota=#{@write_quota}]";
51
51
  end
52
-
52
+
53
53
  end # class
54
54
 
55
- end # module
55
+ end # module
@@ -70,7 +70,7 @@ module Aerospike
70
70
 
71
71
  case status
72
72
  when 'ABORTED'
73
- raise raise Aerospike::Exceptions::QueryTerminated
73
+ raise Aerospike::Exceptions::QueryTerminated
74
74
  when 'IN PROGRESS'
75
75
  return false
76
76
  when 'DONE'
@@ -82,4 +82,4 @@ module Aerospike
82
82
  end
83
83
 
84
84
  end
85
- end
85
+ end
@@ -25,7 +25,7 @@ module Aerospike
25
25
 
26
26
  class IndexTask < Task
27
27
 
28
- MATCHER = /.*load_pct=(?<load_pct>\d+(\.\d+)?).*/
28
+ MATCHER = /.*load_pct=(?<load_pct>\d+(\.\d+)?).*/.freeze
29
29
 
30
30
  def initialize(cluster, namespace, index_name, done=false)
31
31
  super(cluster, done)
@@ -52,4 +52,4 @@ module Aerospike
52
52
 
53
53
  end
54
54
 
55
- end
55
+ end
@@ -38,6 +38,7 @@ module Aerospike
38
38
  UINT32 = 'N'
39
39
  INT64 = 'q>'
40
40
  UINT64 = 'Q>'
41
+ UINT64LE = 'Q'
41
42
  DOUBLE = 'G'
42
43
 
43
44
  DEFAULT_BUFFER_SIZE = 16 * 1024
@@ -162,6 +163,11 @@ module Aerospike
162
163
  vals.unpack(INT64)[0]
163
164
  end
164
165
 
166
+ def read_uint64_little_endian(offset)
167
+ vals = @buf[offset..offset+7]
168
+ vals.unpack(UINT64LE)[0]
169
+ end
170
+
165
171
  def read_uint64(offset)
166
172
  vals = @buf[offset..offset+7]
167
173
  vals.unpack(UINT64)[0]
@@ -53,7 +53,7 @@ module Aerospike
53
53
  end
54
54
 
55
55
  def empty?
56
- @pool.length == 0
56
+ @pool.empty?
57
57
  end
58
58
 
59
59
  def length
@@ -26,19 +26,19 @@ module Aerospike
26
26
  def self.of(value, allow_64bits = false)
27
27
  case value
28
28
  when Integer
29
- if !allow_64bits
30
- if value.bit_length < 64
29
+ if allow_64bits
30
+ # used in bitwise operations
31
+ if value.bit_length <= 64
31
32
  res = IntegerValue.new(value)
32
33
  else
33
- # big nums > 2**63 are not supported
34
+ # nums with more than 64 bits are not supported
34
35
  raise Aerospike::Exceptions::Aerospike.new(Aerospike::ResultCode::TYPE_NOT_SUPPORTED, "Value type #{value.class} not supported with more than 64 bits.")
35
36
  end
36
37
  else
37
- # used in bitwise operations
38
- if value.bit_length <= 64
38
+ if value.bit_length < 64
39
39
  res = IntegerValue.new(value)
40
40
  else
41
- # nums with more than 64 bits are not supported
41
+ # big nums > 2**63 are not supported
42
42
  raise Aerospike::Exceptions::Aerospike.new(Aerospike::ResultCode::TYPE_NOT_SUPPORTED, "Value type #{value.class} not supported with more than 64 bits.")
43
43
  end
44
44
  end
@@ -1,4 +1,4 @@
1
1
  # encoding: utf-8
2
2
  module Aerospike
3
- VERSION = "2.22.0"
3
+ VERSION = "2.23.0"
4
4
  end
data/lib/aerospike.rb CHANGED
@@ -160,6 +160,12 @@ require 'aerospike/query/query_command'
160
160
  require 'aerospike/query/scan_command'
161
161
  require 'aerospike/query/statement'
162
162
  require 'aerospike/query/pred_exp'
163
+ require 'aerospike/query/partition_tracker'
164
+ require 'aerospike/query/partition_status'
165
+ require 'aerospike/query/partition_filter'
166
+ require 'aerospike/query/node_partitions'
167
+ require 'aerospike/query/scan_executor'
168
+ require 'aerospike/query/scan_partition_command'
163
169
 
164
170
  require 'aerospike/query/pred_exp/and_or'
165
171
  require 'aerospike/query/pred_exp/geo_json_value'
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: aerospike
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.22.0
4
+ version: 2.23.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Khosrow Afroozeh
8
8
  - Jan Hecking
9
- autorequire:
9
+ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2022-07-14 00:00:00.000000000 Z
12
+ date: 2022-10-25 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: msgpack
@@ -155,6 +155,10 @@ files:
155
155
  - lib/aerospike/policy/write_policy.rb
156
156
  - lib/aerospike/privilege.rb
157
157
  - lib/aerospike/query/filter.rb
158
+ - lib/aerospike/query/node_partitions.rb
159
+ - lib/aerospike/query/partition_filter.rb
160
+ - lib/aerospike/query/partition_status.rb
161
+ - lib/aerospike/query/partition_tracker.rb
158
162
  - lib/aerospike/query/pred_exp.rb
159
163
  - lib/aerospike/query/pred_exp/and_or.rb
160
164
  - lib/aerospike/query/pred_exp/geo_json_value.rb
@@ -166,6 +170,8 @@ files:
166
170
  - lib/aerospike/query/query_command.rb
167
171
  - lib/aerospike/query/recordset.rb
168
172
  - lib/aerospike/query/scan_command.rb
173
+ - lib/aerospike/query/scan_executor.rb
174
+ - lib/aerospike/query/scan_partition_command.rb
169
175
  - lib/aerospike/query/statement.rb
170
176
  - lib/aerospike/query/stream_command.rb
171
177
  - lib/aerospike/record.rb
@@ -212,8 +218,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
212
218
  - !ruby/object:Gem::Version
213
219
  version: '0'
214
220
  requirements: []
215
- rubygems_version: 3.2.15
216
- signing_key:
221
+ rubygems_version: 3.1.6
222
+ signing_key:
217
223
  specification_version: 4
218
224
  summary: An Aerospike driver for Ruby.
219
225
  test_files: []