aerospike 4.0.0 → 4.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cbbb3eae452fb9c1bbe7a0a99e7505b4fa774396b9591edc80ae707abb9896e0
4
- data.tar.gz: cd2bf9f22247dbc8f49581507b17f6347edf0a6f46a0c307f87eae45c3bf775b
3
+ metadata.gz: e3f436fbfb9e52e5bc36f953a2392559ca2455c8b1f7b8e2749511c6eb6bef62
4
+ data.tar.gz: '0947b6de2c480f3cbeada2da92c9394142bb376bcc4c4fd216eca2970b59e112'
5
5
  SHA512:
6
- metadata.gz: 88c12b118fcdf74f170a06ac3158b47f3e81076ee7c851d5ca06ea80b82d2b668c2df6588444e22c011dd43cbddce6586ecaaa30c895e54cefd47573e75b55ac
7
- data.tar.gz: ffc436ee1b5696765fdc8ab00f87ef0c6e33afea3ae3ddc2d63dcd01fed91e62f3ddb8b109acf9fae65bc5bcabd9c1f36af8c60b87e86fb25c8b1528ed5e926b
6
+ metadata.gz: 6322255e49d66ca929b88ffcb38110ae0d2f40cb8a6ba9b616291c9befb61f41c6b2a00ac5d01afa7ca4233eb748f2a7245dcd41d87394022847617f039acf96
7
+ data.tar.gz: a928ce8356bf8d36377bd165e5939dad19f3a052285f181e2b7a178528f1d66f47de57d4f729578453451cc7d18c70f341667e0f681f21fb0b666519425019fb
data/CHANGELOG.md CHANGED
@@ -2,6 +2,20 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
+ ## [4.1.0] 2024-10-22
6
+
7
+ - **New Features**
8
+ - [CLIENT-2833] Support `Policy#ReadTouchTtlPercent`.
9
+ - [CLIENT-2826] Support `QueryDuration` in `QueryPolicy#ExpectedDuration`.
10
+ - [CLIENT-3103] Support `XDR_KEY_BUSY`.
11
+
12
+ - **Fixes**
13
+ - [CLIENT-3144] Various fixes. PR #132 and #133 Thanks to [Igor Pstyga](https://github.com/opti)
14
+ - Fix `BatchRead` for multiple records with operations.
15
+ - Use correct namespace for the `MapReturnType`.
16
+ - `BatchRead` with operations would throw an exception.
17
+ - Fix a test with invalid map key in Server v7.1.
18
+
5
19
  ## [4.0.0] 2024-08-14
6
20
 
7
21
  - **New Features**
@@ -75,7 +75,7 @@ module Aerospike
75
75
  @write_attr = 0
76
76
  @info_attr = 0
77
77
 
78
- @expiration = 0
78
+ @expiration = rp.read_touch_ttl_percent
79
79
  @generation = 0
80
80
  @has_write = false
81
81
  @send_key = false
@@ -88,7 +88,7 @@ module Aerospike
88
88
  @write_attr = 0
89
89
  @info_attr = 0
90
90
 
91
- @expiration = 0
91
+ @expiration = rp.read_touch_ttl_percent
92
92
  @generation = 0
93
93
  @has_write = false
94
94
  @send_key = false
@@ -68,7 +68,7 @@ module Aerospike
68
68
  # For internal use only.
69
69
  def ==(other) # :nodoc:
70
70
  other && other.instance_of?(self.class) &&
71
- @bin_names.sort == other.bin_names.sort && @ops.sort == other.ops.sort &&
71
+ @bin_names&.sort == other.bin_names&.sort && @ops == other.ops &&
72
72
  @policy == other.policy && @read_all_bins == other.read_all_bins
73
73
  end
74
74
 
@@ -88,7 +88,7 @@ module Aerospike
88
88
  raise AerospikeException.new(ResultCode::PARAMETER_ERROR, "Write operations not allowed in batch read")
89
89
  end
90
90
  size += op.bin_name.bytesize + Aerospike::OPERATION_HEADER_SIZE
91
- size += op.value.estimate_size
91
+ size += op.bin_value.estimate_size
92
92
  end
93
93
 
94
94
  size
@@ -62,7 +62,7 @@ module Aerospike
62
62
  end
63
63
  end
64
64
  size_buffer
65
- write_header_read(policy, read_attr | INFO1_BATCH, 0, field_count, 0)
65
+ write_header_read(policy, read_attr | INFO1_BATCH, 0, 0, field_count, 0)
66
66
 
67
67
  write_filter_exp(@policy.filter_exp, exp_size)
68
68
 
@@ -92,7 +92,7 @@ module Aerospike
92
92
  if record.bin_names&.length&.> 0
93
93
  write_batch_bin_names(key, record.bin_names, attr, attr.filter_exp)
94
94
  elsif record.ops&.length&.> 0
95
- attr.adjust_read(br.ops)
95
+ attr.adjust_read(record.ops)
96
96
  write_batch_operations(key, record.ops, attr, attr.filter_exp)
97
97
  else
98
98
  attr.adjust_read_all_bins(record.read_all_bins)
@@ -58,7 +58,8 @@ module Aerospike
58
58
  INFO2_DURABLE_DELETE = Integer(1 << 4)
59
59
  # Create only. Fail if record already exists.
60
60
  INFO2_CREATE_ONLY = Integer(1 << 5)
61
-
61
+ # Treat as long query, but relax read consistency.
62
+ INFO2_RELAX_AP_LONG_QUERY = (1 << 6)
62
63
  # Return a result for every operation.
63
64
  INFO2_RESPOND_ALL_OPS = Integer(1 << 7)
64
65
 
@@ -195,7 +196,7 @@ module Aerospike
195
196
  field_count += 1 if exp_size > 0
196
197
 
197
198
  size_buffer
198
- write_header_read(policy, INFO1_READ | INFO1_GET_ALL, 0, field_count, 0)
199
+ write_header_read(policy, INFO1_READ | INFO1_GET_ALL, 0, 0, field_count, 0)
199
200
  write_key(key)
200
201
  write_filter_exp(@policy.filter_exp, exp_size)
201
202
  end_cmd
@@ -220,7 +221,7 @@ module Aerospike
220
221
  attr |= INFO1_GET_ALL
221
222
  end
222
223
 
223
- write_header_read(policy, attr, 0, field_count, bin_names.length)
224
+ write_header_read(policy, attr, 0, 0, field_count, bin_names.length)
224
225
  write_key(key)
225
226
  write_filter_exp(@policy.filter_exp, exp_size)
226
227
 
@@ -269,7 +270,7 @@ module Aerospike
269
270
 
270
271
  size_buffer
271
272
 
272
- write_header_read_write(policy, args.read_attr, args.write_attr, field_count, args.operations.length)
273
+ write_header_read_write(policy, args, field_count)
273
274
  write_key(key, policy)
274
275
  write_filter_exp(policy.filter_exp, exp_size)
275
276
 
@@ -377,7 +378,7 @@ module Aerospike
377
378
  operation_count = bin_names.length
378
379
  end
379
380
 
380
- write_header_read(policy, read_attr, info_attr, field_count, operation_count)
381
+ write_header_read(policy, read_attr, 0, info_attr, field_count, operation_count)
381
382
 
382
383
  if namespace
383
384
  write_field_string(namespace, Aerospike::FieldType::NAMESPACE)
@@ -591,10 +592,16 @@ module Aerospike
591
592
  write_header_write(policy, INFO2_WRITE, field_count, operation_count)
592
593
  else
593
594
  read_attr = INFO1_READ
595
+ write_attr = 0
596
+
594
597
  read_attr |= INFO1_NOBINDATA unless policy.include_bin_data
595
- read_attr |= INFO1_SHORT_QUERY if policy.short_query
598
+ if policy.short_query || policy.expected_duration == QueryDuration::SHORT
599
+ read_attr |= INFO1_SHORT_QUERY
600
+ elsif policy.expected_duration == QueryDuration::LONG_RELAX_AP
601
+ write_attr |= INFO2_RELAX_AP_LONG_QUERY
602
+ end
596
603
  info_attr = INFO3_PARTITION_DONE if is_new
597
- write_header_read(policy, read_attr, info_attr, field_count, operation_count)
604
+ write_header_read(policy, read_attr, write_attr, info_attr, field_count, operation_count)
598
605
  end
599
606
 
600
607
 
@@ -903,10 +910,14 @@ module Aerospike
903
910
  end
904
911
 
905
912
  # Header write for write operations.
906
- def write_header_read_write(policy, read_attr, write_attr, field_count, operation_count)
913
+ def write_header_read_write(policy, args, field_count)
907
914
  # Set flags.
908
915
  generation = Integer(0)
916
+ ttl = args.has_write ? policy.expiration : policy.read_touch_ttl_percent
917
+ read_attr = args.read_attr
918
+ write_attr = args.write_attr
909
919
  info_attr = Integer(0)
920
+ operation_count = args.operations.length
910
921
 
911
922
  case policy.record_exists_action
912
923
  when Aerospike::RecordExistsAction::UPDATE
@@ -942,7 +953,7 @@ module Aerospike
942
953
  @data_buffer.write_byte(0, 12) # unused
943
954
  @data_buffer.write_byte(0, 13) # clear the result code
944
955
  @data_buffer.write_uint32(generation, 14)
945
- @data_buffer.write_uint32(policy.ttl, 18)
956
+ @data_buffer.write_uint32(ttl, 18)
946
957
 
947
958
  # Initialize timeout. It will be written later.
948
959
  @data_buffer.write_byte(0, 22)
@@ -956,18 +967,19 @@ module Aerospike
956
967
  @data_offset = MSG_TOTAL_HEADER_SIZE
957
968
  end
958
969
 
959
- def write_header_read(policy, read_attr, info_attr, field_count, operation_count)
970
+ def write_header_read(policy, read_attr, write_attr, info_attr, field_count, operation_count)
960
971
  read_attr |= INFO1_COMPRESS_RESPONSE if policy.use_compression
961
972
  #TODO: Add SC Mode
962
973
 
963
974
  @data_buffer.write_byte(MSG_REMAINING_HEADER_SIZE, 8) # Message header.length.
964
975
  @data_buffer.write_byte(read_attr, 9)
965
- @data_buffer.write_byte(0, 10)
976
+ @data_buffer.write_byte(write_attr, 10)
966
977
  @data_buffer.write_byte(info_attr, 11)
967
978
 
968
- (12...22).each { |i| @data_buffer.write_byte(0, i) }
979
+ (12...18).each { |i| @data_buffer.write_byte(0, i) }
969
980
 
970
981
  # Initialize timeout. It will be written later.
982
+ @data_buffer.write_int32(policy.read_touch_ttl_percent, 18)
971
983
  @data_buffer.write_byte(0, 22)
972
984
  @data_buffer.write_byte(0, 23)
973
985
  @data_buffer.write_byte(0, 24)
@@ -988,9 +1000,10 @@ module Aerospike
988
1000
  @data_buffer.write_byte(0, 10)
989
1001
  @data_buffer.write_byte(info_attr, 11)
990
1002
 
991
- (12...22).each { |i| @data_buffer.write_byte(0, i) }
1003
+ (12...18).each { |i| @data_buffer.write_byte(0, i) }
992
1004
 
993
1005
  # Initialize timeout. It will be written later.
1006
+ @data_buffer.write_int32(policy.read_touch_ttl_percent, 18)
994
1007
  @data_buffer.write_byte(0, 22)
995
1008
  @data_buffer.write_byte(0, 23)
996
1009
  @data_buffer.write_byte(0, 24)
@@ -476,21 +476,21 @@ module Aerospike
476
476
  def self.get_value_type(return_type)
477
477
  t = return_type & ~CDT::MapReturnType::INVERTED
478
478
  case t
479
- when MapReturnType::INDEX, MapReturnType::REVERSE_INDEX, MapReturnType::RANK, MapReturnType::REVERSE_RANK
479
+ when CDT::MapReturnType::INDEX, CDT::MapReturnType::REVERSE_INDEX, CDT::MapReturnType::RANK, CDT::MapReturnType::REVERSE_RANK
480
480
  # This method only called from expressions that can return multiple integers (ie list).
481
481
  Exp::Type::LIST
482
482
 
483
- when MapReturnType::COUNT
483
+ when CDT::MapReturnType::COUNT
484
484
  Exp::Type::INT
485
485
 
486
- when MapReturnType::KEY, MapReturnType::VALUE
486
+ when CDT::MapReturnType::KEY, CDT::MapReturnType::VALUE
487
487
  # This method only called from expressions that can return multiple objects (ie list).
488
488
  Exp::Type::LIST
489
489
 
490
- when MapReturnType::KEY_VALUE, MapReturnType::ORDERED_MAP, MapReturnType::UNORDERED_MAP
490
+ when CDT::MapReturnType::KEY_VALUE, CDT::MapReturnType::ORDERED_MAP, CDT::MapReturnType::UNORDERED_MAP
491
491
  Exp::Type::MAP
492
492
 
493
- when MapReturnType::EXISTS
493
+ when CDT::MapReturnType::EXISTS
494
494
  Exp::Type::BOOL
495
495
 
496
496
  else
@@ -20,7 +20,7 @@ module Aerospike
20
20
  # Policy attributes used in batch read commands.
21
21
  class BatchReadPolicy
22
22
 
23
- attr_accessor :filter_exp
23
+ attr_accessor :filter_exp, :read_touch_ttl_percent
24
24
 
25
25
  def initialize(opt={})
26
26
  # Optional expression filter. If filter_exp exists and evaluates to false, the specific batch key
@@ -33,6 +33,23 @@ module Aerospike
33
33
  #
34
34
  # Default: nil
35
35
  @filter_exp = opt[:filter_exp]
36
+
37
+ # Determines how record TTL (time to live) is affected on reads. When enabled, the server can
38
+ # efficiently operate as a read-based LRU cache where the least recently used records are expired.
39
+ # The value is expressed as a percentage of the TTL sent on the most recent write such that a read
40
+ # within this interval of the record’s end of life will generate a touch.
41
+ #
42
+ # For example, if the most recent write had a TTL of 10 hours and read_touch_ttl_percent is set to
43
+ # 80, the next read within 8 hours of the record's end of life (equivalent to 2 hours after the most
44
+ # recent write) will result in a touch, resetting the TTL to another 10 hours.
45
+ #
46
+ # Values:
47
+ #
48
+ # 0 : Use server config default-read-touch-ttl-pct for the record's namespace/set.
49
+ # -1 : Do not reset record TTL on reads.
50
+ # 1 - 100 : Reset record TTL on reads when within this percentage of the most recent write TTL.
51
+ # Default: 0
52
+ @read_touch_ttl_percent = opt[:read_touch_ttl_percent] || 0
36
53
  end
37
54
  end
38
55
  end
@@ -22,7 +22,7 @@ module Aerospike
22
22
  # Container object for client policy command.
23
23
  class Policy
24
24
  attr_accessor :filter_exp, :priority, :timeout, :max_retries, :sleep_between_retries, :consistency_level,
25
- :fail_on_filtered_out, :replica, :use_compression, :socket_timeout
25
+ :fail_on_filtered_out, :replica, :use_compression, :socket_timeout, :read_touch_ttl_percent
26
26
 
27
27
  alias total_timeout timeout
28
28
  alias total_timeout= timeout=
@@ -95,6 +95,23 @@ module Aerospike
95
95
  # has not yet been exceeded.
96
96
  @max_retries = opt[:max_retries] || 2
97
97
 
98
+ # Determines how record TTL (time to live) is affected on reads. When enabled, the server can
99
+ # efficiently operate as a read-based LRU cache where the least recently used records are expired.
100
+ # The value is expressed as a percentage of the TTL sent on the most recent write such that a read
101
+ # within this interval of the record’s end of life will generate a touch.
102
+ #
103
+ # For example, if the most recent write had a TTL of 10 hours and read_touch_ttl_percent is set to
104
+ # 80, the next read within 8 hours of the record's end of life (equivalent to 2 hours after the most
105
+ # recent write) will result in a touch, resetting the TTL to another 10 hours.
106
+ #
107
+ # Values:
108
+ #
109
+ # 0 : Use server config default-read-touch-ttl-pct for the record's namespace/set.
110
+ # -1 : Do not reset record TTL on reads.
111
+ # 1 - 100 : Reset record TTL on reads when within this percentage of the most recent write TTL.
112
+ # Default: 0
113
+ @read_touch_ttl_percent = opt[:read_touch_ttl_percent] || 0
114
+
98
115
  # Duration to sleep between retries if a transaction fails and the
99
116
  # timeout was not exceeded. Enter zero to skip sleep.
100
117
  @sleep_between_retries = opt[:sleep_between_retries] || 0.5
@@ -0,0 +1,48 @@
1
+ # encoding: utf-8
2
+ # Copyright 2014-2024 Aerospike, Inc.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http:#www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+
16
+ module Aerospike
17
+
18
+ # Defines the expected query duration. The server treats the query in different ways depending on the expected duration.
19
+ # This enum is ignored for aggregation queries, background queries and server versions < 6.0.
20
+ module QueryDuration
21
+
22
+ # The query is expected to return more than 100 records per node. The server optimizes for a large record set in
23
+ # the following ways:
24
+ #
25
+ # Allow query to be run in multiple threads using the server's query threading configuration.
26
+ # Do not relax read consistency for AP namespaces.
27
+ # Add the query to the server's query monitor.
28
+ # Do not add the overall latency to the server's latency histogram.
29
+ # Do not allow server timeouts.
30
+ LONG = 0
31
+
32
+ # The query is expected to return less than 100 records per node. The server optimizes for a small record set in
33
+ # the following ways:
34
+ # Always run the query in one thread and ignore the server's query threading configuration.
35
+ # Allow query to be inlined directly on the server's service thread.
36
+ # Relax read consistency for AP namespaces.
37
+ # Do not add the query to the server's query monitor.
38
+ # Add the overall latency to the server's latency histogram.
39
+ # Allow server timeouts. The default server timeout for a short query is 1 second.
40
+ SHORT = 1
41
+
42
+ # Treat query as a LONG query, but relax read consistency for AP namespaces.
43
+ # This value is treated exactly like LONG for server versions < 7.1.
44
+ LONG_RELAX_AP = 2
45
+
46
+ end # module
47
+
48
+ end # module
@@ -15,6 +15,7 @@
15
15
  # License for the specific language governing permissions and limitations under
16
16
  # the License.
17
17
 
18
+ require 'aerospike/policy/query_duration'
18
19
  require 'aerospike/policy/policy'
19
20
 
20
21
  module Aerospike
@@ -22,16 +23,10 @@ module Aerospike
22
23
  # Container object for query policy command.
23
24
  class QueryPolicy < Policy
24
25
 
25
- attr_accessor :concurrent_nodes
26
- attr_accessor :max_records
27
- attr_accessor :include_bin_data
28
- attr_accessor :record_queue_size
29
- attr_accessor :records_per_second
30
- attr_accessor :socket_timeout
31
- attr_accessor :short_query
26
+ attr_accessor :concurrent_nodes, :max_records, :include_bin_data, :record_queue_size, :records_per_second, :socket_timeout, :short_query, :expected_duration
32
27
 
33
28
  def initialize(opt={})
34
- super(opt)
29
+ super
35
30
 
36
31
  # Indicates if bin data is retrieved. If false, only record digests (and
37
32
  # user keys if stored on the server) are retrieved.
@@ -74,11 +69,21 @@ module Aerospike
74
69
  # Default is 0
75
70
  @records_per_second = opt[:records_per_second] || 0
76
71
 
72
+ # Expected query duration. The server treats the query in different ways depending on the expected duration.
73
+ # This field is ignored for aggregation queries, background queries and server versions < 6.0.
74
+ #
75
+ # Default: QueryDuration::LONG
76
+ @expected_duration = opt[:expected_duration] || QueryDuration::LONG
77
+
78
+ # DEPRECATED
77
79
  # Detemine wether query expected to return less than 100 records.
78
80
  # If true, the server will optimize the query for a small record set.
79
81
  # This field is ignored for aggregation queries, background queries
80
82
  # and server versions 6.0+.
81
83
  #
84
+ # This field is deprecated and will eventually be removed. Use {expected_duration} instead.
85
+ # For backwards compatibility: If ShortQuery is true, the query is treated as a short query and
86
+ # {expected_duration} is ignored. If {short_query} is false, {expected_duration} is used as defaults to {Policy#QueryDuration#LONG}.
82
87
  # Default: false
83
88
  @short_query = opt[:short_query] ||false
84
89
 
@@ -168,6 +168,9 @@ module Aerospike
168
168
  # Write command loses conflict to XDR.
169
169
  LOST_CONFLICT = 28
170
170
 
171
+ # Write can't complete until XDR finishes shipping.
172
+ XDR_KEY_BUSY = 32
173
+
171
174
  # There are no more records left for query.
172
175
  QUERY_END = 50
173
176
 
@@ -445,6 +448,10 @@ module Aerospike
445
448
  when LOST_CONFLICT
446
449
  "Write command loses conflict to XDR."
447
450
 
451
+ # Write can't complete until XDR finishes shipping.
452
+ when XDR_KEY_BUSY
453
+ "XDR key busy"
454
+
448
455
  when QUERY_END
449
456
  "Query end"
450
457
 
@@ -580,7 +587,6 @@ module Aerospike
580
587
  else
581
588
  "ResultCode #{code} unknown in the client. Please file a github issue."
582
589
  end # case
583
-
584
590
  end
585
591
 
586
592
  end # class
@@ -1,4 +1,4 @@
1
1
  # encoding: utf-8
2
2
  module Aerospike
3
- VERSION = "4.0.0"
3
+ VERSION = "4.1.0"
4
4
  end
data/lib/aerospike.rb CHANGED
@@ -90,6 +90,7 @@ require "aerospike/cdt/bit_policy"
90
90
  require "aerospike/geo_json"
91
91
  require "aerospike/ttl"
92
92
 
93
+ require "aerospike/policy/query_duration"
93
94
  require "aerospike/policy/client_policy"
94
95
  require "aerospike/policy/priority"
95
96
  require "aerospike/policy/record_exists_action"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: aerospike
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.0.0
4
+ version: 4.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Khosrow Afroozeh
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2024-08-14 00:00:00.000000000 Z
13
+ date: 2024-10-22 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: msgpack
@@ -166,6 +166,7 @@ files:
166
166
  - lib/aerospike/policy/operate_policy.rb
167
167
  - lib/aerospike/policy/policy.rb
168
168
  - lib/aerospike/policy/priority.rb
169
+ - lib/aerospike/policy/query_duration.rb
169
170
  - lib/aerospike/policy/query_policy.rb
170
171
  - lib/aerospike/policy/record_bin_multiplicity.rb
171
172
  - lib/aerospike/policy/record_exists_action.rb