aerospike 2.26.0 → 2.27.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: 569388197af73988d3965e15f8b7caf42605896f21183a0e6f7d507690dec816
4
- data.tar.gz: dfe35172403817d176aecfd83747e6155a961b92960a97f8efc713a6b7540d23
3
+ metadata.gz: 3fe67950bfa737ce26a8a0e823cd84424219c6ce41720e0202ca93d4dcab2c1d
4
+ data.tar.gz: 83976d88565599f00136967bd86fe832a88783518c51be2789c1463fa06e795e
5
5
  SHA512:
6
- metadata.gz: e4de68155586c168c75a51c71749531becdf066cb22888745f8473237cb775dd9054c6401e44a04b00bee517848859d128141692da3fc7c970df2f202e5e49b9
7
- data.tar.gz: 7c041a196f2bf45a3ff575426b9269ba45c10e16f641c82f5ce11e362ace013d2480c407b8f1e9a663a27bcf78df1988d6af46de2bd22d41c0fce5366fb2a52c
6
+ metadata.gz: e018d80b673081cdbf229aa5c48dd7ebbeb9a127492cc04c651a4e56bab92d7764aba82ffb3e3783f6a6f34755ded66be58c3bf5a9e110be61c0c21e20128932
7
+ data.tar.gz: 8e02a4d37b620f838dde53b63d4af3fe20146905dd4f3a30c14f97a83453c69f0dccfbaf1f44a777bf4ab53e89583cc7a6e4343204e6749b1d4fb888f0a7200f
data/CHANGELOG.md CHANGED
@@ -2,6 +2,11 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
+ ## [2.27.0] 2023-05-18
6
+ - **New Features**
7
+ - [CLIENT-1176] Support write operations in background query
8
+
9
+
5
10
  ## [2.26.0] 2022-12-02
6
11
 
7
12
  - **New Features**
@@ -1,4 +1,4 @@
1
- # Copyright 2014-2020 Aerospike, Inc.
1
+ # Copyright 2014-2023 Aerospike, Inc.
2
2
  #
3
3
  # Portions may be licensed to Aerospike, Inc. under one or more contributor
4
4
  # license agreements.
@@ -225,7 +225,6 @@ module Aerospike
225
225
  policy = create_policy(options, Policy, default_info_policy)
226
226
 
227
227
  node = @cluster.random_node
228
- conn = node.get_connection(policy.timeout)
229
228
 
230
229
  if set_name && !set_name.to_s.strip.empty?
231
230
  str_cmd = "truncate:namespace=#{namespace}"
@@ -731,6 +730,59 @@ module Aerospike
731
730
  query_partitions(Aerospike::PartitionFilter.all, statement, options)
732
731
  end
733
732
 
733
+ #----------------------------------------------------------
734
+ # Query/Execute (Supported by Aerospike 3+ servers only)
735
+ #----------------------------------------------------------
736
+
737
+ # QueryExecute applies operations on records that match the statement filter.
738
+ # Records are not returned to the client.
739
+ # This asynchronous server call will return before the command is complete.
740
+ # The user can optionally wait for command completion by using the returned
741
+ # ExecuteTask instance.
742
+ #
743
+ # This method is only supported by Aerospike 3+ servers.
744
+ # If the policy is nil, the default relevant policy will be used.
745
+ #
746
+ # @param statement [Aerospike::Statement] The query or batch read statement.
747
+ # @param operations [Array<Aerospike::Operation>] An optional list of operations.
748
+ # @param options [Hash] An optional hash of policy options.
749
+ # @return [Aerospike::ExecuteTask] An ExecuteTask instance that can be used to wait for command completion.
750
+ #
751
+ # @raise [Aerospike::Exceptions::Aerospike] if an error occurs during the operation.
752
+ def query_execute(statement, operations = [], options = nil)
753
+ policy = create_policy(options, WritePolicy, default_write_policy)
754
+
755
+ if statement.nil?
756
+ raise Aerospike::Exceptions::Aerospike.new(Aerospike::ResultCode::INVALID_COMMAND, "Query failed of invalid statement.")
757
+ end
758
+
759
+ statement = statement.clone
760
+ unless operations.empty?
761
+ statement.operations = operations
762
+ end
763
+
764
+ task_id = statement.task_id
765
+ nodes = @cluster.nodes
766
+ if nodes.empty?
767
+ raise Aerospike::Exceptions::Aerospike.new(Aerospike::ResultCode::SERVER_NOT_AVAILABLE, "Query failed because cluster is empty.")
768
+ end
769
+
770
+ # Use a thread per node
771
+ nodes.each do |node|
772
+ Thread.new do
773
+ Thread.current.abort_on_exception = true
774
+ begin
775
+ command = ServerCommand.new(@cluster, node, policy, statement, true, task_id)
776
+ execute_command(command)
777
+ rescue => e
778
+ Aerospike.logger.error(e)
779
+ raise e
780
+ end
781
+ end
782
+ end
783
+ ExecuteTask.new(@cluster, statement)
784
+ end
785
+
734
786
  #-------------------------------------------------------
735
787
  # User administration
736
788
  #-------------------------------------------------------
@@ -1,4 +1,4 @@
1
- # Copyright 2014-2020 Aerospike, Inc.
1
+ # Copyright 2014-2024 Aerospike, Inc.
2
2
  #
3
3
  # Portions may be licensed to Aerospike, Inc. under one or more contributor
4
4
  # license agreements.
@@ -465,6 +465,254 @@ module Aerospike
465
465
  end_cmd
466
466
  end
467
467
 
468
+ def set_query(policy, statement, background, node_partitions)
469
+ function_arg_buffer = nil
470
+ field_count = 0
471
+ filter_size = 0
472
+
473
+ begin_cmd
474
+
475
+ if statement.namespace
476
+ @data_offset += statement.namespace.bytesize + FIELD_HEADER_SIZE
477
+ field_count += 1
478
+ end
479
+
480
+ if statement.set_name
481
+ @data_offset += statement.set_name.bytesize + FIELD_HEADER_SIZE
482
+ field_count += 1
483
+ end
484
+
485
+ # Estimate recordsPerSecond field size. This field is used in new servers and not used
486
+ # (but harmless to add) in old servers.
487
+ if statement.records_per_second > 0
488
+ @data_offset += 4 + FIELD_HEADER_SIZE
489
+ field_count += 1
490
+ end
491
+
492
+ # Estimate socket timeout field size. This field is used in new servers and not used
493
+ # (but harmless to add) in old servers.
494
+ @data_offset += 4 + FIELD_HEADER_SIZE
495
+ field_count += 1
496
+
497
+ # Estimate task_id field.
498
+ @data_offset += 8 + FIELD_HEADER_SIZE
499
+ field_count += 1
500
+
501
+ filter = statement.filters[0]
502
+ bin_names = statement.bin_names
503
+ packed_ctx = nil
504
+
505
+ if filter
506
+ col_type = filter.collection_type
507
+
508
+ # Estimate INDEX_TYPE field.
509
+ if col_type > 0
510
+ @data_offset += FIELD_HEADER_SIZE + 1
511
+ field_count += 1
512
+ end
513
+
514
+ # Estimate INDEX_RANGE field.
515
+ @data_offset += FIELD_HEADER_SIZE
516
+ filter_size += 1 # num filters
517
+ filter_size += filter.estimate_size
518
+
519
+ @data_offset += filter_size
520
+ field_count += 1
521
+
522
+ packed_ctx = filter.packed_ctx
523
+ if packed_ctx
524
+ @data_offset += FIELD_HEADER_SIZE + packed_ctx.length
525
+ field_count += 1
526
+ end
527
+ end
528
+
529
+ statement.set_task_id
530
+ predexp = policy.predexp || statement.predexp
531
+
532
+ if predexp
533
+ @data_offset += FIELD_HEADER_SIZE
534
+ pred_size = Aerospike::PredExp.estimate_size(predexp)
535
+ @data_offset += pred_size
536
+ field_count += 1
537
+ end
538
+
539
+ unless policy.filter_exp.nil?
540
+ exp_size = estimate_expression_size(policy.filter_exp)
541
+ field_count += 1 if exp_size > 0
542
+ end
543
+
544
+ # Estimate aggregation/background function size.
545
+ if statement.function_name
546
+ @data_offset += FIELD_HEADER_SIZE + 1 # udf type
547
+ @data_offset += statement.package_name.bytesize + FIELD_HEADER_SIZE
548
+ @data_offset += statement.function_name.bytesize + FIELD_HEADER_SIZE
549
+
550
+ function_arg_buffer = ""
551
+ if statement.function_args && statement.function_args.length > 0
552
+ function_arg_buffer = Value.of(statement.function_args).to_bytes
553
+ end
554
+ @data_offset += FIELD_HEADER_SIZE + function_arg_buffer.bytesize
555
+ field_count += 4
556
+ end
557
+
558
+ max_records = 0
559
+ parts_full_size = 0
560
+ parts_partial_digest_size = 0
561
+ parts_partial_bval_size = 0
562
+
563
+ unless node_partitions.nil?
564
+ parts_full_size = node_partitions.parts_full.length * 2
565
+ parts_partial_digest_size = node_partitions.parts_partial.length * 20
566
+
567
+ unless filter.nil?
568
+ parts_partial_bval_size = node_partitions.parts_partial.length * 8
569
+ end
570
+ max_records = node_partitions.record_max
571
+ end
572
+
573
+ if parts_full_size > 0
574
+ @data_offset += parts_full_size + FIELD_HEADER_SIZE
575
+ field_count += 1
576
+ end
577
+
578
+ if parts_partial_digest_size > 0
579
+ @data_offset += parts_partial_digest_size + FIELD_HEADER_SIZE
580
+ field_count += 1
581
+ end
582
+
583
+ if parts_partial_bval_size > 0
584
+ @data_offset += parts_partial_bval_size + FIELD_HEADER_SIZE
585
+ field_count += 1
586
+ end
587
+
588
+ # Estimate max records field size. This field is used in new servers and not used
589
+ # (but harmless to add) in old servers.
590
+ if max_records > 0
591
+ @data_offset += 8 + FIELD_HEADER_SIZE
592
+ field_count += 1
593
+ end
594
+
595
+ operations = statement.operations
596
+ operation_count = 0
597
+
598
+ if !operations.empty?
599
+
600
+ unless background
601
+ raise Aerospike::Exceptions::Aerospike.new(Aerospike::ResultCode::PARAMETER_ERROR)
602
+ end
603
+
604
+ operations.each do |operation|
605
+ estimate_operation_size_for_operation(operation)
606
+ end
607
+ operation_count = operations.size
608
+ elsif !bin_names.empty?
609
+ bin_names.each do |bin_name|
610
+ estimate_operation_size_for_bin_name(bin_name)
611
+ end
612
+ operation_count = bin_names.length
613
+ # Estimate size for selected bin names (query bin names already handled for old servers).
614
+ end
615
+
616
+ size_buffer
617
+
618
+ if background
619
+ write_header_with_policy(policy, 0, INFO2_WRITE, field_count, operation_count)
620
+ else
621
+ read_attr = INFO1_READ
622
+ read_attr |= INFO1_NOBINDATA unless policy.include_bin_data
623
+ read_attr |= INFO1_SHORT_QUERY if policy.short_query
624
+ write_header(policy, read_attr, 0, field_count, operation_count)
625
+ end
626
+
627
+ write_field_string(statement.namespace, FieldType::NAMESPACE) if statement.namespace
628
+ write_field_string(statement.set_name, FieldType::TABLE) if statement.set_name
629
+
630
+ # Write records per second.
631
+ write_field_int(statement.records_per_second, FieldType::RECORDS_PER_SECOND) if statement.records_per_second > 0
632
+
633
+ write_filter_exp(policy.filter_exp, exp_size)
634
+
635
+ # Write socket idle timeout.
636
+ write_field_int(policy.socket_timeout, FieldType::SOCKET_TIMEOUT)
637
+
638
+ # Write task_id field
639
+ write_field_int64(statement.task_id, FieldType::TRAN_ID)
640
+
641
+ unless predexp.nil?
642
+ write_field_header(pred_size, Aerospike::FieldType::PREDEXP)
643
+ @data_offset = Aerospike::PredExp.write(
644
+ predexp, @data_buffer, @data_offset
645
+ )
646
+ end
647
+
648
+ if filter
649
+ type = filter.collection_type
650
+
651
+ if type > 0
652
+ write_field_header(1, FieldType::INDEX_TYPE)
653
+ @data_offset += @data_buffer.write_byte(type, @data_offset)
654
+ end
655
+
656
+ write_field_header(filter_size, FieldType::INDEX_RANGE)
657
+ @data_offset += @data_buffer.write_byte(1, @data_offset)
658
+ @data_offset = filter.write(@data_buffer, @data_offset)
659
+
660
+ if packed_ctx
661
+ write_field_header(packed_ctx.length, FieldType::INDEX_CONTEXT)
662
+ @data_offset += @data_buffer.write_binary(packed_ctx, @data_offset)
663
+ end
664
+ end
665
+
666
+ if statement.function_name
667
+ write_field_header(1, FieldType::UDF_OP)
668
+ @data_offset += @data_buffer.write_byte(1, @data_offset)
669
+ write_field_string(statement.package_name, FieldType::UDF_PACKAGE_NAME)
670
+ write_field_string(statement.function_name, FieldType::UDF_FUNCTION)
671
+ write_field_string(function_arg_buffer, FieldType::UDF_ARGLIST)
672
+ end
673
+
674
+ if parts_full_size > 0
675
+ write_field_header(parts_full_size, FieldType::PID_ARRAY)
676
+ node_partitions.parts_full.each do |part|
677
+ @data_offset += @data_buffer.write_uint16_little_endian(part.id, @data_offset)
678
+ end
679
+ end
680
+
681
+ if parts_partial_digest_size > 0
682
+ write_field_header(parts_partial_digest_size, FieldType::DIGEST_ARRAY)
683
+ node_partitions.parts_partial.each do |part|
684
+ @data_offset += @data_buffer.write_binary(part.digest, @data_offset)
685
+ end
686
+ end
687
+
688
+ if parts_partial_bval_size > 0
689
+ write_field_header(parts_partial_bval_size, FieldType::BVAL_ARRAY)
690
+ @node_partitions.parts_partial.each do |part|
691
+ @data_offset += @data_buffer.write_uint64_little_endian(part.bval, @data_offset)
692
+ end
693
+ end
694
+
695
+ if max_records > 0
696
+ write_field(max_records, FieldType::MAX_RECORDS)
697
+ end
698
+
699
+ if operations.empty?
700
+ if bin_names.empty?
701
+ bin_names.each do |bin_name|
702
+ write_operation_for_bin_name(bin_name, Operation::READ)
703
+ end
704
+ end
705
+ else
706
+ operations.each do |operation|
707
+ write_operation_for_operation(operation)
708
+ end
709
+ end
710
+
711
+ end_cmd
712
+
713
+ nil
714
+ end
715
+
468
716
  def execute
469
717
  iterations = 0
470
718
 
@@ -537,7 +785,7 @@ module Aerospike
537
785
  parse_result
538
786
  rescue => e
539
787
  case e
540
- # do not log the following exceptions
788
+ # do not log the following exceptions
541
789
  when Aerospike::Exceptions::ScanTerminated
542
790
  when Aerospike::Exceptions::QueryTerminated
543
791
  else
@@ -703,9 +951,8 @@ module Aerospike
703
951
  read_attr |= INFO1_CONSISTENCY_ALL if policy.consistency_level == Aerospike::ConsistencyLevel::CONSISTENCY_ALL
704
952
  write_attr |= INFO2_DURABLE_DELETE if policy.durable_delete
705
953
  read_attr |= INFO1_COMPRESS_RESPONSE if policy.use_compression
706
-
707
954
  # Write all header data except total size which must be written last.
708
- @data_buffer.write_byte(MSG_REMAINING_HEADER_SIZE, 8) # Message heade.length.
955
+ @data_buffer.write_byte(MSG_REMAINING_HEADER_SIZE, 8) # Message header.length.
709
956
  @data_buffer.write_byte(read_attr, 9)
710
957
  @data_buffer.write_byte(write_attr, 10)
711
958
  @data_buffer.write_byte(info_attr, 11)
@@ -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
- :predexp, :fail_on_filtered_out, :replica, :use_compression
25
+ :predexp, :fail_on_filtered_out, :replica, :use_compression, :socket_timeout
26
26
 
27
27
  alias total_timeout timeout
28
28
  alias total_timeout= timeout=
@@ -133,6 +133,16 @@ module Aerospike
133
133
  # Duration to sleep between retries if a transaction fails and the
134
134
  # timeout was not exceeded. Enter zero to skip sleep.
135
135
  @sleep_between_retries = opt[:sleep_between_retries] || 0.5
136
+
137
+ # Determines network timeout for each attempt.
138
+ #
139
+ # If socket_timeout is not zero and socket_timeout is reached before an attempt completes,
140
+ # the Timeout above is checked. If Timeout is not exceeded, the transaction
141
+ # is retried. If both socket_timeout and Timeout are non-zero, socket_timeout must be less
142
+ # than or equal to Timeout, otherwise Timeout will also be used for socket_timeout.
143
+ #
144
+ # Default: 30s
145
+ @socket_timeout = opt[:socket_timeout] || 30000
136
146
  end
137
147
  end # class
138
148
  end # module
@@ -1,5 +1,5 @@
1
1
  # encoding: utf-8
2
- # Copyright 2014-2020 Aerospike, Inc.
2
+ # Copyright 2014-2023 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.
@@ -24,8 +24,8 @@ module Aerospike
24
24
  class WritePolicy < Policy
25
25
 
26
26
  attr_accessor :record_exists_action, :generation_policy,
27
- :generation, :ttl, :send_key, :commit_level,
28
- :durable_delete
27
+ :generation, :ttl, :send_key, :commit_level,
28
+ :durable_delete
29
29
 
30
30
  alias expiration ttl
31
31
  alias expiration= ttl=
@@ -74,6 +74,11 @@ module Aerospike
74
74
  # Valid for Aerospike Server Enterprise Edition 3.10+ only.
75
75
  @durable_delete = opt.fetch(:durable_delete, false)
76
76
 
77
+ # Transaction timeout.
78
+ # This timeout is used to set the socket timeout and is also sent to the
79
+ # server along with the transaction in the wire protocol.
80
+ # Default for write policy is 1.
81
+ @timeout = opt[:timeout] || 1
77
82
  self
78
83
  end
79
84
 
@@ -0,0 +1,60 @@
1
+ # encoding: utf-8
2
+ # Copyright 2014-2023 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
+
18
+ module Aerospike
19
+ class ServerCommand < MultiCommand
20
+ attr_accessor :statement, :task_id, :cluster, :write_policy, :background
21
+
22
+ def initialize(cluster, node, policy, statement, background, task_id)
23
+ super(node)
24
+ @statement = statement
25
+ @task_id = task_id
26
+ @cluster = cluster
27
+ @policy = policy
28
+ @background = background
29
+ end
30
+
31
+ def write?
32
+ true
33
+ end
34
+
35
+ def write_buffer
36
+ set_query(@policy, @statement, background, nil)
37
+ end
38
+
39
+ def parse_row
40
+ field_count = @data_buffer.read_int16(18)
41
+ result_code = @data_buffer.read(5).ord & 0xFF
42
+ skip_key(field_count)
43
+
44
+ if result_code != 0
45
+ if result_code == Aerospike::ResultCode::KEY_NOT_FOUND_ERROR
46
+ return false
47
+ end
48
+ raise Aerospike::Exceptions::Aerospike.new(result_code)
49
+ end
50
+ op_count = @data_buffer.read_int16(20)
51
+ if op_count <= 0
52
+ return Record.new(@node, key, bins, generation, expiration)
53
+ end
54
+
55
+ unless valid?
56
+ raise Aerospike::Exceptions::QueryTerminated
57
+ end
58
+ end
59
+ end
60
+ end
@@ -1,5 +1,5 @@
1
1
  # encoding: utf-8
2
- # Copyright 2014-2020 Aerospike, Inc.
2
+ # Copyright 2014-2023 Aerospike, Inc.
3
3
  #
4
4
  # Portions may be licensed to Aerospike, Inc. under one or more contributor
5
5
  # license agreements.
@@ -16,11 +16,14 @@
16
16
 
17
17
  module Aerospike
18
18
 
19
+ # The Aerospike::Statement class represents a query or scan statement to be executed on the database.
20
+ # It provides a set of properties that define the query or scan, including namespace, set name, bin names,
21
+ # index name, filters, and operations.
19
22
  class Statement
20
23
 
21
24
  attr_accessor :namespace, :set_name, :index_name, :bin_names, :task_id
22
- attr_accessor :filters, :package_name, :function_name, :function_args
23
- attr_accessor :predexp, :return_data
25
+ attr_accessor :filters, :package_name, :function_name, :function_args, :operations
26
+ attr_accessor :predexp, :return_data, :records_per_second
24
27
 
25
28
  def initialize(namespace, set_name, bin_names=[])
26
29
  # Namespace determines query Namespace
@@ -56,6 +59,14 @@ module Aerospike
56
59
  @package_name = nil
57
60
  @function_name = nil
58
61
  @function_args = nil
62
+ @operations = nil
63
+
64
+
65
+ # Limit returned records per second (rps) rate for each server.
66
+ # Will not apply rps limit if records_per_second is zero.
67
+ # Currently only applicable to a query without a defined filter (scan).
68
+ # Default is 0
69
+ @records_per_second = 0
59
70
 
60
71
  # TaskId determines query task id. (Optional)
61
72
  @task_id = rand(RAND_MAX)
@@ -64,33 +75,35 @@ module Aerospike
64
75
  @return_data = true
65
76
  end
66
77
 
67
- def set_aggregate_function(package_name, function_name, function_args=[], return_data=true)
78
+ def set_aggregate_function(package_name, function_name, function_args=[], return_data=true)
68
79
  @package_name = package_name
69
80
  @function_name = function_name
70
81
  @function_args = function_args
71
82
  @return_data = return_data
72
- end
83
+ end
73
84
 
74
- def is_scan?
75
- return (filters.nil? || (filters.empty?))
76
- end
85
+ def is_scan?
86
+ return (filters.nil? || (filters.empty?))
87
+ end
77
88
 
78
- def set_task_id
79
- while @task_id == 0
80
- @task_id = rand(RAND_MAX)
89
+ def set_task_id
90
+ while @task_id == 0
91
+ @task_id = rand(RAND_MAX)
92
+ end
81
93
  end
82
- end
83
94
 
84
- def reset_task_id
85
- @task_id = rand(RAND_MAX)
86
- while @task_id == 0
95
+ def reset_task_id
87
96
  @task_id = rand(RAND_MAX)
97
+ while @task_id == 0
98
+ @task_id = rand(RAND_MAX)
99
+ end
88
100
  end
89
- end
90
101
 
91
- private
92
102
 
93
- RAND_MAX = 2**63
103
+
104
+ private
105
+
106
+ RAND_MAX = 2**63 - 1
94
107
 
95
108
  end # class
96
109
  end
@@ -1,4 +1,4 @@
1
- # Copyright 2014-2020 Aerospike, Inc.
1
+ # Copyright 2014-2023 Aerospike, Inc.
2
2
  #
3
3
  # Portions may be licensed to Aerospike, Inc. under one or more contributor
4
4
  # license agreements.
@@ -33,6 +33,8 @@ module Aerospike
33
33
  @node = node
34
34
  end
35
35
 
36
+
37
+
36
38
  def to_s
37
39
  "key: `#{key}` bins: `#{bins}` generation: `#{generation}`, ttl: `#{ttl}`"
38
40
  end
@@ -41,6 +43,18 @@ module Aerospike
41
43
 
42
44
  CITRUSLEAF_EPOCH = 1262304000
43
45
 
46
+ # Arguments:
47
+ # value: the key to retrieve the value for
48
+ #
49
+ # Returns:
50
+ # the value of the specified key, or `nil` if `@bins` is `nil`
51
+ def get_value(value)
52
+ unless @bins.nil?
53
+ return @bins[value]
54
+ end
55
+ nil
56
+ end
57
+
44
58
  # Converts an absolute expiration time (in seconds from citrusleaf epoch)
45
59
  # to relative time-to-live (TTL) in seconds
46
60
  def expiration_to_ttl(secs_from_epoc)
@@ -1,4 +1,4 @@
1
1
  # encoding: utf-8
2
2
  module Aerospike
3
- VERSION = "2.26.0"
3
+ VERSION = "2.27.0"
4
4
  end
data/lib/aerospike.rb CHANGED
@@ -169,6 +169,7 @@ require "aerospike/query/scan_executor"
169
169
  require "aerospike/query/scan_partition_command"
170
170
  require "aerospike/query/query_executor"
171
171
  require "aerospike/query/query_partition_command"
172
+ require "aerospike/query/server_command"
172
173
 
173
174
  require "aerospike/exp/exp"
174
175
  require "aerospike/exp/exp_map"
metadata CHANGED
@@ -1,15 +1,16 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: aerospike
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.26.0
4
+ version: 2.27.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Khosrow Afroozeh
8
8
  - Jan Hecking
9
- autorequire:
9
+ - Sachin Venkatesha Murthy
10
+ autorequire:
10
11
  bindir: bin
11
12
  cert_chain: []
12
- date: 2022-12-02 00:00:00.000000000 Z
13
+ date: 2023-05-18 00:00:00.000000000 Z
13
14
  dependencies:
14
15
  - !ruby/object:Gem::Dependency
15
16
  name: msgpack
@@ -44,6 +45,7 @@ description: Official Aerospike Client for ruby. Access your Aerospike cluster w
44
45
  email:
45
46
  - khosrow@aerospike.com
46
47
  - jhecking@aerospike.com
48
+ - smurthy@aerospike.com
47
49
  executables: []
48
50
  extensions: []
49
51
  extra_rdoc_files: []
@@ -181,6 +183,7 @@ files:
181
183
  - lib/aerospike/query/scan_command.rb
182
184
  - lib/aerospike/query/scan_executor.rb
183
185
  - lib/aerospike/query/scan_partition_command.rb
186
+ - lib/aerospike/query/server_command.rb
184
187
  - lib/aerospike/query/statement.rb
185
188
  - lib/aerospike/query/stream_command.rb
186
189
  - lib/aerospike/record.rb
@@ -227,8 +230,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
227
230
  - !ruby/object:Gem::Version
228
231
  version: '0'
229
232
  requirements: []
230
- rubygems_version: 3.3.5
231
- signing_key:
233
+ rubygems_version: 3.3.3
234
+ signing_key:
232
235
  specification_version: 4
233
236
  summary: An Aerospike driver for Ruby.
234
237
  test_files: []