aerospike 2.26.0 → 2.28.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 569388197af73988d3965e15f8b7caf42605896f21183a0e6f7d507690dec816
4
- data.tar.gz: dfe35172403817d176aecfd83747e6155a961b92960a97f8efc713a6b7540d23
3
+ metadata.gz: 646dcb876d7a83fab511f844216980206ee489f5cdb50f6d169a5c1893184861
4
+ data.tar.gz: f508306bf2eb681e493f1e929cab19427475f6eb7c0976b3c16b86056083b443
5
5
  SHA512:
6
- metadata.gz: e4de68155586c168c75a51c71749531becdf066cb22888745f8473237cb775dd9054c6401e44a04b00bee517848859d128141692da3fc7c970df2f202e5e49b9
7
- data.tar.gz: 7c041a196f2bf45a3ff575426b9269ba45c10e16f641c82f5ce11e362ace013d2480c407b8f1e9a663a27bcf78df1988d6af46de2bd22d41c0fce5366fb2a52c
6
+ metadata.gz: 51e3be1cb3b4790695eeae954e989da0df09f62deb43c9bc7995cd6c17e72804f2be1a02cf4bfcf09179a9aaff03c6d87f457bf338226d214614a6d6e3c75719
7
+ data.tar.gz: c36094ad5db6f9758131aa33258ec551a59a9fcfd72c3f106008bdcc2a8de9530d47fae6bd90a6d1459bdf772902d8770ec842c8d3cc41ef4cd1d720dd3bd430
data/CHANGELOG.md CHANGED
@@ -2,6 +2,19 @@
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-1432] Support minimum connections in connection pools
8
+
9
+ - **Updates**
10
+ - [CLIENT-1529] Remove Policy.priority, ScanPolicy.scanPercent and ScanPolicy.failOnClusterChange
11
+
12
+
13
+ ## [2.27.0] 2023-05-18
14
+ - **New Features**
15
+ - [CLIENT-1176] Support write operations in background query
16
+
17
+
5
18
  ## [2.26.0] 2022-12-02
6
19
 
7
20
  - **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
  #-------------------------------------------------------
@@ -23,13 +23,8 @@ require 'aerospike/atomic/atomic'
23
23
 
24
24
  module Aerospike
25
25
  class Cluster
26
- attr_reader :connection_timeout, :connection_queue_size, :user, :password
27
- attr_reader :features, :tls_options
28
- attr_reader :cluster_id, :aliases
29
- attr_reader :cluster_name
30
- attr_reader :client_policy
31
- attr_accessor :rack_aware, :rack_id
32
- attr_accessor :session_token, :session_expiration
26
+ attr_reader :connection_timeout, :connection_queue_size, :user, :password, :features, :tls_options, :cluster_id, :aliases, :cluster_name, :client_policy
27
+ attr_accessor :rack_aware, :rack_id, :session_token, :session_expiration
33
28
 
34
29
  def initialize(policy, hosts)
35
30
  @client_policy = policy
@@ -63,6 +58,10 @@ module Aerospike
63
58
  end
64
59
 
65
60
  initialize_tls_host_names(hosts) if tls_enabled?
61
+
62
+ if policy.min_connections_per_node > policy.max_connections_per_node
63
+ raise Aerospike::Exceptions::Aerospike.new(Aerospike::ResultCode::PARAMETER_ERROR, "Invalid policy configuration: Minimum connections per node cannot be greater than maximum connections per node.")
64
+ end
66
65
  end
67
66
 
68
67
  def connect
@@ -584,7 +583,9 @@ module Aerospike
584
583
  end
585
584
 
586
585
  def create_node(nv)
587
- ::Aerospike::Node.new(self, nv)
586
+ node = ::Aerospike::Node.new(self, nv)
587
+ node.fill_connection_pool_up_to(@client_policy.min_connections_per_node)
588
+ node
588
589
  end
589
590
 
590
591
  def create_connection(host)
@@ -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 @@ 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, :rebalance_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, :connections
26
26
 
27
27
  PARTITIONS = 4096
28
28
  FULL_HEALTH = 100
@@ -69,6 +69,17 @@ module Aerospike
69
69
  racks[ns] == rack_id
70
70
  end
71
71
 
72
+ def fill_connection_pool_up_to(min_connection_size)
73
+ current_number_of_connections = @connections.length
74
+ if min_connection_size > 0
75
+ while current_number_of_connections < min_connection_size
76
+ conn = @connections.create
77
+ @connections.offer(conn)
78
+ current_number_of_connections += 1
79
+ end
80
+ end
81
+ end
82
+
72
83
  # Get a connection to the node. If no cached connection is not available,
73
84
  # a new connection will be created
74
85
  def get_connection(timeout)
@@ -23,7 +23,7 @@ module Aerospike
23
23
  class ClientPolicy
24
24
 
25
25
  attr_accessor :user, :password, :auth_mode
26
- attr_accessor :timeout, :connection_queue_size, :fail_if_not_connected, :tend_interval
26
+ attr_accessor :timeout, :connection_queue_size, :fail_if_not_connected, :tend_interval, :max_connections_per_node, :min_connections_per_node
27
27
  attr_accessor :cluster_name
28
28
  attr_accessor :tls
29
29
  attr_accessor :policies
@@ -74,6 +74,26 @@ module Aerospike
74
74
  # ClientPolicy#rack_aware, Replica#PREFER_RACK and server rack
75
75
  # configuration must also be set to enable this functionality.
76
76
  @rack_id = opt[:rack_id] || 0
77
+
78
+ # Maximum number of synchronous connections allowed per server node. Transactions will go
79
+ # through retry logic and potentially fail with "ResultCode.NO_MORE_CONNECTIONS" if the maximum
80
+ # number of connections would be exceeded.
81
+ # The number of connections used per node depends on concurrent commands in progress
82
+ # plus sub-commands used for parallel multi-node commands (batch, scan, and query).
83
+ # One connection will be used for each command.
84
+ # Default: 100
85
+ @max_connections_per_node = opt[:max_connections_per_node] || 100
86
+
87
+ # MinConnectionsPerNode specifies the minimum number of synchronous connections allowed per server node.
88
+ # Preallocate min connections on client node creation.
89
+ # The client will periodically allocate new connections if count falls below min connections.
90
+ #
91
+ # Server proto-fd-idle-ms may also need to be increased substantially if min connections are defined.
92
+ # The proto-fd-idle-ms default directs the server to close connections that are idle for 60 seconds
93
+ # which can defeat the purpose of keeping connections in reserve for a future burst of activity.
94
+ #
95
+ # Default: 0
96
+ @min_connections_per_node = opt[:min_connections_per_node] || 0
77
97
  end
78
98
 
79
99
  def requires_authentication
@@ -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=
@@ -51,8 +51,10 @@ module Aerospike
51
51
  # Default: false
52
52
  @fail_on_filtered_out = opt[:fail_on_filtered_out] || false
53
53
 
54
- # Priority of request relative to other transactions.
55
- # Currently, only used for scans.
54
+ # [:nodoc:]
55
+ # DEPRECATED
56
+ # The Aerospike server does not support this policy anymore
57
+ # TODO: Remove for next major release
56
58
  @priority = opt[:priority] || Priority::DEFAULT
57
59
 
58
60
  # Set optional predicate expression filters in postfix notation.
@@ -133,6 +135,16 @@ module Aerospike
133
135
  # Duration to sleep between retries if a transaction fails and the
134
136
  # timeout was not exceeded. Enter zero to skip sleep.
135
137
  @sleep_between_retries = opt[:sleep_between_retries] || 0.5
138
+
139
+ # Determines network timeout for each attempt.
140
+ #
141
+ # If socket_timeout is not zero and socket_timeout is reached before an attempt completes,
142
+ # the Timeout above is checked. If Timeout is not exceeded, the transaction
143
+ # is retried. If both socket_timeout and Timeout are non-zero, socket_timeout must be less
144
+ # than or equal to Timeout, otherwise Timeout will also be used for socket_timeout.
145
+ #
146
+ # Default: 30s
147
+ @socket_timeout = opt[:socket_timeout] || 30000
136
148
  end
137
149
  end # class
138
150
  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.
@@ -13,6 +13,10 @@
13
13
  # See the License for the specific language governing permissions and
14
14
  # limitations under the License.
15
15
 
16
+
17
+ #[:nodoc:]
18
+ # DEPRECATED
19
+ # TODO: Remove this module on the next major release
16
20
  module Aerospike
17
21
 
18
22
  module Priority
@@ -48,7 +48,10 @@ module Aerospike
48
48
  # Default is 100.
49
49
  @scan_percent = opt[:scan_percent] || 100
50
50
 
51
- # Issue scan requests in parallel or serially.
51
+ # [:nodoc:]
52
+ # DEPRECATED
53
+ # The Aerospike server does not support this policy anymore
54
+ # TODO: Remove for next major release
52
55
  @concurrent_nodes = opt.fetch(:concurrent_nodes) { true }
53
56
 
54
57
  # Indicates if bin data is retrieved. If false, only record digests (and
@@ -56,8 +59,10 @@ module Aerospike
56
59
  # Default is true.
57
60
  @include_bin_data = opt.fetch(:include_bin_data) { true }
58
61
 
59
- # Terminate scan if cluster in fluctuating state.
60
- # Default is true.
62
+ # [:nodoc:]
63
+ # DEPRECATED
64
+ # The Aerospike server does not support this policy anymore
65
+ # TODO: Remove for next major release
61
66
  @fail_on_cluster_change = opt.fetch(:fail_on_cluster_change) { true }
62
67
 
63
68
  # Determines network timeout for each attempt.
@@ -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)
@@ -18,7 +18,7 @@ module Aerospike
18
18
 
19
19
  class Pool #:nodoc:
20
20
 
21
- attr_accessor :create_proc, :cleanup_proc, :check_proc
21
+ attr_accessor :create_proc, :cleanup_proc, :check_proc, :max_size
22
22
 
23
23
  def initialize(max_size = 256, &block)
24
24
  @create_proc = block
@@ -1,4 +1,4 @@
1
1
  # encoding: utf-8
2
2
  module Aerospike
3
- VERSION = "2.26.0"
3
+ VERSION = "2.28.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.28.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-06-23 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: []