aerospike 2.9.1 → 2.14.0

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 (105) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +50 -4
  3. data/README.md +1 -1
  4. data/lib/aerospike.rb +17 -4
  5. data/lib/aerospike/aerospike_exception.rb +7 -1
  6. data/lib/aerospike/atomic/atomic.rb +1 -1
  7. data/lib/aerospike/bin.rb +1 -1
  8. data/lib/aerospike/cdt/list_operation.rb +1 -1
  9. data/lib/aerospike/cdt/map_operation.rb +1 -1
  10. data/lib/aerospike/cdt/map_order.rb +1 -1
  11. data/lib/aerospike/cdt/map_policy.rb +1 -1
  12. data/lib/aerospike/cdt/map_return_type.rb +1 -1
  13. data/lib/aerospike/cdt/map_write_mode.rb +1 -1
  14. data/lib/aerospike/client.rb +31 -17
  15. data/lib/aerospike/cluster.rb +139 -17
  16. data/lib/aerospike/cluster/partition.rb +1 -1
  17. data/lib/aerospike/cluster/partition_parser.rb +169 -0
  18. data/lib/aerospike/cluster/rack_parser.rb +117 -0
  19. data/lib/aerospike/command/admin_command.rb +1 -1
  20. data/lib/aerospike/command/batch_direct_command.rb +2 -1
  21. data/lib/aerospike/command/batch_direct_exists_command.rb +1 -1
  22. data/lib/aerospike/command/batch_direct_node.rb +3 -3
  23. data/lib/aerospike/command/batch_index_command.rb +11 -2
  24. data/lib/aerospike/command/batch_index_node.rb +2 -2
  25. data/lib/aerospike/command/batch_item.rb +1 -1
  26. data/lib/aerospike/command/command.rb +157 -11
  27. data/lib/aerospike/command/delete_command.rb +21 -5
  28. data/lib/aerospike/command/execute_command.rb +1 -1
  29. data/lib/aerospike/command/exists_command.rb +21 -5
  30. data/lib/aerospike/command/field_type.rb +3 -1
  31. data/lib/aerospike/command/multi_command.rb +55 -5
  32. data/lib/aerospike/command/operate_command.rb +6 -1
  33. data/lib/aerospike/command/read_command.rb +63 -20
  34. data/lib/aerospike/command/read_header_command.rb +18 -6
  35. data/lib/aerospike/command/roles.rb +1 -1
  36. data/lib/aerospike/command/single_command.rb +9 -3
  37. data/lib/aerospike/command/touch_command.rb +48 -4
  38. data/lib/aerospike/command/unsupported_particle_type_validator.rb +1 -1
  39. data/lib/aerospike/command/write_command.rb +13 -4
  40. data/lib/aerospike/connection/create.rb +1 -1
  41. data/lib/aerospike/features.rb +3 -1
  42. data/lib/aerospike/geo_json.rb +70 -1
  43. data/lib/aerospike/host.rb +1 -1
  44. data/lib/aerospike/info.rb +1 -1
  45. data/lib/aerospike/key.rb +1 -1
  46. data/lib/aerospike/language.rb +1 -1
  47. data/lib/aerospike/node.rb +21 -7
  48. data/lib/aerospike/node/rebalance.rb +50 -0
  49. data/lib/aerospike/node/refresh/info.rb +4 -1
  50. data/lib/aerospike/node/refresh/partitions.rb +6 -15
  51. data/lib/aerospike/node/refresh/racks.rb +47 -0
  52. data/lib/aerospike/node/refresh/reset.rb +1 -0
  53. data/lib/aerospike/node/verify/rebalance_generation.rb +43 -0
  54. data/lib/aerospike/node_validator.rb +45 -40
  55. data/lib/aerospike/operation.rb +6 -1
  56. data/lib/aerospike/policy/admin_policy.rb +1 -1
  57. data/lib/aerospike/policy/batch_policy.rb +1 -1
  58. data/lib/aerospike/policy/client_policy.rb +16 -1
  59. data/lib/aerospike/policy/commit_level.rb +1 -1
  60. data/lib/aerospike/policy/consistency_level.rb +1 -1
  61. data/lib/aerospike/policy/generation_policy.rb +1 -1
  62. data/lib/aerospike/policy/operate_policy.rb +1 -1
  63. data/lib/aerospike/policy/policy.rb +64 -2
  64. data/lib/aerospike/policy/priority.rb +1 -1
  65. data/lib/aerospike/policy/query_policy.rb +8 -1
  66. data/lib/aerospike/policy/record_bin_multiplicity.rb +1 -1
  67. data/lib/aerospike/policy/record_exists_action.rb +1 -1
  68. data/lib/aerospike/policy/replica.rb +45 -0
  69. data/lib/aerospike/policy/scan_policy.rb +8 -1
  70. data/lib/aerospike/policy/write_policy.rb +1 -1
  71. data/lib/aerospike/query/filter.rb +1 -1
  72. data/lib/aerospike/query/pred_exp.rb +192 -0
  73. data/lib/aerospike/query/pred_exp/and_or.rb +32 -0
  74. data/lib/aerospike/query/pred_exp/geo_json_value.rb +41 -0
  75. data/lib/aerospike/query/pred_exp/integer_value.rb +32 -0
  76. data/lib/aerospike/query/pred_exp/op.rb +27 -0
  77. data/lib/aerospike/query/pred_exp/regex.rb +32 -0
  78. data/lib/aerospike/query/pred_exp/regex_flags.rb +23 -0
  79. data/lib/aerospike/query/pred_exp/string_value.rb +29 -0
  80. data/lib/aerospike/query/query_command.rb +27 -1
  81. data/lib/aerospike/query/recordset.rb +5 -5
  82. data/lib/aerospike/query/scan_command.rb +1 -1
  83. data/lib/aerospike/query/statement.rb +12 -3
  84. data/lib/aerospike/query/stream_command.rb +1 -1
  85. data/lib/aerospike/record.rb +1 -1
  86. data/lib/aerospike/result_code.rb +13 -7
  87. data/lib/aerospike/socket/base.rb +4 -3
  88. data/lib/aerospike/task/execute_task.rb +1 -1
  89. data/lib/aerospike/task/index_task.rb +1 -1
  90. data/lib/aerospike/task/task.rb +1 -1
  91. data/lib/aerospike/task/udf_register_task.rb +1 -1
  92. data/lib/aerospike/task/udf_remove_task.rb +1 -1
  93. data/lib/aerospike/ttl.rb +1 -1
  94. data/lib/aerospike/udf.rb +1 -1
  95. data/lib/aerospike/user_role.rb +1 -1
  96. data/lib/aerospike/utils/buffer.rb +14 -4
  97. data/lib/aerospike/utils/packer.rb +1 -1
  98. data/lib/aerospike/utils/pool.rb +1 -1
  99. data/lib/aerospike/utils/unpacker.rb +7 -2
  100. data/lib/aerospike/value/particle_type.rb +1 -1
  101. data/lib/aerospike/value/value.rb +59 -29
  102. data/lib/aerospike/version.rb +1 -1
  103. metadata +19 -8
  104. data/lib/aerospike/cluster/partition_tokenizer_new.rb +0 -130
  105. data/lib/aerospike/cluster/partition_tokenizer_old.rb +0 -135
@@ -1,5 +1,5 @@
1
1
  # encoding: utf-8
2
- # Copyright 2014-2017 Aerospike, Inc.
2
+ # Copyright 2014-2020 Aerospike, Inc.
3
3
  #
4
4
  # Portions may be licensed to Aerospike, Inc. under one or more contributor
5
5
  # license agreements.
@@ -30,19 +30,63 @@ module Aerospike
30
30
  self
31
31
  end
32
32
 
33
+ def get_node
34
+ @cluster.master_node(@partition)
35
+ end
36
+
33
37
  def write_buffer
34
38
  set_touch(@policy, @key)
35
39
  end
36
40
 
37
41
  def parse_result
38
42
  # Read header.
39
- @conn.read(@data_buffer, MSG_TOTAL_HEADER_SIZE)
43
+ begin
44
+ @conn.read(@data_buffer, 8)
45
+ rescue => e
46
+ Aerospike.logger.error("parse result error: #{e}")
47
+ raise e
48
+ end
49
+
50
+ # inflate if compressed
51
+ compressed_sz = compressed_size
52
+ if compressed_sz
53
+ begin
54
+ #waste 8 size bytes
55
+ @conn.read(@data_buffer, 8)
56
+
57
+ # read compressed message
58
+ @conn.read(@data_buffer, sz - 8)
59
+
60
+ # inflate the results
61
+ # TODO: reuse the current buffer
62
+ uncompressed = Zlib::inflate(@data_buffer.buf)
63
+
64
+ @data_buffer = Buffer.new(-1, uncompressed)
65
+ rescue => e
66
+ Aerospike.logger.error("parse result error: #{e}")
67
+ raise e
68
+ end
69
+ else
70
+ begin
71
+ bytes_read = @conn.read(@data_buffer, MSG_TOTAL_HEADER_SIZE - 8, 8)
72
+ rescue => e
73
+ Aerospike.logger.error("parse result error: #{e}")
74
+ raise e
75
+ end
76
+ end
40
77
 
41
78
  result_code = @data_buffer.read(13).ord & 0xFF
42
79
 
43
- raise Aerospike::Exceptions::Aerospike.new(result_code) if result_code != 0
80
+ return if result_code == 0
81
+
82
+ if result_code == Aerospike::ResultCode::FILTERED_OUT
83
+ if @policy.fail_on_filtered_out
84
+ raise Aerospike::Exceptions::Aerospike.new(result_code)
85
+ end
86
+ return
87
+ end
44
88
 
45
- empty_socket
89
+ raise Aerospike::Exceptions::Aerospike.new(result_code)
46
90
  end
47
91
 
48
92
  end # class
@@ -1,5 +1,5 @@
1
1
  # encoding: utf-8
2
- # Copyright 2015-2017 Aerospike, Inc.
2
+ # Copyright 2015-2020 Aerospike, Inc.
3
3
  #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License")
5
5
  # you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
1
1
  # encoding: utf-8
2
- # Copyright 2014-2017 Aerospike, Inc.
2
+ # Copyright 2014-2020 Aerospike, Inc.
3
3
  #
4
4
  # Portions may be licensed to Aerospike, Inc. under one or more contributor
5
5
  # license agreements.
@@ -33,6 +33,10 @@ module Aerospike
33
33
  self
34
34
  end
35
35
 
36
+ def get_node
37
+ @cluster.master_node(@partition)
38
+ end
39
+
36
40
  def write_bins
37
41
  @bins
38
42
  end
@@ -52,11 +56,16 @@ module Aerospike
52
56
 
53
57
  result_code = @data_buffer.read(13).ord & 0xFF
54
58
 
55
- if result_code != 0
56
- raise Aerospike::Exceptions::Aerospike.new(result_code)
59
+ return if result_code == 0
60
+
61
+ if result_code == Aerospike::ResultCode::FILTERED_OUT
62
+ if @policy.fail_on_filtered_out
63
+ raise Aerospike::Exceptions::Aerospike.new(result_code)
64
+ end
65
+ return
57
66
  end
58
67
 
59
- empty_socket
68
+ raise Aerospike::Exceptions::Aerospike.new(result_code)
60
69
  end
61
70
 
62
71
  end # class
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Copyright 2014-2018 Aerospike, Inc.
3
+ # Copyright 2014-2020 Aerospike, Inc.
4
4
  #
5
5
  # Portions may be licensed to Aerospike, Inc. under one or more contributor
6
6
  # license agreements.
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Copyright 2014-2017 Aerospike, Inc.
3
+ # Copyright 2014-2020 Aerospike, Inc.
4
4
  #
5
5
  # Portions may be licensed to Aerospike, Inc. under one or more contributor
6
6
  # license agreements.
@@ -40,5 +40,7 @@ module Aerospike
40
40
  # Server supports the new "peers" protocol for automatic node discovery
41
41
  PEERS = :peers
42
42
 
43
+ # Server supports the "truncate-namespace" command
44
+ TRUNCATE_NAMESPACE = :"truncate-namespace"
43
45
  end
44
46
  end
@@ -1,5 +1,5 @@
1
1
  # encoding: utf-8
2
- # Copyright 2015-2017 Aerospike, Inc.
2
+ # Copyright 2015-2020 Aerospike, Inc.
3
3
  #
4
4
  # Portions may be licensed to Aerospike, Inc. under one or more contributor
5
5
  # license agreements.
@@ -52,6 +52,75 @@ module Aerospike
52
52
  other.to_json == self.to_json
53
53
  end
54
54
 
55
+ def lng
56
+ case type
57
+ when 'Point'
58
+ coordinates.first
59
+ when 'AeroCircle'
60
+ coordinates.first.first
61
+ end
62
+ end
63
+
64
+ def lat
65
+ case type
66
+ when 'Point'
67
+ coordinates.last
68
+ when 'AeroCircle'
69
+ coordinates.first.last
70
+ end
71
+ end
72
+
73
+ def radius
74
+ return nil unless circle?
75
+
76
+ coordinates.last
77
+ end
78
+
79
+ def coordinates
80
+ to_h['coordinates']
81
+ end
82
+
83
+ def type
84
+ to_h['type']
85
+ end
86
+
87
+ def point?
88
+ type == 'Point'
89
+ end
90
+
91
+ def circle?
92
+ type == 'AeroCircle'
93
+ end
94
+
95
+ def polygon?
96
+ type == 'Polygon'
97
+ end
98
+
99
+ def self.point(lng, lat)
100
+ new(type: 'Point', coordinates: [lng, lat])
101
+ end
102
+
103
+ def self.circle(lng, lat, radius)
104
+ new(type: 'AeroCircle', coordinates: [[lng, lat], radius])
105
+ end
106
+
107
+ def self.polygon(coordinates)
108
+ new(type: 'Polygon', coordinates: coordinates)
109
+ end
110
+
111
+ def to_circle(radius)
112
+ raise TypeError, 'Cannot create a Circle from a Polygon' if polygon?
113
+
114
+ self.class.circle(lng, lat, radius)
115
+ end
116
+
117
+ def to_point
118
+ return self if point?
119
+ raise TypeError, 'Cannot create a Point from a Polygon' if polygon?
120
+
121
+ self.class.point(lng, lat)
122
+ end
123
+
55
124
  protected
56
125
 
57
126
  attr_accessor :json_data
@@ -1,5 +1,5 @@
1
1
  # encoding: utf-8
2
- # Copyright 2014-2018 Aerospike, Inc.
2
+ # Copyright 2014-2020 Aerospike, Inc.
3
3
  #
4
4
  # Portions may be licensed to Aerospike, Inc. under one or more contributor
5
5
  # license agreements.
@@ -1,5 +1,5 @@
1
1
  # encoding: utf-8
2
- # Copyright 2014-2017 Aerospike, Inc.
2
+ # Copyright 2014-2020 Aerospike, Inc.
3
3
  #
4
4
  # Portions may be licensed to Aerospike, Inc. under one or more contributor
5
5
  # license agreements.
@@ -1,5 +1,5 @@
1
1
  # encoding: utf-8
2
- # Copyright 2014-2017 Aerospike, Inc.
2
+ # Copyright 2014-2020 Aerospike, Inc.
3
3
  #
4
4
  # Portions may be licensed to Aerospike, Inc. under one or more contributor
5
5
  # license agreements.
@@ -1,5 +1,5 @@
1
1
  # encoding: utf-8
2
- # Copyright 2014-2017 Aerospike, Inc.
2
+ # Copyright 2014-2020 Aerospike, Inc.
3
3
  #
4
4
  # Portions may be licensed to Aerospike, Inc. under one or more contributor
5
5
  # license agreements.
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Copyright 2014-2018 Aerospike, Inc.
3
+ # Copyright 2014-2020 Aerospike, Inc.
4
4
  #
5
5
  # Portions may be licensed to Aerospike, Inc. under one or more contributor
6
6
  # license agreements.
@@ -22,7 +22,7 @@ require 'aerospike/atomic/atomic'
22
22
  module Aerospike
23
23
  class Node
24
24
 
25
- attr_reader :reference_count, :responded, :name, :features, :cluster_name, :partition_generation, :peers_generation, :failures, :cluster, :peers_count, :host
25
+ attr_reader :reference_count, :responded, :name, :features, :cluster_name, :partition_generation, :rebalance_generation, :peers_generation, :failures, :cluster, :peers_count, :host
26
26
 
27
27
  PARTITIONS = 4096
28
28
  FULL_HEALTH = 100
@@ -33,7 +33,6 @@ module Aerospike
33
33
  @name = nv.name
34
34
  @aliases = Atomic.new(nv.aliases)
35
35
  @host = nv.host
36
- @use_new_info = Atomic.new(nv.use_new_info)
37
36
  @features = nv.features
38
37
  @cluster_name = nv.cluster_name
39
38
 
@@ -47,14 +46,29 @@ module Aerospike
47
46
  @peers_count = Atomic.new(0)
48
47
  @peers_generation = ::Aerospike::Node::Generation.new
49
48
  @partition_generation = ::Aerospike::Node::Generation.new
49
+ @rebalance_generation = ::Aerospike::Node::Rebalance.new
50
50
  @reference_count = Atomic.new(0)
51
51
  @responded = Atomic.new(false)
52
52
  @active = Atomic.new(true)
53
53
  @failures = Atomic.new(0)
54
54
 
55
+ @replica_index = Atomic.new(0)
56
+ @racks = Atomic.new(nil)
57
+
55
58
  @connections = ::Aerospike::ConnectionPool.new(cluster, host)
56
59
  end
57
60
 
61
+ def update_racks(parser)
62
+ new_racks = parser.update_racks
63
+ @racks.value = new_racks if new_racks
64
+ end
65
+
66
+ def has_rack(ns, rack_id)
67
+ racks = @racks.value
68
+ return false if !racks
69
+ racks[ns] == rack_id
70
+ end
71
+
58
72
  # Get a connection to the node. If no cached connection is not available,
59
73
  # a new connection will be created
60
74
  def get_connection(timeout)
@@ -178,10 +192,6 @@ module Aerospike
178
192
  end
179
193
  alias eql? ==
180
194
 
181
- def use_new_info?
182
- @use_new_info.value
183
- end
184
-
185
195
  def hash
186
196
  @name.hash
187
197
  end
@@ -202,6 +212,10 @@ module Aerospike
202
212
  Node::Refresh::Partitions.(self, peers)
203
213
  end
204
214
 
215
+ def refresh_racks()
216
+ Node::Refresh::Racks.(self)
217
+ end
218
+
205
219
  def refresh_peers(peers)
206
220
  Node::Refresh::Peers.(self, peers)
207
221
  end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2018 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
11
+ #
12
+ # http://www.apache.org/licenses/LICENSE-2.0
13
+ #
14
+ # Unless required by applicable law or agreed to in writing, software
15
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
16
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
17
+ # License for the specific language governing permissions and limitations under
18
+ # the License.
19
+
20
+ module Aerospike
21
+ class Node
22
+ # generic class for representing changes in eg. peer and partition generation
23
+ class Rebalance
24
+ attr_reader :generation
25
+
26
+ def initialize(generation = -1)
27
+ @generation = ::Aerospike::Atomic.new(generation)
28
+ @changed = ::Aerospike::Atomic.new(false)
29
+ end
30
+
31
+ def changed?
32
+ @changed.value == true
33
+ end
34
+
35
+ def eql?(generation)
36
+ @generation.value == generation
37
+ end
38
+
39
+ def reset_changed!
40
+ @changed.value = false
41
+ end
42
+
43
+ def update(new_generation)
44
+ return if @generation.value == new_generation
45
+ @generation.value = new_generation
46
+ @changed.value = true
47
+ end
48
+ end
49
+ end
50
+ end
@@ -24,14 +24,17 @@ module Aerospike
24
24
  CMDS_BASE = %w[node partition-generation cluster-name].freeze
25
25
  CMDS_PEERS = (CMDS_BASE + ['peers-generation']).freeze
26
26
  CMDS_SERVICES = (CMDS_BASE + ['services']).freeze
27
+ CMDS_REBALANCE = (CMDS_PEERS + ['rebalance-generation']).freeze
27
28
 
28
29
  class << self
29
30
  def call(node, peers)
30
31
  conn = node.tend_connection
31
32
  if peers.use_peers?
32
- info_map = ::Aerospike::Info.request(conn, *CMDS_PEERS)
33
+ cmds = node.cluster.rack_aware ? CMDS_REBALANCE : CMDS_PEERS
34
+ info_map = ::Aerospike::Info.request(conn, *cmds)
33
35
  Verify::PeersGeneration.(node, info_map, peers)
34
36
  Verify::PartitionGeneration.(node, info_map)
37
+ Verify::RebalanceGeneration.(node, info_map) if node.cluster.rack_aware
35
38
  Verify::Name.(node, info_map)
36
39
  Verify::ClusterName.(node, info_map)
37
40
  else
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Copyright 2018 Aerospike, Inc.
3
+ # Copyright 2018-2020 Aerospike, Inc.
4
4
  #
5
5
  # Portions may be licensed to Aerospike, Inc. under one or more contributor
6
6
  # license agreements.
@@ -25,24 +25,15 @@ module Aerospike
25
25
  def call(node, peers)
26
26
  return unless should_refresh?(node, peers)
27
27
 
28
- node.cluster.update_partitions(tokenizer(node), node)
28
+ Aerospike.logger.info("Updating partitions for node #{node.name}")
29
+ conn = node.tend_connection
30
+ parser = PartitionParser.new(node, conn)
31
+ node.cluster.update_partitions(parser)
29
32
  rescue ::Aerospike::Exceptions::Aerospike => e
30
- node.tend_connection.close
33
+ conn.close
31
34
  Refresh::Failed.(node, e)
32
35
  end
33
36
 
34
- # Return correct tokenizer depending on version
35
- def tokenizer(node)
36
- conn = node.tend_connection
37
- if node.use_new_info?
38
- Aerospike.logger.info("Updating partitions for node #{node.name} using new protocol")
39
- PartitionTokenizerNew.new(conn)
40
- else
41
- Aerospike.logger.info("Updating partitions for node #{node.name} using old protocol")
42
- PartitionTokenizerOld.new(conn)
43
- end
44
- end
45
-
46
37
  # Do not refresh partitions when node connection has already failed
47
38
  # during this cluster tend iteration. Also, avoid "split cluster"
48
39
  # case where this node thinks it's a 1-node cluster. Unchecked, such
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2018-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
11
+ #
12
+ # http://www.apache.org/licenses/LICENSE-2.0
13
+ #
14
+ # Unless required by applicable law or agreed to in writing, software
15
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
16
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
17
+ # License for the specific language governing permissions and limitations under
18
+ # the License.
19
+
20
+ module Aerospike
21
+ class Node
22
+ module Refresh
23
+ module Racks
24
+ class << self
25
+ def call(node)
26
+ return unless should_refresh?(node)
27
+
28
+ Aerospike.logger.info("Updating racks for node #{node.name}")
29
+ conn = node.tend_connection
30
+ parser = RackParser.new(node, conn)
31
+ node.update_racks(parser)
32
+ rescue ::Aerospike::Exceptions::Aerospike => e
33
+ conn.close
34
+ Refresh::Failed.(node, e)
35
+ end
36
+
37
+ # Do not refresh racks when node connection has already failed
38
+ # during this cluster tend iteration.
39
+ def should_refresh?(node)
40
+ return false if node.failed? || !node.active?
41
+ true
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end