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 +4 -4
- data/CHANGELOG.md +13 -0
- data/lib/aerospike/client.rb +54 -2
- data/lib/aerospike/cluster.rb +9 -8
- data/lib/aerospike/command/command.rb +251 -4
- data/lib/aerospike/node.rb +12 -1
- data/lib/aerospike/policy/client_policy.rb +21 -1
- data/lib/aerospike/policy/policy.rb +15 -3
- data/lib/aerospike/policy/priority.rb +5 -1
- data/lib/aerospike/policy/scan_policy.rb +8 -3
- data/lib/aerospike/policy/write_policy.rb +8 -3
- data/lib/aerospike/query/server_command.rb +60 -0
- data/lib/aerospike/query/statement.rb +31 -18
- data/lib/aerospike/record.rb +15 -1
- data/lib/aerospike/utils/pool.rb +1 -1
- data/lib/aerospike/version.rb +1 -1
- data/lib/aerospike.rb +1 -0
- metadata +8 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 646dcb876d7a83fab511f844216980206ee489f5cdb50f6d169a5c1893184861
|
4
|
+
data.tar.gz: f508306bf2eb681e493f1e929cab19427475f6eb7c0976b3c16b86056083b443
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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**
|
data/lib/aerospike/client.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright 2014-
|
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
|
#-------------------------------------------------------
|
data/lib/aerospike/cluster.rb
CHANGED
@@ -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
|
-
|
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-
|
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
|
-
|
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
|
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)
|
data/lib/aerospike/node.rb
CHANGED
@@ -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
|
-
#
|
55
|
-
#
|
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-
|
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
|
-
#
|
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
|
-
#
|
60
|
-
#
|
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-
|
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
|
-
|
28
|
-
|
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-
|
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
|
-
|
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
|
-
|
83
|
+
end
|
73
84
|
|
74
|
-
|
75
|
-
|
76
|
-
|
85
|
+
def is_scan?
|
86
|
+
return (filters.nil? || (filters.empty?))
|
87
|
+
end
|
77
88
|
|
78
|
-
|
79
|
-
|
80
|
-
|
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
|
-
|
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
|
-
|
103
|
+
|
104
|
+
private
|
105
|
+
|
106
|
+
RAND_MAX = 2**63 - 1
|
94
107
|
|
95
108
|
end # class
|
96
109
|
end
|
data/lib/aerospike/record.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright 2014-
|
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)
|
data/lib/aerospike/utils/pool.rb
CHANGED
data/lib/aerospike/version.rb
CHANGED
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.
|
4
|
+
version: 2.28.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Khosrow Afroozeh
|
8
8
|
- Jan Hecking
|
9
|
-
|
9
|
+
- Sachin Venkatesha Murthy
|
10
|
+
autorequire:
|
10
11
|
bindir: bin
|
11
12
|
cert_chain: []
|
12
|
-
date:
|
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.
|
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: []
|