couchbase 3.4.3 → 3.4.5
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/README.md +2 -2
- data/ext/couchbase/CMakeLists.txt +22 -1
- data/ext/couchbase/core/bucket.cxx +183 -152
- data/ext/couchbase/core/bucket.hxx +17 -4
- data/ext/couchbase/core/cluster.hxx +41 -13
- data/ext/couchbase/core/cluster_options.hxx +3 -0
- data/ext/couchbase/core/crud_component.cxx +51 -22
- data/ext/couchbase/core/error_context/key_value.cxx +2 -1
- data/ext/couchbase/core/error_context/key_value.hxx +10 -12
- data/ext/couchbase/core/impl/build_deferred_query_indexes.cxx +115 -50
- data/ext/couchbase/core/impl/cluster.cxx +6 -0
- data/ext/couchbase/core/impl/create_bucket.cxx +158 -0
- data/ext/couchbase/core/impl/create_collection.cxx +83 -0
- data/ext/couchbase/core/impl/create_query_index.cxx +172 -59
- data/ext/couchbase/core/impl/create_scope.cxx +69 -0
- data/ext/couchbase/core/impl/dns_srv_tracker.cxx +2 -1
- data/ext/couchbase/core/impl/drop_bucket.cxx +66 -0
- data/ext/couchbase/core/impl/drop_collection.cxx +76 -0
- data/ext/couchbase/core/impl/drop_query_index.cxx +138 -59
- data/ext/couchbase/core/impl/drop_scope.cxx +68 -0
- data/ext/couchbase/core/impl/flush_bucket.cxx +66 -0
- data/ext/couchbase/core/impl/get_all_buckets.cxx +178 -0
- data/ext/couchbase/core/impl/get_all_query_indexes.cxx +67 -37
- data/ext/couchbase/core/impl/get_all_scopes.cxx +94 -0
- data/ext/couchbase/core/impl/get_bucket.cxx +168 -0
- data/ext/couchbase/core/impl/internal_manager_error_context.cxx +113 -0
- data/ext/couchbase/core/impl/internal_manager_error_context.hxx +60 -0
- data/ext/couchbase/core/impl/key_value_error_category.cxx +2 -4
- data/ext/couchbase/core/impl/key_value_error_context.cxx +98 -0
- data/ext/couchbase/core/impl/lookup_in.cxx +1 -0
- data/ext/couchbase/core/impl/lookup_in_all_replicas.cxx +178 -0
- data/ext/couchbase/core/impl/lookup_in_all_replicas.hxx +80 -0
- data/ext/couchbase/core/impl/lookup_in_any_replica.cxx +169 -0
- data/ext/couchbase/core/impl/lookup_in_any_replica.hxx +75 -0
- data/ext/couchbase/core/impl/lookup_in_replica.cxx +104 -0
- data/ext/couchbase/core/impl/lookup_in_replica.hxx +67 -0
- data/ext/couchbase/core/impl/manager_error_context.cxx +100 -0
- data/ext/couchbase/core/impl/query.cxx +1 -0
- data/ext/couchbase/core/impl/query_error_context.cxx +75 -0
- data/ext/couchbase/core/impl/update_bucket.cxx +133 -0
- data/ext/couchbase/core/impl/update_collection.cxx +83 -0
- data/ext/couchbase/core/impl/watch_query_indexes.cxx +53 -29
- data/ext/couchbase/core/io/dns_client.cxx +111 -40
- data/ext/couchbase/core/io/dns_config.cxx +5 -4
- data/ext/couchbase/core/io/http_session.hxx +24 -1
- data/ext/couchbase/core/io/mcbp_command.hxx +9 -2
- data/ext/couchbase/core/io/mcbp_session.cxx +80 -43
- data/ext/couchbase/core/io/mcbp_session.hxx +4 -3
- data/ext/couchbase/core/logger/custom_rotating_file_sink.cxx +1 -1
- data/ext/couchbase/core/logger/logger.cxx +80 -20
- data/ext/couchbase/core/logger/logger.hxx +31 -0
- data/ext/couchbase/core/management/bucket_settings.hxx +8 -5
- data/ext/couchbase/core/management/bucket_settings_json.hxx +12 -2
- data/ext/couchbase/core/meta/features.hxx +42 -0
- data/ext/couchbase/core/operations/document_lookup_in.cxx +8 -1
- data/ext/couchbase/core/operations/document_lookup_in_all_replicas.hxx +192 -0
- data/ext/couchbase/core/operations/document_lookup_in_any_replica.hxx +188 -0
- data/ext/couchbase/core/operations/document_query.cxx +11 -0
- data/ext/couchbase/core/operations/document_query.hxx +1 -0
- data/ext/couchbase/core/operations/management/CMakeLists.txt +1 -0
- data/ext/couchbase/core/operations/management/bucket_create.cxx +30 -9
- data/ext/couchbase/core/operations/management/bucket_update.cxx +27 -6
- data/ext/couchbase/core/operations/management/collection_create.cxx +5 -1
- data/ext/couchbase/core/operations/management/collection_create.hxx +1 -0
- data/ext/couchbase/core/operations/management/collection_update.cxx +87 -0
- data/ext/couchbase/core/operations/management/collection_update.hxx +54 -0
- data/ext/couchbase/core/operations/management/collections.hxx +1 -0
- data/ext/couchbase/core/operations.hxx +2 -0
- data/ext/couchbase/core/origin.cxx +270 -0
- data/ext/couchbase/core/origin.hxx +2 -0
- data/ext/couchbase/core/protocol/client_response.hxx +1 -0
- data/ext/couchbase/core/protocol/cmd_hello.hxx +1 -0
- data/ext/couchbase/core/protocol/cmd_lookup_in_replica.cxx +107 -0
- data/ext/couchbase/core/protocol/cmd_lookup_in_replica.hxx +137 -0
- data/ext/couchbase/core/protocol/hello_feature.hxx +6 -0
- data/ext/couchbase/core/protocol/hello_feature_fmt.hxx +3 -0
- data/ext/couchbase/core/protocol/status.cxx +2 -2
- data/ext/couchbase/core/range_scan_options.cxx +3 -27
- data/ext/couchbase/core/range_scan_options.hxx +13 -17
- data/ext/couchbase/core/range_scan_orchestrator.cxx +388 -170
- data/ext/couchbase/core/range_scan_orchestrator.hxx +13 -2
- data/ext/couchbase/core/range_scan_orchestrator_options.hxx +5 -3
- data/ext/couchbase/core/scan_options.hxx +0 -19
- data/ext/couchbase/core/scan_result.cxx +19 -5
- data/ext/couchbase/core/scan_result.hxx +5 -2
- data/ext/couchbase/core/timeout_defaults.hxx +3 -4
- data/ext/couchbase/core/topology/capabilities.hxx +4 -0
- data/ext/couchbase/core/topology/capabilities_fmt.hxx +11 -0
- data/ext/couchbase/core/topology/collections_manifest.hxx +2 -0
- data/ext/couchbase/core/topology/collections_manifest_fmt.hxx +1 -1
- data/ext/couchbase/core/topology/collections_manifest_json.hxx +3 -0
- data/ext/couchbase/core/topology/configuration.hxx +20 -0
- data/ext/couchbase/core/topology/configuration_json.hxx +8 -1
- data/ext/couchbase/core/utils/connection_string.cxx +62 -47
- data/ext/couchbase/core/utils/connection_string.hxx +1 -0
- data/ext/couchbase/couchbase/analytics_error_context.hxx +1 -1
- data/ext/couchbase/couchbase/behavior_options.hxx +19 -2
- data/ext/couchbase/couchbase/bucket.hxx +14 -0
- data/ext/couchbase/couchbase/bucket_manager.hxx +135 -0
- data/ext/couchbase/couchbase/build_query_index_options.hxx +0 -30
- data/ext/couchbase/couchbase/cluster.hxx +14 -0
- data/ext/couchbase/couchbase/collection.hxx +111 -0
- data/ext/couchbase/couchbase/collection_manager.hxx +160 -0
- data/ext/couchbase/couchbase/collection_query_index_manager.hxx +7 -48
- data/ext/couchbase/couchbase/create_bucket_options.hxx +41 -0
- data/ext/couchbase/couchbase/create_collection_options.hxx +44 -0
- data/ext/couchbase/couchbase/create_primary_query_index_options.hxx +0 -29
- data/ext/couchbase/couchbase/create_query_index_options.hxx +0 -33
- data/ext/couchbase/couchbase/create_scope_options.hxx +41 -0
- data/ext/couchbase/couchbase/drop_bucket_options.hxx +41 -0
- data/ext/couchbase/couchbase/drop_collection_options.hxx +41 -0
- data/ext/couchbase/couchbase/drop_primary_query_index_options.hxx +0 -30
- data/ext/couchbase/couchbase/drop_query_index_options.hxx +0 -31
- data/ext/couchbase/couchbase/drop_scope_options.hxx +41 -0
- data/ext/couchbase/couchbase/error_codes.hxx +1 -2
- data/ext/couchbase/couchbase/error_context.hxx +10 -2
- data/ext/couchbase/couchbase/flush_bucket_options.hxx +41 -0
- data/ext/couchbase/{core/topology/error_map_fmt.hxx → couchbase/fmt/key_value_error_map_attribute.hxx} +21 -21
- data/ext/couchbase/couchbase/get_all_buckets_options.hxx +44 -0
- data/ext/couchbase/couchbase/get_all_query_indexes_options.hxx +0 -30
- data/ext/couchbase/couchbase/get_all_scopes_options.hxx +44 -0
- data/ext/couchbase/couchbase/get_and_lock_options.hxx +2 -2
- data/ext/couchbase/couchbase/get_and_touch_options.hxx +2 -2
- data/ext/couchbase/couchbase/get_bucket_options.hxx +43 -0
- data/ext/couchbase/couchbase/get_options.hxx +2 -2
- data/ext/couchbase/couchbase/insert_options.hxx +3 -3
- data/ext/couchbase/couchbase/key_value_error_context.hxx +7 -2
- data/ext/couchbase/couchbase/lookup_in_all_replicas_options.hxx +109 -0
- data/ext/couchbase/couchbase/lookup_in_any_replica_options.hxx +101 -0
- data/ext/couchbase/couchbase/lookup_in_options.hxx +2 -2
- data/ext/couchbase/couchbase/lookup_in_replica_result.hxx +74 -0
- data/ext/couchbase/couchbase/lookup_in_result.hxx +26 -0
- data/ext/couchbase/couchbase/management/bucket_settings.hxx +119 -0
- data/ext/couchbase/couchbase/management/collection_spec.hxx +29 -0
- data/ext/couchbase/couchbase/management/scope_spec.hxx +29 -0
- data/ext/couchbase/couchbase/manager_error_context.hxx +29 -53
- data/ext/couchbase/couchbase/mutate_in_options.hxx +2 -2
- data/ext/couchbase/couchbase/query_error_context.hxx +3 -1
- data/ext/couchbase/couchbase/query_index_manager.hxx +16 -83
- data/ext/couchbase/couchbase/query_options.hxx +18 -0
- data/ext/couchbase/couchbase/remove_options.hxx +2 -2
- data/ext/couchbase/couchbase/replace_options.hxx +3 -3
- data/ext/couchbase/couchbase/security_options.hxx +15 -0
- data/ext/couchbase/couchbase/subdocument_error_context.hxx +4 -2
- data/ext/couchbase/couchbase/touch_options.hxx +2 -2
- data/ext/couchbase/couchbase/unlock_options.hxx +2 -2
- data/ext/couchbase/couchbase/update_bucket_options.hxx +41 -0
- data/ext/couchbase/couchbase/update_collection_options.hxx +44 -0
- data/ext/couchbase/couchbase/upsert_options.hxx +3 -3
- data/ext/couchbase/couchbase/watch_query_indexes_options.hxx +0 -31
- data/ext/couchbase/test/CMakeLists.txt +1 -0
- data/ext/couchbase/test/test_integration_collections.cxx +6 -0
- data/ext/couchbase/test/test_integration_crud.cxx +5 -0
- data/ext/couchbase/test/test_integration_examples.cxx +137 -1
- data/ext/couchbase/test/test_integration_management.cxx +1009 -309
- data/ext/couchbase/test/test_integration_query.cxx +19 -7
- data/ext/couchbase/test/test_integration_range_scan.cxx +351 -112
- data/ext/couchbase/test/test_integration_search.cxx +10 -1
- data/ext/couchbase/test/test_integration_subdoc.cxx +721 -7
- data/ext/couchbase/test/test_transaction_public_async_api.cxx +13 -12
- data/ext/couchbase/test/test_transaction_public_blocking_api.cxx +27 -21
- data/ext/couchbase/test/test_unit_connection_string.cxx +29 -0
- data/ext/couchbase/test/test_unit_query.cxx +75 -0
- data/ext/couchbase.cxx +735 -60
- data/ext/revisions.rb +3 -3
- data/lib/couchbase/cluster.rb +1 -1
- data/lib/couchbase/collection.rb +108 -0
- data/lib/couchbase/collection_options.rb +100 -1
- data/lib/couchbase/errors.rb +5 -0
- data/lib/couchbase/key_value_scan.rb +125 -0
- data/lib/couchbase/management/bucket_manager.rb +22 -15
- data/lib/couchbase/management/collection_manager.rb +158 -9
- data/lib/couchbase/options.rb +151 -0
- data/lib/couchbase/scope.rb +1 -1
- data/lib/couchbase/utils/time.rb +14 -1
- data/lib/couchbase/version.rb +1 -1
- metadata +59 -8
- data/ext/couchbase/core/impl/collection_query_index_manager.cxx +0 -93
data/ext/couchbase.cxx
CHANGED
|
@@ -33,9 +33,12 @@
|
|
|
33
33
|
#include <core/platform/terminate_handler.h>
|
|
34
34
|
|
|
35
35
|
#include <core/cluster.hxx>
|
|
36
|
+
|
|
37
|
+
#include <core/agent_group.hxx>
|
|
36
38
|
#include <core/design_document_namespace_fmt.hxx>
|
|
37
39
|
#include <core/logger/configuration.hxx>
|
|
38
40
|
#include <core/operations.hxx>
|
|
41
|
+
|
|
39
42
|
#include <core/operations/management/analytics.hxx>
|
|
40
43
|
#include <core/operations/management/bucket.hxx>
|
|
41
44
|
#include <core/operations/management/cluster_developer_preview_enable.hxx>
|
|
@@ -45,6 +48,12 @@
|
|
|
45
48
|
#include <core/operations/management/user.hxx>
|
|
46
49
|
#include <core/operations/management/view.hxx>
|
|
47
50
|
|
|
51
|
+
#include <core/impl/subdoc/path_flags.hxx>
|
|
52
|
+
|
|
53
|
+
#include <core/range_scan_options.hxx>
|
|
54
|
+
#include <core/range_scan_orchestrator.hxx>
|
|
55
|
+
#include <core/range_scan_orchestrator_options.hxx>
|
|
56
|
+
|
|
48
57
|
#include <core/io/dns_client.hxx>
|
|
49
58
|
#include <core/io/dns_config.hxx>
|
|
50
59
|
#include <core/utils/connection_string.hxx>
|
|
@@ -435,7 +444,7 @@ cb_backend_close(cb_backend_data* backend)
|
|
|
435
444
|
static void
|
|
436
445
|
cb_Backend_mark(void* /* ptr */)
|
|
437
446
|
{
|
|
438
|
-
/* no
|
|
447
|
+
/* no embedded ruby objects -- no mark */
|
|
439
448
|
}
|
|
440
449
|
|
|
441
450
|
static void
|
|
@@ -495,6 +504,8 @@ cb_backend_to_cluster(VALUE self)
|
|
|
495
504
|
return backend->cluster;
|
|
496
505
|
}
|
|
497
506
|
|
|
507
|
+
static VALUE eCouchbaseError;
|
|
508
|
+
|
|
498
509
|
static VALUE eAmbiguousTimeout;
|
|
499
510
|
static VALUE eAuthenticationFailure;
|
|
500
511
|
static VALUE eBucketExists;
|
|
@@ -534,6 +545,7 @@ static VALUE eInvalidArgument;
|
|
|
534
545
|
static VALUE eJobQueueFull;
|
|
535
546
|
static VALUE eLinkNotFound;
|
|
536
547
|
static VALUE eLinkExists;
|
|
548
|
+
static VALUE eMutationTokenOutdated;
|
|
537
549
|
static VALUE eNumberTooBig;
|
|
538
550
|
static VALUE eParsingFailure;
|
|
539
551
|
static VALUE ePathExists;
|
|
@@ -586,7 +598,7 @@ static void
|
|
|
586
598
|
init_exceptions(VALUE mCouchbase)
|
|
587
599
|
{
|
|
588
600
|
VALUE mError = rb_define_module_under(mCouchbase, "Error");
|
|
589
|
-
|
|
601
|
+
eCouchbaseError = rb_define_class_under(mError, "CouchbaseError", rb_eStandardError);
|
|
590
602
|
|
|
591
603
|
VALUE eTimeout = rb_define_class_under(mError, "Timeout", eCouchbaseError);
|
|
592
604
|
|
|
@@ -629,6 +641,7 @@ init_exceptions(VALUE mCouchbase)
|
|
|
629
641
|
eJobQueueFull = rb_define_class_under(mError, "JobQueueFull", eCouchbaseError);
|
|
630
642
|
eLinkNotFound = rb_define_class_under(mError, "LinkNotFound", eCouchbaseError);
|
|
631
643
|
eLinkExists = rb_define_class_under(mError, "LinkExists", eCouchbaseError);
|
|
644
|
+
eMutationTokenOutdated = rb_define_class_under(mError, "MutationTokenOutdated", eCouchbaseError);
|
|
632
645
|
eNumberTooBig = rb_define_class_under(mError, "NumberTooBig", eCouchbaseError);
|
|
633
646
|
eParsingFailure = rb_define_class_under(mError, "ParsingFailure", eCouchbaseError);
|
|
634
647
|
ePathExists = rb_define_class_under(mError, "PathExists", eCouchbaseError);
|
|
@@ -784,6 +797,9 @@ cb_map_error_code(std::error_code ec, const std::string& message, bool include_e
|
|
|
784
797
|
case couchbase::errc::key_value::durable_write_re_commit_in_progress:
|
|
785
798
|
return rb_exc_new_cstr(eDurableWriteReCommitInProgress, what.c_str());
|
|
786
799
|
|
|
800
|
+
case couchbase::errc::key_value::mutation_token_outdated:
|
|
801
|
+
return rb_exc_new_cstr(eMutationTokenOutdated, what.c_str());
|
|
802
|
+
|
|
787
803
|
case couchbase::errc::key_value::path_not_found:
|
|
788
804
|
return rb_exc_new_cstr(ePathNotFound, what.c_str());
|
|
789
805
|
|
|
@@ -834,6 +850,10 @@ cb_map_error_code(std::error_code ec, const std::string& message, bool include_e
|
|
|
834
850
|
|
|
835
851
|
case couchbase::errc::key_value::cannot_revive_living_document:
|
|
836
852
|
return rb_exc_new_cstr(eCannotReviveLivingDocument, what.c_str());
|
|
853
|
+
|
|
854
|
+
case couchbase::errc::key_value::range_scan_completed:
|
|
855
|
+
// Should not be exposed to the Ruby SDK, map it to a BackendError
|
|
856
|
+
return rb_exc_new_cstr(eBackendError, what.c_str());
|
|
837
857
|
}
|
|
838
858
|
} else if (ec.category() == couchbase::core::impl::query_category()) {
|
|
839
859
|
switch (static_cast<couchbase::errc::query>(ec.value())) {
|
|
@@ -993,16 +1013,14 @@ cb_map_error_code(const couchbase::key_value_error_context& ctx, const std::stri
|
|
|
993
1013
|
rb_hash_aset(enhanced_error_info, rb_id2sym(rb_intern("context")), cb_str_new(ctx.extended_error_info()->context()));
|
|
994
1014
|
rb_hash_aset(error_context, rb_id2sym(rb_intern("extended_error_info")), enhanced_error_info);
|
|
995
1015
|
}
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
rb_ary_push(retry_reasons, rb_id2sym(rb_intern(reason_str.c_str())));
|
|
1003
|
-
}
|
|
1004
|
-
rb_hash_aset(error_context, rb_id2sym(rb_intern("retry_reasons")), retry_reasons);
|
|
1016
|
+
rb_hash_aset(error_context, rb_id2sym(rb_intern("retry_attempts")), INT2FIX(ctx.retry_attempts()));
|
|
1017
|
+
if (!ctx.retry_reasons().empty()) {
|
|
1018
|
+
VALUE retry_reasons = rb_ary_new_capa(static_cast<long>(ctx.retry_reasons().size()));
|
|
1019
|
+
for (const auto& reason : ctx.retry_reasons()) {
|
|
1020
|
+
auto reason_str = fmt::format("{}", reason);
|
|
1021
|
+
rb_ary_push(retry_reasons, rb_id2sym(rb_intern(reason_str.c_str())));
|
|
1005
1022
|
}
|
|
1023
|
+
rb_hash_aset(error_context, rb_id2sym(rb_intern("retry_reasons")), retry_reasons);
|
|
1006
1024
|
}
|
|
1007
1025
|
if (ctx.last_dispatched_to()) {
|
|
1008
1026
|
rb_hash_aset(error_context, rb_id2sym(rb_intern("last_dispatched_to")), cb_str_new(ctx.last_dispatched_to().value()));
|
|
@@ -3409,7 +3427,7 @@ cb_Backend_document_decrement(VALUE self, VALUE bucket, VALUE scope, VALUE colle
|
|
|
3409
3427
|
static VALUE
|
|
3410
3428
|
cb_Backend_document_lookup_in(VALUE self, VALUE bucket, VALUE scope, VALUE collection, VALUE id, VALUE specs, VALUE options)
|
|
3411
3429
|
{
|
|
3412
|
-
const auto&
|
|
3430
|
+
const auto& cluster = cb_backend_to_cluster(self);
|
|
3413
3431
|
|
|
3414
3432
|
Check_Type(bucket, T_STRING);
|
|
3415
3433
|
Check_Type(scope, T_STRING);
|
|
@@ -3425,10 +3443,6 @@ cb_Backend_document_lookup_in(VALUE self, VALUE bucket, VALUE scope, VALUE colle
|
|
|
3425
3443
|
}
|
|
3426
3444
|
|
|
3427
3445
|
try {
|
|
3428
|
-
couchbase::lookup_in_options opts;
|
|
3429
|
-
couchbase::ruby::set_timeout(opts, options);
|
|
3430
|
-
couchbase::ruby::set_access_deleted(opts, options);
|
|
3431
|
-
|
|
3432
3446
|
couchbase::core::document_id doc_id{
|
|
3433
3447
|
cb_string_new(bucket),
|
|
3434
3448
|
cb_string_new(scope),
|
|
@@ -3436,12 +3450,15 @@ cb_Backend_document_lookup_in(VALUE self, VALUE bucket, VALUE scope, VALUE colle
|
|
|
3436
3450
|
cb_string_new(id),
|
|
3437
3451
|
};
|
|
3438
3452
|
|
|
3453
|
+
couchbase::core::operations::lookup_in_request req{ doc_id };
|
|
3454
|
+
cb_extract_timeout(req, options);
|
|
3455
|
+
cb_extract_option_bool(req.access_deleted, options, "access_deleted");
|
|
3456
|
+
|
|
3439
3457
|
static VALUE xattr_property = rb_id2sym(rb_intern("xattr"));
|
|
3440
3458
|
static VALUE path_property = rb_id2sym(rb_intern("path"));
|
|
3441
3459
|
static VALUE opcode_property = rb_id2sym(rb_intern("opcode"));
|
|
3442
3460
|
|
|
3443
3461
|
auto entries_size = static_cast<std::size_t>(RARRAY_LEN(specs));
|
|
3444
|
-
couchbase::lookup_in_specs cxx_specs;
|
|
3445
3462
|
for (std::size_t i = 0; i < entries_size; ++i) {
|
|
3446
3463
|
VALUE entry = rb_ary_entry(specs, static_cast<long>(i));
|
|
3447
3464
|
cb_check_type(entry, T_HASH);
|
|
@@ -3450,29 +3467,138 @@ cb_Backend_document_lookup_in(VALUE self, VALUE bucket, VALUE scope, VALUE colle
|
|
|
3450
3467
|
bool xattr = RTEST(rb_hash_aref(entry, xattr_property));
|
|
3451
3468
|
VALUE path = rb_hash_aref(entry, path_property);
|
|
3452
3469
|
cb_check_type(path, T_STRING);
|
|
3470
|
+
auto opcode = couchbase::core::impl::subdoc::opcode{};
|
|
3453
3471
|
if (ID operation_id = rb_sym2id(operation); operation_id == rb_intern("get_doc")) {
|
|
3454
|
-
|
|
3472
|
+
opcode = couchbase::core::impl::subdoc::opcode::get_doc;
|
|
3455
3473
|
} else if (operation_id == rb_intern("get")) {
|
|
3456
|
-
|
|
3474
|
+
opcode = couchbase::core::impl::subdoc::opcode::get;
|
|
3457
3475
|
} else if (operation_id == rb_intern("exists")) {
|
|
3458
|
-
|
|
3476
|
+
opcode = couchbase::core::impl::subdoc::opcode::exists;
|
|
3459
3477
|
} else if (operation_id == rb_intern("count")) {
|
|
3460
|
-
|
|
3478
|
+
opcode = couchbase::core::impl::subdoc::opcode::get_count;
|
|
3461
3479
|
} else {
|
|
3462
3480
|
throw ruby_exception(eInvalidArgument, rb_sprintf("unsupported operation for subdocument lookup: %+" PRIsVALUE, operation));
|
|
3463
3481
|
}
|
|
3464
3482
|
cb_check_type(path, T_STRING);
|
|
3483
|
+
|
|
3484
|
+
req.specs.emplace_back(couchbase::core::impl::subdoc::command{
|
|
3485
|
+
opcode, cb_string_new(path), {}, couchbase::core::impl::subdoc::build_lookup_in_path_flags(xattr) });
|
|
3465
3486
|
}
|
|
3466
3487
|
|
|
3467
|
-
auto
|
|
3468
|
-
|
|
3469
|
-
|
|
3470
|
-
|
|
3471
|
-
|
|
3488
|
+
auto barrier = std::make_shared<std::promise<couchbase::core::operations::lookup_in_response>>();
|
|
3489
|
+
auto f = barrier->get_future();
|
|
3490
|
+
cluster->execute(req, [barrier](couchbase::core::operations::lookup_in_response&& resp) { barrier->set_value(std::move(resp)); });
|
|
3491
|
+
auto resp = cb_wait_for_future(f);
|
|
3492
|
+
if (resp.ctx.ec()) {
|
|
3493
|
+
cb_throw_error_code(resp.ctx, "unable to perform lookup_in operation");
|
|
3494
|
+
}
|
|
3472
3495
|
|
|
3473
|
-
|
|
3474
|
-
|
|
3475
|
-
|
|
3496
|
+
static VALUE deleted_property = rb_id2sym(rb_intern("deleted"));
|
|
3497
|
+
static VALUE fields_property = rb_id2sym(rb_intern("fields"));
|
|
3498
|
+
static VALUE index_property = rb_id2sym(rb_intern("index"));
|
|
3499
|
+
static VALUE exists_property = rb_id2sym(rb_intern("exists"));
|
|
3500
|
+
static VALUE cas_property = rb_id2sym(rb_intern("cas"));
|
|
3501
|
+
static VALUE value_property = rb_id2sym(rb_intern("value"));
|
|
3502
|
+
static VALUE error_property = rb_id2sym(rb_intern("error"));
|
|
3503
|
+
|
|
3504
|
+
VALUE res = rb_hash_new();
|
|
3505
|
+
rb_hash_aset(res, cas_property, cb_cas_to_num(resp.cas));
|
|
3506
|
+
VALUE fields = rb_ary_new_capa(static_cast<long>(entries_size));
|
|
3507
|
+
rb_hash_aset(res, fields_property, fields);
|
|
3508
|
+
rb_hash_aset(res, deleted_property, resp.deleted ? Qtrue : Qfalse);
|
|
3509
|
+
for (std::size_t i = 0; i < entries_size; ++i) {
|
|
3510
|
+
auto resp_entry = resp.fields.at(i);
|
|
3511
|
+
VALUE entry = rb_hash_new();
|
|
3512
|
+
rb_hash_aset(entry, index_property, ULL2NUM(resp_entry.original_index));
|
|
3513
|
+
rb_hash_aset(entry, exists_property, resp_entry.exists ? Qtrue : Qfalse);
|
|
3514
|
+
rb_hash_aset(entry, path_property, cb_str_new(resp_entry.path));
|
|
3515
|
+
if (!resp_entry.value.empty()) {
|
|
3516
|
+
rb_hash_aset(entry, value_property, cb_str_new(resp_entry.value));
|
|
3517
|
+
}
|
|
3518
|
+
if (resp_entry.ec) {
|
|
3519
|
+
rb_hash_aset(entry,
|
|
3520
|
+
error_property,
|
|
3521
|
+
cb_map_error_code(resp_entry.ec,
|
|
3522
|
+
fmt::format("error getting result for spec at index {}, path \"{}\"", i, resp_entry.path)));
|
|
3523
|
+
}
|
|
3524
|
+
rb_ary_store(fields, static_cast<long>(i), entry);
|
|
3525
|
+
}
|
|
3526
|
+
return res;
|
|
3527
|
+
} catch (const std::system_error& se) {
|
|
3528
|
+
rb_exc_raise(cb_map_error_code(se.code(), fmt::format("failed to perform {}: {}", __func__, se.what()), false));
|
|
3529
|
+
} catch (const ruby_exception& e) {
|
|
3530
|
+
rb_exc_raise(e.exception_object());
|
|
3531
|
+
}
|
|
3532
|
+
return Qnil;
|
|
3533
|
+
}
|
|
3534
|
+
|
|
3535
|
+
static VALUE
|
|
3536
|
+
cb_Backend_document_lookup_in_any_replica(VALUE self, VALUE bucket, VALUE scope, VALUE collection, VALUE id, VALUE specs, VALUE options)
|
|
3537
|
+
{
|
|
3538
|
+
const auto& cluster = cb_backend_to_cluster(self);
|
|
3539
|
+
|
|
3540
|
+
Check_Type(bucket, T_STRING);
|
|
3541
|
+
Check_Type(scope, T_STRING);
|
|
3542
|
+
Check_Type(collection, T_STRING);
|
|
3543
|
+
Check_Type(id, T_STRING);
|
|
3544
|
+
Check_Type(specs, T_ARRAY);
|
|
3545
|
+
if (RARRAY_LEN(specs) <= 0) {
|
|
3546
|
+
rb_raise(rb_eArgError, "Array with specs cannot be empty");
|
|
3547
|
+
return Qnil;
|
|
3548
|
+
}
|
|
3549
|
+
if (!NIL_P(options)) {
|
|
3550
|
+
Check_Type(options, T_HASH);
|
|
3551
|
+
}
|
|
3552
|
+
|
|
3553
|
+
try {
|
|
3554
|
+
couchbase::core::document_id doc_id{
|
|
3555
|
+
cb_string_new(bucket),
|
|
3556
|
+
cb_string_new(scope),
|
|
3557
|
+
cb_string_new(collection),
|
|
3558
|
+
cb_string_new(id),
|
|
3559
|
+
};
|
|
3560
|
+
|
|
3561
|
+
couchbase::core::operations::lookup_in_any_replica_request req{ doc_id };
|
|
3562
|
+
cb_extract_timeout(req, options);
|
|
3563
|
+
|
|
3564
|
+
static VALUE xattr_property = rb_id2sym(rb_intern("xattr"));
|
|
3565
|
+
static VALUE path_property = rb_id2sym(rb_intern("path"));
|
|
3566
|
+
static VALUE opcode_property = rb_id2sym(rb_intern("opcode"));
|
|
3567
|
+
|
|
3568
|
+
auto entries_size = static_cast<std::size_t>(RARRAY_LEN(specs));
|
|
3569
|
+
for (std::size_t i = 0; i < entries_size; ++i) {
|
|
3570
|
+
VALUE entry = rb_ary_entry(specs, static_cast<long>(i));
|
|
3571
|
+
cb_check_type(entry, T_HASH);
|
|
3572
|
+
VALUE operation = rb_hash_aref(entry, opcode_property);
|
|
3573
|
+
cb_check_type(operation, T_SYMBOL);
|
|
3574
|
+
bool xattr = RTEST(rb_hash_aref(entry, xattr_property));
|
|
3575
|
+
VALUE path = rb_hash_aref(entry, path_property);
|
|
3576
|
+
cb_check_type(path, T_STRING);
|
|
3577
|
+
auto opcode = couchbase::core::impl::subdoc::opcode{};
|
|
3578
|
+
if (ID operation_id = rb_sym2id(operation); operation_id == rb_intern("get_doc")) {
|
|
3579
|
+
opcode = couchbase::core::impl::subdoc::opcode::get_doc;
|
|
3580
|
+
} else if (operation_id == rb_intern("get")) {
|
|
3581
|
+
opcode = couchbase::core::impl::subdoc::opcode::get;
|
|
3582
|
+
} else if (operation_id == rb_intern("exists")) {
|
|
3583
|
+
opcode = couchbase::core::impl::subdoc::opcode::exists;
|
|
3584
|
+
} else if (operation_id == rb_intern("count")) {
|
|
3585
|
+
opcode = couchbase::core::impl::subdoc::opcode::get_count;
|
|
3586
|
+
} else {
|
|
3587
|
+
throw ruby_exception(eInvalidArgument, rb_sprintf("unsupported operation for subdocument lookup: %+" PRIsVALUE, operation));
|
|
3588
|
+
}
|
|
3589
|
+
cb_check_type(path, T_STRING);
|
|
3590
|
+
|
|
3591
|
+
req.specs.emplace_back(couchbase::core::impl::subdoc::command{
|
|
3592
|
+
opcode, cb_string_new(path), {}, couchbase::core::impl::subdoc::build_lookup_in_path_flags(xattr) });
|
|
3593
|
+
}
|
|
3594
|
+
|
|
3595
|
+
auto barrier = std::make_shared<std::promise<couchbase::core::operations::lookup_in_any_replica_response>>();
|
|
3596
|
+
auto f = barrier->get_future();
|
|
3597
|
+
cluster->execute(
|
|
3598
|
+
req, [barrier](couchbase::core::operations::lookup_in_any_replica_response&& resp) { barrier->set_value(std::move(resp)); });
|
|
3599
|
+
auto resp = cb_wait_for_future(f);
|
|
3600
|
+
if (resp.ctx.ec()) {
|
|
3601
|
+
cb_throw_error_code(resp.ctx, "unable to perform lookup_in_any_replica operation");
|
|
3476
3602
|
}
|
|
3477
3603
|
|
|
3478
3604
|
static VALUE deleted_property = rb_id2sym(rb_intern("deleted"));
|
|
@@ -3481,23 +3607,153 @@ cb_Backend_document_lookup_in(VALUE self, VALUE bucket, VALUE scope, VALUE colle
|
|
|
3481
3607
|
static VALUE exists_property = rb_id2sym(rb_intern("exists"));
|
|
3482
3608
|
static VALUE cas_property = rb_id2sym(rb_intern("cas"));
|
|
3483
3609
|
static VALUE value_property = rb_id2sym(rb_intern("value"));
|
|
3610
|
+
static VALUE error_property = rb_id2sym(rb_intern("error"));
|
|
3611
|
+
static VALUE is_replica_property = rb_id2sym(rb_intern("is_replica"));
|
|
3484
3612
|
|
|
3485
3613
|
VALUE res = rb_hash_new();
|
|
3486
|
-
rb_hash_aset(res, cas_property, cb_cas_to_num(resp.cas
|
|
3614
|
+
rb_hash_aset(res, cas_property, cb_cas_to_num(resp.cas));
|
|
3487
3615
|
VALUE fields = rb_ary_new_capa(static_cast<long>(entries_size));
|
|
3488
3616
|
rb_hash_aset(res, fields_property, fields);
|
|
3489
|
-
rb_hash_aset(res, deleted_property, resp.
|
|
3617
|
+
rb_hash_aset(res, deleted_property, resp.deleted ? Qtrue : Qfalse);
|
|
3618
|
+
rb_hash_aset(res, is_replica_property, resp.is_replica ? Qtrue : Qfalse);
|
|
3619
|
+
|
|
3490
3620
|
for (std::size_t i = 0; i < entries_size; ++i) {
|
|
3621
|
+
auto resp_entry = resp.fields.at(i);
|
|
3491
3622
|
VALUE entry = rb_hash_new();
|
|
3492
|
-
rb_hash_aset(entry, index_property, ULL2NUM(
|
|
3493
|
-
rb_hash_aset(entry, exists_property,
|
|
3494
|
-
rb_hash_aset(entry, path_property,
|
|
3495
|
-
if (
|
|
3496
|
-
|
|
3497
|
-
|
|
3623
|
+
rb_hash_aset(entry, index_property, ULL2NUM(resp_entry.original_index));
|
|
3624
|
+
rb_hash_aset(entry, exists_property, resp_entry.exists ? Qtrue : Qfalse);
|
|
3625
|
+
rb_hash_aset(entry, path_property, cb_str_new(resp_entry.path));
|
|
3626
|
+
if (!resp_entry.value.empty()) {
|
|
3627
|
+
rb_hash_aset(entry, value_property, cb_str_new(resp_entry.value));
|
|
3628
|
+
}
|
|
3629
|
+
if (resp_entry.ec) {
|
|
3630
|
+
rb_hash_aset(entry,
|
|
3631
|
+
error_property,
|
|
3632
|
+
cb_map_error_code(resp_entry.ec,
|
|
3633
|
+
fmt::format("error getting result for spec at index {}, path \"{}\"", i, resp_entry.path)));
|
|
3498
3634
|
}
|
|
3499
3635
|
rb_ary_store(fields, static_cast<long>(i), entry);
|
|
3500
3636
|
}
|
|
3637
|
+
|
|
3638
|
+
return res;
|
|
3639
|
+
} catch (const std::system_error& se) {
|
|
3640
|
+
rb_exc_raise(cb_map_error_code(se.code(), fmt::format("failed to perform {}: {}", __func__, se.what()), false));
|
|
3641
|
+
} catch (const ruby_exception& e) {
|
|
3642
|
+
rb_exc_raise(e.exception_object());
|
|
3643
|
+
}
|
|
3644
|
+
return Qnil;
|
|
3645
|
+
}
|
|
3646
|
+
|
|
3647
|
+
static VALUE
|
|
3648
|
+
cb_Backend_document_lookup_in_all_replicas(VALUE self, VALUE bucket, VALUE scope, VALUE collection, VALUE id, VALUE specs, VALUE options)
|
|
3649
|
+
{
|
|
3650
|
+
const auto& cluster = cb_backend_to_cluster(self);
|
|
3651
|
+
|
|
3652
|
+
Check_Type(bucket, T_STRING);
|
|
3653
|
+
Check_Type(scope, T_STRING);
|
|
3654
|
+
Check_Type(collection, T_STRING);
|
|
3655
|
+
Check_Type(id, T_STRING);
|
|
3656
|
+
Check_Type(specs, T_ARRAY);
|
|
3657
|
+
if (RARRAY_LEN(specs) <= 0) {
|
|
3658
|
+
rb_raise(rb_eArgError, "Array with specs cannot be empty");
|
|
3659
|
+
return Qnil;
|
|
3660
|
+
}
|
|
3661
|
+
if (!NIL_P(options)) {
|
|
3662
|
+
Check_Type(options, T_HASH);
|
|
3663
|
+
}
|
|
3664
|
+
|
|
3665
|
+
try {
|
|
3666
|
+
couchbase::core::document_id doc_id{
|
|
3667
|
+
cb_string_new(bucket),
|
|
3668
|
+
cb_string_new(scope),
|
|
3669
|
+
cb_string_new(collection),
|
|
3670
|
+
cb_string_new(id),
|
|
3671
|
+
};
|
|
3672
|
+
|
|
3673
|
+
couchbase::core::operations::lookup_in_all_replicas_request req{ doc_id };
|
|
3674
|
+
cb_extract_timeout(req, options);
|
|
3675
|
+
|
|
3676
|
+
static VALUE xattr_property = rb_id2sym(rb_intern("xattr"));
|
|
3677
|
+
static VALUE path_property = rb_id2sym(rb_intern("path"));
|
|
3678
|
+
static VALUE opcode_property = rb_id2sym(rb_intern("opcode"));
|
|
3679
|
+
|
|
3680
|
+
auto entries_size = static_cast<std::size_t>(RARRAY_LEN(specs));
|
|
3681
|
+
for (std::size_t i = 0; i < entries_size; ++i) {
|
|
3682
|
+
VALUE entry = rb_ary_entry(specs, static_cast<long>(i));
|
|
3683
|
+
cb_check_type(entry, T_HASH);
|
|
3684
|
+
VALUE operation = rb_hash_aref(entry, opcode_property);
|
|
3685
|
+
cb_check_type(operation, T_SYMBOL);
|
|
3686
|
+
bool xattr = RTEST(rb_hash_aref(entry, xattr_property));
|
|
3687
|
+
VALUE path = rb_hash_aref(entry, path_property);
|
|
3688
|
+
cb_check_type(path, T_STRING);
|
|
3689
|
+
auto opcode = couchbase::core::impl::subdoc::opcode{};
|
|
3690
|
+
if (ID operation_id = rb_sym2id(operation); operation_id == rb_intern("get_doc")) {
|
|
3691
|
+
opcode = couchbase::core::impl::subdoc::opcode::get_doc;
|
|
3692
|
+
} else if (operation_id == rb_intern("get")) {
|
|
3693
|
+
opcode = couchbase::core::impl::subdoc::opcode::get;
|
|
3694
|
+
} else if (operation_id == rb_intern("exists")) {
|
|
3695
|
+
opcode = couchbase::core::impl::subdoc::opcode::exists;
|
|
3696
|
+
} else if (operation_id == rb_intern("count")) {
|
|
3697
|
+
opcode = couchbase::core::impl::subdoc::opcode::get_count;
|
|
3698
|
+
} else {
|
|
3699
|
+
throw ruby_exception(eInvalidArgument, rb_sprintf("unsupported operation for subdocument lookup: %+" PRIsVALUE, operation));
|
|
3700
|
+
}
|
|
3701
|
+
cb_check_type(path, T_STRING);
|
|
3702
|
+
|
|
3703
|
+
req.specs.emplace_back(couchbase::core::impl::subdoc::command{
|
|
3704
|
+
opcode, cb_string_new(path), {}, couchbase::core::impl::subdoc::build_lookup_in_path_flags(xattr) });
|
|
3705
|
+
}
|
|
3706
|
+
|
|
3707
|
+
auto barrier = std::make_shared<std::promise<couchbase::core::operations::lookup_in_all_replicas_response>>();
|
|
3708
|
+
auto f = barrier->get_future();
|
|
3709
|
+
cluster->execute(
|
|
3710
|
+
req, [barrier](couchbase::core::operations::lookup_in_all_replicas_response&& resp) { barrier->set_value(std::move(resp)); });
|
|
3711
|
+
auto resp = cb_wait_for_future(f);
|
|
3712
|
+
if (resp.ctx.ec()) {
|
|
3713
|
+
cb_throw_error_code(resp.ctx, "unable to perform lookup_in_all_replicas operation");
|
|
3714
|
+
}
|
|
3715
|
+
|
|
3716
|
+
static VALUE deleted_property = rb_id2sym(rb_intern("deleted"));
|
|
3717
|
+
static VALUE fields_property = rb_id2sym(rb_intern("fields"));
|
|
3718
|
+
static VALUE index_property = rb_id2sym(rb_intern("index"));
|
|
3719
|
+
static VALUE exists_property = rb_id2sym(rb_intern("exists"));
|
|
3720
|
+
static VALUE cas_property = rb_id2sym(rb_intern("cas"));
|
|
3721
|
+
static VALUE value_property = rb_id2sym(rb_intern("value"));
|
|
3722
|
+
static VALUE error_property = rb_id2sym(rb_intern("error"));
|
|
3723
|
+
static VALUE is_replica_property = rb_id2sym(rb_intern("is_replica"));
|
|
3724
|
+
|
|
3725
|
+
auto lookup_in_entries_size = resp.entries.size();
|
|
3726
|
+
VALUE res = rb_ary_new_capa(static_cast<long>(lookup_in_entries_size));
|
|
3727
|
+
for (std::size_t j = 0; j < lookup_in_entries_size; ++j) {
|
|
3728
|
+
auto lookup_in_entry = resp.entries.at(j);
|
|
3729
|
+
VALUE lookup_in_entry_res = rb_hash_new();
|
|
3730
|
+
rb_hash_aset(lookup_in_entry_res, cas_property, cb_cas_to_num(lookup_in_entry.cas));
|
|
3731
|
+
VALUE fields = rb_ary_new_capa(static_cast<long>(entries_size));
|
|
3732
|
+
rb_hash_aset(lookup_in_entry_res, fields_property, fields);
|
|
3733
|
+
rb_hash_aset(lookup_in_entry_res, deleted_property, lookup_in_entry.deleted ? Qtrue : Qfalse);
|
|
3734
|
+
rb_hash_aset(lookup_in_entry_res, is_replica_property, lookup_in_entry.is_replica ? Qtrue : Qfalse);
|
|
3735
|
+
|
|
3736
|
+
for (std::size_t i = 0; i < entries_size; ++i) {
|
|
3737
|
+
auto field_entry = lookup_in_entry.fields.at(i);
|
|
3738
|
+
VALUE entry = rb_hash_new();
|
|
3739
|
+
rb_hash_aset(entry, index_property, ULL2NUM(field_entry.original_index));
|
|
3740
|
+
rb_hash_aset(entry, exists_property, field_entry.exists ? Qtrue : Qfalse);
|
|
3741
|
+
rb_hash_aset(entry, path_property, cb_str_new(field_entry.path));
|
|
3742
|
+
if (!field_entry.value.empty()) {
|
|
3743
|
+
rb_hash_aset(entry, value_property, cb_str_new(field_entry.value));
|
|
3744
|
+
}
|
|
3745
|
+
if (field_entry.ec) {
|
|
3746
|
+
rb_hash_aset(
|
|
3747
|
+
entry,
|
|
3748
|
+
error_property,
|
|
3749
|
+
cb_map_error_code(field_entry.ec,
|
|
3750
|
+
fmt::format("error getting result for spec at index {}, path \"{}\"", i, field_entry.path)));
|
|
3751
|
+
}
|
|
3752
|
+
rb_ary_store(fields, static_cast<long>(i), entry);
|
|
3753
|
+
}
|
|
3754
|
+
rb_ary_store(res, static_cast<long>(j), lookup_in_entry_res);
|
|
3755
|
+
}
|
|
3756
|
+
|
|
3501
3757
|
return res;
|
|
3502
3758
|
} catch (const std::system_error& se) {
|
|
3503
3759
|
rb_exc_raise(cb_map_error_code(se.code(), fmt::format("failed to perform {}: {}", __func__, se.what()), false));
|
|
@@ -3661,6 +3917,284 @@ cb_Backend_document_mutate_in(VALUE self, VALUE bucket, VALUE scope, VALUE colle
|
|
|
3661
3917
|
return Qnil;
|
|
3662
3918
|
}
|
|
3663
3919
|
|
|
3920
|
+
struct cb_core_scan_result_data {
|
|
3921
|
+
std::unique_ptr<couchbase::core::scan_result> scan_result{};
|
|
3922
|
+
};
|
|
3923
|
+
|
|
3924
|
+
static void
|
|
3925
|
+
cb_CoreScanResult_mark(void* ptr)
|
|
3926
|
+
{
|
|
3927
|
+
/* No embedded Ruby objects */
|
|
3928
|
+
}
|
|
3929
|
+
|
|
3930
|
+
static void
|
|
3931
|
+
cb_CoreScanResult_free(void* ptr)
|
|
3932
|
+
{
|
|
3933
|
+
auto* data = static_cast<cb_core_scan_result_data*>(ptr);
|
|
3934
|
+
if (data->scan_result != nullptr && !data->scan_result->is_cancelled()) {
|
|
3935
|
+
data->scan_result->cancel();
|
|
3936
|
+
}
|
|
3937
|
+
data->scan_result.reset();
|
|
3938
|
+
ruby_xfree(data);
|
|
3939
|
+
}
|
|
3940
|
+
|
|
3941
|
+
static const rb_data_type_t cb_core_scan_result_type {
|
|
3942
|
+
.wrap_struct_name = "Couchbase/Backend/CoreScanResult",
|
|
3943
|
+
.function = {
|
|
3944
|
+
.dmark = cb_CoreScanResult_mark,
|
|
3945
|
+
.dfree = cb_CoreScanResult_free,
|
|
3946
|
+
},
|
|
3947
|
+
.data = nullptr,
|
|
3948
|
+
#ifdef RUBY_TYPED_FREE_IMMEDIATELY
|
|
3949
|
+
.flags = RUBY_TYPED_FREE_IMMEDIATELY,
|
|
3950
|
+
#endif
|
|
3951
|
+
};
|
|
3952
|
+
|
|
3953
|
+
static VALUE
|
|
3954
|
+
cb_CoreScanResult_allocate(VALUE klass)
|
|
3955
|
+
{
|
|
3956
|
+
cb_core_scan_result_data* data = nullptr;
|
|
3957
|
+
VALUE obj = TypedData_Make_Struct(klass, cb_core_scan_result_data, &cb_core_scan_result_type, data);
|
|
3958
|
+
return obj;
|
|
3959
|
+
}
|
|
3960
|
+
|
|
3961
|
+
static VALUE
|
|
3962
|
+
cb_CoreScanResult_is_cancelled(VALUE self)
|
|
3963
|
+
{
|
|
3964
|
+
cb_core_scan_result_data* data = nullptr;
|
|
3965
|
+
TypedData_Get_Struct(self, cb_core_scan_result_data, &cb_core_scan_result_type, data);
|
|
3966
|
+
auto resp = data->scan_result->is_cancelled();
|
|
3967
|
+
if (resp) {
|
|
3968
|
+
return Qtrue;
|
|
3969
|
+
} else {
|
|
3970
|
+
return Qfalse;
|
|
3971
|
+
}
|
|
3972
|
+
}
|
|
3973
|
+
|
|
3974
|
+
static VALUE
|
|
3975
|
+
cb_CoreScanResult_cancel(VALUE self)
|
|
3976
|
+
{
|
|
3977
|
+
cb_core_scan_result_data* data = nullptr;
|
|
3978
|
+
TypedData_Get_Struct(self, cb_core_scan_result_data, &cb_core_scan_result_type, data);
|
|
3979
|
+
data->scan_result->cancel();
|
|
3980
|
+
return Qnil;
|
|
3981
|
+
}
|
|
3982
|
+
|
|
3983
|
+
static VALUE
|
|
3984
|
+
cb_CoreScanResult_next_item(VALUE self)
|
|
3985
|
+
{
|
|
3986
|
+
try {
|
|
3987
|
+
cb_core_scan_result_data* data = nullptr;
|
|
3988
|
+
TypedData_Get_Struct(self, cb_core_scan_result_data, &cb_core_scan_result_type, data);
|
|
3989
|
+
auto barrier = std::make_shared<std::promise<tl::expected<couchbase::core::range_scan_item, std::error_code>>>();
|
|
3990
|
+
auto f = barrier->get_future();
|
|
3991
|
+
data->scan_result->next([barrier](couchbase::core::range_scan_item item, std::error_code ec) {
|
|
3992
|
+
if (ec) {
|
|
3993
|
+
return barrier->set_value(tl::unexpected(ec));
|
|
3994
|
+
} else {
|
|
3995
|
+
return barrier->set_value(item);
|
|
3996
|
+
}
|
|
3997
|
+
});
|
|
3998
|
+
auto resp = cb_wait_for_future(f);
|
|
3999
|
+
if (!resp.has_value()) {
|
|
4000
|
+
// If the error code is range_scan_completed return nil without raising an exception (nil signifies that there
|
|
4001
|
+
// are no more items)
|
|
4002
|
+
if (resp.error() != couchbase::errc::key_value::range_scan_completed) {
|
|
4003
|
+
cb_throw_error_code(resp.error(), "unable to fetch next scan item");
|
|
4004
|
+
}
|
|
4005
|
+
// Release ownership of scan_result unique pointer
|
|
4006
|
+
return Qnil;
|
|
4007
|
+
}
|
|
4008
|
+
auto item = resp.value();
|
|
4009
|
+
VALUE res = rb_hash_new();
|
|
4010
|
+
rb_hash_aset(res, rb_id2sym(rb_intern("id")), cb_str_new(item.key));
|
|
4011
|
+
if (item.body.has_value()) {
|
|
4012
|
+
auto body = item.body.value();
|
|
4013
|
+
rb_hash_aset(res, rb_id2sym(rb_intern("id")), cb_str_new(item.key));
|
|
4014
|
+
rb_hash_aset(res, rb_id2sym(rb_intern("encoded")), cb_str_new(body.value));
|
|
4015
|
+
rb_hash_aset(res, rb_id2sym(rb_intern("cas")), cb_cas_to_num(body.cas));
|
|
4016
|
+
rb_hash_aset(res, rb_id2sym(rb_intern("flags")), UINT2NUM(body.flags));
|
|
4017
|
+
rb_hash_aset(res, rb_id2sym(rb_intern("expiry")), UINT2NUM(body.expiry));
|
|
4018
|
+
rb_hash_aset(res, rb_id2sym(rb_intern("id_only")), Qfalse);
|
|
4019
|
+
} else {
|
|
4020
|
+
rb_hash_aset(res, rb_id2sym(rb_intern("id_only")), Qtrue);
|
|
4021
|
+
}
|
|
4022
|
+
return res;
|
|
4023
|
+
} catch (const std::system_error& se) {
|
|
4024
|
+
rb_exc_raise(cb_map_error_code(se.code(), fmt::format("failed to perform {}: {}", __func__, se.what()), false));
|
|
4025
|
+
} catch (const ruby_exception& e) {
|
|
4026
|
+
rb_exc_raise(e.exception_object());
|
|
4027
|
+
}
|
|
4028
|
+
return Qnil;
|
|
4029
|
+
}
|
|
4030
|
+
|
|
4031
|
+
static VALUE
|
|
4032
|
+
cb_Backend_document_scan_create(VALUE self, VALUE bucket, VALUE scope, VALUE collection, VALUE scan_type, VALUE options)
|
|
4033
|
+
{
|
|
4034
|
+
const auto& cluster = cb_backend_to_cluster(self);
|
|
4035
|
+
|
|
4036
|
+
Check_Type(bucket, T_STRING);
|
|
4037
|
+
Check_Type(scope, T_STRING);
|
|
4038
|
+
Check_Type(collection, T_STRING);
|
|
4039
|
+
Check_Type(scan_type, T_HASH);
|
|
4040
|
+
if (!NIL_P(options)) {
|
|
4041
|
+
Check_Type(options, T_HASH);
|
|
4042
|
+
}
|
|
4043
|
+
|
|
4044
|
+
try {
|
|
4045
|
+
couchbase::core::range_scan_orchestrator_options orchestrator_options{};
|
|
4046
|
+
cb_extract_timeout(orchestrator_options, options);
|
|
4047
|
+
cb_extract_option_bool(orchestrator_options.ids_only, options, "ids_only");
|
|
4048
|
+
cb_extract_option_number(orchestrator_options.batch_item_limit, options, "batch_item_limit");
|
|
4049
|
+
cb_extract_option_number(orchestrator_options.batch_byte_limit, options, "batch_byte_limit");
|
|
4050
|
+
cb_extract_option_number(orchestrator_options.concurrency, options, "concurrency");
|
|
4051
|
+
|
|
4052
|
+
// Extracting the mutation state
|
|
4053
|
+
if (VALUE mutation_state = rb_hash_aref(options, rb_id2sym(rb_intern("mutation_state"))); !NIL_P(mutation_state)) {
|
|
4054
|
+
cb_check_type(mutation_state, T_ARRAY);
|
|
4055
|
+
auto state_size = static_cast<std::size_t>(RARRAY_LEN(mutation_state));
|
|
4056
|
+
|
|
4057
|
+
if (state_size > 0) {
|
|
4058
|
+
auto core_mut_state = couchbase::core::mutation_state{};
|
|
4059
|
+
core_mut_state.tokens.reserve(state_size);
|
|
4060
|
+
for (std::size_t i = 0; i < state_size; ++i) {
|
|
4061
|
+
VALUE token = rb_ary_entry(mutation_state, static_cast<long>(i));
|
|
4062
|
+
cb_check_type(token, T_HASH);
|
|
4063
|
+
VALUE bucket_name = rb_hash_aref(token, rb_id2sym(rb_intern("bucket_name")));
|
|
4064
|
+
cb_check_type(bucket_name, T_STRING);
|
|
4065
|
+
VALUE partition_id = rb_hash_aref(token, rb_id2sym(rb_intern("partition_id")));
|
|
4066
|
+
cb_check_type(partition_id, T_FIXNUM);
|
|
4067
|
+
VALUE partition_uuid = rb_hash_aref(token, rb_id2sym(rb_intern("partition_uuid")));
|
|
4068
|
+
switch (TYPE(partition_uuid)) {
|
|
4069
|
+
case T_FIXNUM:
|
|
4070
|
+
case T_BIGNUM:
|
|
4071
|
+
break;
|
|
4072
|
+
default:
|
|
4073
|
+
rb_raise(rb_eArgError, "partition_uuid must be an Integer");
|
|
4074
|
+
}
|
|
4075
|
+
VALUE sequence_number = rb_hash_aref(token, rb_id2sym(rb_intern("sequence_number")));
|
|
4076
|
+
switch (TYPE(sequence_number)) {
|
|
4077
|
+
case T_FIXNUM:
|
|
4078
|
+
case T_BIGNUM:
|
|
4079
|
+
break;
|
|
4080
|
+
default:
|
|
4081
|
+
rb_raise(rb_eArgError, "sequence_number must be an Integer");
|
|
4082
|
+
}
|
|
4083
|
+
core_mut_state.tokens.emplace_back(NUM2ULL(partition_uuid),
|
|
4084
|
+
NUM2ULL(sequence_number),
|
|
4085
|
+
gsl::narrow_cast<std::uint16_t>(NUM2UINT(partition_id)),
|
|
4086
|
+
cb_string_new(bucket_name));
|
|
4087
|
+
}
|
|
4088
|
+
|
|
4089
|
+
orchestrator_options.consistent_with = core_mut_state;
|
|
4090
|
+
}
|
|
4091
|
+
}
|
|
4092
|
+
|
|
4093
|
+
auto bucket_name = cb_string_new(bucket);
|
|
4094
|
+
auto scope_name = cb_string_new(scope);
|
|
4095
|
+
auto collection_name = cb_string_new(collection);
|
|
4096
|
+
|
|
4097
|
+
// Getting the operation agent
|
|
4098
|
+
auto agent_group = couchbase::core::agent_group(cluster->io_context(), couchbase::core::agent_group_config{ { cluster } });
|
|
4099
|
+
agent_group.open_bucket(bucket_name);
|
|
4100
|
+
auto agent = agent_group.get_agent(bucket_name);
|
|
4101
|
+
if (!agent.has_value()) {
|
|
4102
|
+
rb_raise(eCouchbaseError, "Cannot perform scan operation. Unable to get operation agent");
|
|
4103
|
+
return Qnil;
|
|
4104
|
+
}
|
|
4105
|
+
|
|
4106
|
+
// Getting the vbucket map
|
|
4107
|
+
auto barrier = std::make_shared<std::promise<tl::expected<couchbase::core::topology::configuration, std::error_code>>>();
|
|
4108
|
+
auto f = barrier->get_future();
|
|
4109
|
+
cluster->with_bucket_configuration(bucket_name,
|
|
4110
|
+
[barrier](std::error_code ec, const couchbase::core::topology::configuration& config) mutable {
|
|
4111
|
+
if (ec) {
|
|
4112
|
+
return barrier->set_value(tl::unexpected(ec));
|
|
4113
|
+
}
|
|
4114
|
+
barrier->set_value(config);
|
|
4115
|
+
});
|
|
4116
|
+
auto config = cb_wait_for_future(f);
|
|
4117
|
+
if (!config.has_value()) {
|
|
4118
|
+
rb_raise(eCouchbaseError, "Cannot perform scan operation. Unable to get bucket configuration");
|
|
4119
|
+
return Qnil;
|
|
4120
|
+
}
|
|
4121
|
+
if (!config->supports_range_scan()) {
|
|
4122
|
+
rb_raise(eFeatureNotAvailable, "Server does not support key-value scan operations");
|
|
4123
|
+
return Qnil;
|
|
4124
|
+
}
|
|
4125
|
+
auto vbucket_map = config->vbmap;
|
|
4126
|
+
if (!vbucket_map || vbucket_map->empty()) {
|
|
4127
|
+
rb_raise(eCouchbaseError, "Cannot perform scan operation. Unable to get vbucket map");
|
|
4128
|
+
return Qnil;
|
|
4129
|
+
}
|
|
4130
|
+
|
|
4131
|
+
// Constructing the scan type
|
|
4132
|
+
std::variant<std::monostate, couchbase::core::range_scan, couchbase::core::prefix_scan, couchbase::core::sampling_scan>
|
|
4133
|
+
core_scan_type{};
|
|
4134
|
+
ID scan_type_id = rb_sym2id(rb_hash_aref(scan_type, rb_id2sym(rb_intern("scan_type"))));
|
|
4135
|
+
if (scan_type_id == rb_intern("range")) {
|
|
4136
|
+
auto range_scan = couchbase::core::range_scan{};
|
|
4137
|
+
|
|
4138
|
+
VALUE from_hash = rb_hash_aref(scan_type, rb_id2sym(rb_intern("from")));
|
|
4139
|
+
VALUE to_hash = rb_hash_aref(scan_type, rb_id2sym(rb_intern("to")));
|
|
4140
|
+
|
|
4141
|
+
if (!NIL_P(from_hash)) {
|
|
4142
|
+
Check_Type(from_hash, T_HASH);
|
|
4143
|
+
range_scan.from = couchbase::core::scan_term{};
|
|
4144
|
+
cb_extract_option_string(range_scan.from->term, from_hash, "term");
|
|
4145
|
+
cb_extract_option_bool(range_scan.from->exclusive, from_hash, "exclusive");
|
|
4146
|
+
}
|
|
4147
|
+
if (!NIL_P(to_hash)) {
|
|
4148
|
+
Check_Type(to_hash, T_HASH);
|
|
4149
|
+
range_scan.to = couchbase::core::scan_term{};
|
|
4150
|
+
cb_extract_option_string(range_scan.to->term, to_hash, "term");
|
|
4151
|
+
cb_extract_option_bool(range_scan.to->exclusive, to_hash, "exclusive");
|
|
4152
|
+
}
|
|
4153
|
+
core_scan_type = range_scan;
|
|
4154
|
+
} else if (scan_type_id == rb_intern("prefix")) {
|
|
4155
|
+
auto prefix_scan = couchbase::core::prefix_scan{};
|
|
4156
|
+
cb_extract_option_string(prefix_scan.prefix, scan_type, "prefix");
|
|
4157
|
+
core_scan_type = prefix_scan;
|
|
4158
|
+
} else if (scan_type_id == rb_intern("sampling")) {
|
|
4159
|
+
auto sampling_scan = couchbase::core::sampling_scan{};
|
|
4160
|
+
cb_extract_option_number(sampling_scan.limit, scan_type, "limit");
|
|
4161
|
+
cb_extract_option_number(sampling_scan.seed, scan_type, "seed");
|
|
4162
|
+
core_scan_type = sampling_scan;
|
|
4163
|
+
} else {
|
|
4164
|
+
rb_raise(eInvalidArgument, "Invalid scan operation type");
|
|
4165
|
+
}
|
|
4166
|
+
|
|
4167
|
+
auto orchestrator = couchbase::core::range_scan_orchestrator(
|
|
4168
|
+
cluster->io_context(), agent.value(), vbucket_map.value(), scope_name, collection_name, core_scan_type, orchestrator_options);
|
|
4169
|
+
|
|
4170
|
+
// Start the scan
|
|
4171
|
+
auto resp = orchestrator.scan();
|
|
4172
|
+
if (!resp.has_value()) {
|
|
4173
|
+
cb_throw_error_code(resp.error(), "unable to start scan");
|
|
4174
|
+
}
|
|
4175
|
+
|
|
4176
|
+
// Wrap core scan_result inside Ruby ScanResult
|
|
4177
|
+
// Creating a Ruby CoreScanResult object *after* checking that no error occurred during orchestrator.scan()
|
|
4178
|
+
VALUE cCoreScanResult = rb_define_class_under(rb_define_module("Couchbase"), "CoreScanResult", rb_cObject);
|
|
4179
|
+
rb_define_alloc_func(cCoreScanResult, cb_CoreScanResult_allocate);
|
|
4180
|
+
rb_define_method(cCoreScanResult, "next_item", VALUE_FUNC(cb_CoreScanResult_next_item), 0);
|
|
4181
|
+
rb_define_method(cCoreScanResult, "cancelled?", VALUE_FUNC(cb_CoreScanResult_is_cancelled), 0);
|
|
4182
|
+
rb_define_method(cCoreScanResult, "cancel", VALUE_FUNC(cb_CoreScanResult_cancel), 0);
|
|
4183
|
+
VALUE core_scan_result_obj = rb_class_new_instance(0, NULL, cCoreScanResult);
|
|
4184
|
+
rb_ivar_set(core_scan_result_obj, rb_intern("@backend"), self);
|
|
4185
|
+
cb_core_scan_result_data* data = nullptr;
|
|
4186
|
+
TypedData_Get_Struct(core_scan_result_obj, cb_core_scan_result_data, &cb_core_scan_result_type, data);
|
|
4187
|
+
data->scan_result = std::make_unique<couchbase::core::scan_result>(resp.value());
|
|
4188
|
+
return core_scan_result_obj;
|
|
4189
|
+
|
|
4190
|
+
} catch (const std::system_error& se) {
|
|
4191
|
+
rb_exc_raise(cb_map_error_code(se.code(), fmt::format("failed to perform {}: {}", __func__, se.what()), false));
|
|
4192
|
+
} catch (const ruby_exception& e) {
|
|
4193
|
+
rb_exc_raise(e.exception_object());
|
|
4194
|
+
}
|
|
4195
|
+
return Qnil;
|
|
4196
|
+
}
|
|
4197
|
+
|
|
3664
4198
|
static int
|
|
3665
4199
|
cb_for_each_named_param(VALUE key, VALUE value, VALUE arg)
|
|
3666
4200
|
{
|
|
@@ -3696,6 +4230,7 @@ cb_Backend_document_query(VALUE self, VALUE statement, VALUE options)
|
|
|
3696
4230
|
cb_extract_option_bool(req.readonly, options, "readonly");
|
|
3697
4231
|
cb_extract_option_bool(req.flex_index, options, "flex_index");
|
|
3698
4232
|
cb_extract_option_bool(req.preserve_expiry, options, "preserve_expiry");
|
|
4233
|
+
cb_extract_option_bool(req.use_replica, options, "use_replica");
|
|
3699
4234
|
cb_extract_option_uint64(req.scan_cap, options, "scan_cap");
|
|
3700
4235
|
cb_extract_duration(req.scan_wait, options, "scan_wait");
|
|
3701
4236
|
cb_extract_option_uint64(req.max_parallelism, options, "max_parallelism");
|
|
@@ -3833,18 +4368,20 @@ cb_Backend_document_query(VALUE self, VALUE statement, VALUE options)
|
|
|
3833
4368
|
static void
|
|
3834
4369
|
cb_generate_bucket_settings(VALUE bucket, couchbase::core::management::cluster::bucket_settings& entry, bool is_create)
|
|
3835
4370
|
{
|
|
3836
|
-
if (VALUE bucket_type = rb_hash_aref(bucket, rb_id2sym(rb_intern("bucket_type")));
|
|
3837
|
-
if (bucket_type
|
|
3838
|
-
|
|
3839
|
-
|
|
3840
|
-
|
|
3841
|
-
|
|
3842
|
-
|
|
4371
|
+
if (VALUE bucket_type = rb_hash_aref(bucket, rb_id2sym(rb_intern("bucket_type"))); !NIL_P(bucket_type)) {
|
|
4372
|
+
if (TYPE(bucket_type) == T_SYMBOL) {
|
|
4373
|
+
if (bucket_type == rb_id2sym(rb_intern("couchbase")) || bucket_type == rb_id2sym(rb_intern("membase"))) {
|
|
4374
|
+
entry.bucket_type = couchbase::core::management::cluster::bucket_type::couchbase;
|
|
4375
|
+
} else if (bucket_type == rb_id2sym(rb_intern("memcached"))) {
|
|
4376
|
+
entry.bucket_type = couchbase::core::management::cluster::bucket_type::memcached;
|
|
4377
|
+
} else if (bucket_type == rb_id2sym(rb_intern("ephemeral"))) {
|
|
4378
|
+
entry.bucket_type = couchbase::core::management::cluster::bucket_type::ephemeral;
|
|
4379
|
+
} else {
|
|
4380
|
+
throw ruby_exception(rb_eArgError, rb_sprintf("unknown bucket type, given %+" PRIsVALUE, bucket_type));
|
|
4381
|
+
}
|
|
3843
4382
|
} else {
|
|
3844
|
-
throw ruby_exception(rb_eArgError, rb_sprintf("
|
|
4383
|
+
throw ruby_exception(rb_eArgError, rb_sprintf("bucket type must be a Symbol, given %+" PRIsVALUE, bucket_type));
|
|
3845
4384
|
}
|
|
3846
|
-
} else {
|
|
3847
|
-
throw ruby_exception(rb_eArgError, rb_sprintf("bucket type must be a Symbol, given %+" PRIsVALUE, bucket_type));
|
|
3848
4385
|
}
|
|
3849
4386
|
|
|
3850
4387
|
if (VALUE name = rb_hash_aref(bucket, rb_id2sym(rb_intern("name"))); TYPE(name) == T_STRING) {
|
|
@@ -3853,10 +4390,12 @@ cb_generate_bucket_settings(VALUE bucket, couchbase::core::management::cluster::
|
|
|
3853
4390
|
throw ruby_exception(rb_eArgError, rb_sprintf("bucket name must be a String, given %+" PRIsVALUE, name));
|
|
3854
4391
|
}
|
|
3855
4392
|
|
|
3856
|
-
if (VALUE quota = rb_hash_aref(bucket, rb_id2sym(rb_intern("ram_quota_mb")));
|
|
3857
|
-
|
|
3858
|
-
|
|
3859
|
-
|
|
4393
|
+
if (VALUE quota = rb_hash_aref(bucket, rb_id2sym(rb_intern("ram_quota_mb"))); !NIL_P(quota)) {
|
|
4394
|
+
if (TYPE(quota) == T_FIXNUM) {
|
|
4395
|
+
entry.ram_quota_mb = FIX2ULONG(quota);
|
|
4396
|
+
} else {
|
|
4397
|
+
throw ruby_exception(rb_eArgError, rb_sprintf("bucket RAM quota must be an Integer, given %+" PRIsVALUE, quota));
|
|
4398
|
+
}
|
|
3860
4399
|
}
|
|
3861
4400
|
|
|
3862
4401
|
if (VALUE expiry = rb_hash_aref(bucket, rb_id2sym(rb_intern("max_expiry"))); !NIL_P(expiry)) {
|
|
@@ -3953,6 +4492,31 @@ cb_generate_bucket_settings(VALUE bucket, couchbase::core::management::cluster::
|
|
|
3953
4492
|
}
|
|
3954
4493
|
}
|
|
3955
4494
|
|
|
4495
|
+
if (VALUE history_retention_collection_default = rb_hash_aref(bucket, rb_id2sym(rb_intern("history_retention_collection_default")));
|
|
4496
|
+
!NIL_P(history_retention_collection_default)) {
|
|
4497
|
+
entry.history_retention_collection_default = RTEST(history_retention_collection_default);
|
|
4498
|
+
}
|
|
4499
|
+
|
|
4500
|
+
if (VALUE history_retention_bytes = rb_hash_aref(bucket, rb_id2sym(rb_intern("history_retention_bytes")));
|
|
4501
|
+
!NIL_P(history_retention_bytes)) {
|
|
4502
|
+
if (TYPE(history_retention_bytes) == T_FIXNUM) {
|
|
4503
|
+
entry.history_retention_bytes = FIX2UINT(history_retention_bytes);
|
|
4504
|
+
} else {
|
|
4505
|
+
throw ruby_exception(rb_eArgError,
|
|
4506
|
+
rb_sprintf("history retention bytes must be an Integer, given %+" PRIsVALUE, history_retention_bytes));
|
|
4507
|
+
}
|
|
4508
|
+
}
|
|
4509
|
+
|
|
4510
|
+
if (VALUE history_retention_duration = rb_hash_aref(bucket, rb_id2sym(rb_intern("history_retention_duration")));
|
|
4511
|
+
!NIL_P(history_retention_duration)) {
|
|
4512
|
+
if (TYPE(history_retention_duration) == T_FIXNUM) {
|
|
4513
|
+
entry.history_retention_duration = FIX2UINT(history_retention_duration);
|
|
4514
|
+
} else {
|
|
4515
|
+
throw ruby_exception(
|
|
4516
|
+
rb_eArgError, rb_sprintf("history retention duration must be an Integer, given %+" PRIsVALUE, history_retention_duration));
|
|
4517
|
+
}
|
|
4518
|
+
}
|
|
4519
|
+
|
|
3956
4520
|
if (is_create) {
|
|
3957
4521
|
if (VALUE conflict_resolution_type = rb_hash_aref(bucket, rb_id2sym(rb_intern("conflict_resolution_type")));
|
|
3958
4522
|
!NIL_P(conflict_resolution_type)) {
|
|
@@ -4117,7 +4681,9 @@ cb_extract_bucket_settings(const couchbase::core::management::cluster::bucket_se
|
|
|
4117
4681
|
rb_hash_aset(bucket, rb_id2sym(rb_intern("name")), cb_str_new(entry.name));
|
|
4118
4682
|
rb_hash_aset(bucket, rb_id2sym(rb_intern("uuid")), cb_str_new(entry.uuid));
|
|
4119
4683
|
rb_hash_aset(bucket, rb_id2sym(rb_intern("ram_quota_mb")), ULL2NUM(entry.ram_quota_mb));
|
|
4120
|
-
|
|
4684
|
+
if (const auto& val = entry.max_expiry; val.has_value()) {
|
|
4685
|
+
rb_hash_aset(bucket, rb_id2sym(rb_intern("max_expiry")), ULONG2NUM(val.value()));
|
|
4686
|
+
}
|
|
4121
4687
|
switch (entry.compression_mode) {
|
|
4122
4688
|
case couchbase::core::management::cluster::bucket_compression::off:
|
|
4123
4689
|
rb_hash_aset(bucket, rb_id2sym(rb_intern("compression_mode")), rb_id2sym(rb_intern("off")));
|
|
@@ -4132,9 +4698,15 @@ cb_extract_bucket_settings(const couchbase::core::management::cluster::bucket_se
|
|
|
4132
4698
|
rb_hash_aset(bucket, rb_id2sym(rb_intern("compression_mode")), Qnil);
|
|
4133
4699
|
break;
|
|
4134
4700
|
}
|
|
4135
|
-
|
|
4136
|
-
|
|
4137
|
-
|
|
4701
|
+
if (const auto& val = entry.num_replicas; val.has_value()) {
|
|
4702
|
+
rb_hash_aset(bucket, rb_id2sym(rb_intern("num_replicas")), ULONG2NUM(val.value()));
|
|
4703
|
+
}
|
|
4704
|
+
if (const auto& val = entry.replica_indexes; val.has_value()) {
|
|
4705
|
+
rb_hash_aset(bucket, rb_id2sym(rb_intern("replica_indexes")), val.value() ? Qtrue : Qfalse);
|
|
4706
|
+
}
|
|
4707
|
+
if (const auto& val = entry.flush_enabled; val.has_value()) {
|
|
4708
|
+
rb_hash_aset(bucket, rb_id2sym(rb_intern("flush_enabled")), val.value() ? Qtrue : Qfalse);
|
|
4709
|
+
}
|
|
4138
4710
|
switch (entry.eviction_policy) {
|
|
4139
4711
|
case couchbase::core::management::cluster::bucket_eviction_policy::full:
|
|
4140
4712
|
rb_hash_aset(bucket, rb_id2sym(rb_intern("eviction_policy")), rb_id2sym(rb_intern("full")));
|
|
@@ -4183,6 +4755,18 @@ cb_extract_bucket_settings(const couchbase::core::management::cluster::bucket_se
|
|
|
4183
4755
|
break;
|
|
4184
4756
|
}
|
|
4185
4757
|
}
|
|
4758
|
+
if (entry.history_retention_collection_default.has_value()) {
|
|
4759
|
+
rb_hash_aset(bucket,
|
|
4760
|
+
rb_id2sym(rb_intern("history_retention_collection_default")),
|
|
4761
|
+
entry.history_retention_collection_default.value() ? Qtrue : Qfalse);
|
|
4762
|
+
}
|
|
4763
|
+
if (const auto& val = entry.history_retention_bytes; val.has_value()) {
|
|
4764
|
+
rb_hash_aset(bucket, rb_id2sym(rb_intern("history_retention_bytes")), ULONG2NUM(val.value()));
|
|
4765
|
+
}
|
|
4766
|
+
if (const auto& val = entry.history_retention_duration; val.has_value()) {
|
|
4767
|
+
rb_hash_aset(bucket, rb_id2sym(rb_intern("history_retention_duration")), ULONG2NUM(val.value()));
|
|
4768
|
+
}
|
|
4769
|
+
|
|
4186
4770
|
VALUE capabilities = rb_ary_new_capa(static_cast<long>(entry.capabilities.size()));
|
|
4187
4771
|
for (const auto& capa : entry.capabilities) {
|
|
4188
4772
|
rb_ary_push(capabilities, cb_str_new(capa));
|
|
@@ -4864,6 +5448,10 @@ cb_Backend_scope_get_all(VALUE self, VALUE bucket_name, VALUE options)
|
|
|
4864
5448
|
VALUE collection = rb_hash_new();
|
|
4865
5449
|
rb_hash_aset(collection, rb_id2sym(rb_intern("uid")), ULL2NUM(c.uid));
|
|
4866
5450
|
rb_hash_aset(collection, rb_id2sym(rb_intern("name")), cb_str_new(c.name));
|
|
5451
|
+
rb_hash_aset(collection, rb_id2sym(rb_intern("max_expiry")), ULONG2NUM(c.max_expiry));
|
|
5452
|
+
if (c.history.has_value()) {
|
|
5453
|
+
rb_hash_aset(collection, rb_id2sym(rb_intern("history")), c.history.value() ? Qtrue : Qfalse);
|
|
5454
|
+
}
|
|
4867
5455
|
rb_ary_push(collections, collection);
|
|
4868
5456
|
}
|
|
4869
5457
|
rb_hash_aset(scope, rb_id2sym(rb_intern("collections")), collections);
|
|
@@ -4994,13 +5582,16 @@ cb_Backend_scope_drop(VALUE self, VALUE bucket_name, VALUE scope_name, VALUE opt
|
|
|
4994
5582
|
}
|
|
4995
5583
|
|
|
4996
5584
|
static VALUE
|
|
4997
|
-
cb_Backend_collection_create(VALUE self, VALUE bucket_name, VALUE scope_name, VALUE collection_name, VALUE
|
|
5585
|
+
cb_Backend_collection_create(VALUE self, VALUE bucket_name, VALUE scope_name, VALUE collection_name, VALUE settings, VALUE options)
|
|
4998
5586
|
{
|
|
4999
5587
|
const auto& cluster = cb_backend_to_cluster(self);
|
|
5000
5588
|
|
|
5001
5589
|
Check_Type(bucket_name, T_STRING);
|
|
5002
5590
|
Check_Type(scope_name, T_STRING);
|
|
5003
5591
|
Check_Type(collection_name, T_STRING);
|
|
5592
|
+
if (!NIL_P(settings)) {
|
|
5593
|
+
Check_Type(settings, T_HASH);
|
|
5594
|
+
}
|
|
5004
5595
|
if (!NIL_P(options)) {
|
|
5005
5596
|
Check_Type(options, T_HASH);
|
|
5006
5597
|
}
|
|
@@ -5011,10 +5602,20 @@ cb_Backend_collection_create(VALUE self, VALUE bucket_name, VALUE scope_name, VA
|
|
|
5011
5602
|
cb_string_new(collection_name) };
|
|
5012
5603
|
cb_extract_timeout(req, options);
|
|
5013
5604
|
|
|
5014
|
-
if (!NIL_P(
|
|
5015
|
-
|
|
5016
|
-
|
|
5605
|
+
if (!NIL_P(settings)) {
|
|
5606
|
+
if (VALUE max_expiry = rb_hash_aref(settings, rb_id2sym(rb_intern("max_expiry"))); !NIL_P(max_expiry)) {
|
|
5607
|
+
if (TYPE(max_expiry) == T_FIXNUM) {
|
|
5608
|
+
req.max_expiry = FIX2UINT(max_expiry);
|
|
5609
|
+
} else {
|
|
5610
|
+
throw ruby_exception(rb_eArgError,
|
|
5611
|
+
rb_sprintf("collection max expiry must be an Integer, given %+" PRIsVALUE, max_expiry));
|
|
5612
|
+
}
|
|
5613
|
+
}
|
|
5614
|
+
if (VALUE history = rb_hash_aref(settings, rb_id2sym(rb_intern("history"))); !NIL_P(history)) {
|
|
5615
|
+
req.history = RTEST(history);
|
|
5616
|
+
}
|
|
5017
5617
|
}
|
|
5618
|
+
|
|
5018
5619
|
auto barrier = std::make_shared<std::promise<couchbase::core::operations::management::collection_create_response>>();
|
|
5019
5620
|
auto f = barrier->get_future();
|
|
5020
5621
|
cluster->execute(req, [barrier](couchbase::core::operations::management::collection_create_response&& resp) {
|
|
@@ -5036,6 +5637,62 @@ cb_Backend_collection_create(VALUE self, VALUE bucket_name, VALUE scope_name, VA
|
|
|
5036
5637
|
return Qnil;
|
|
5037
5638
|
}
|
|
5038
5639
|
|
|
5640
|
+
static VALUE
|
|
5641
|
+
cb_Backend_collection_update(VALUE self, VALUE bucket_name, VALUE scope_name, VALUE collection_name, VALUE settings, VALUE options)
|
|
5642
|
+
{
|
|
5643
|
+
const auto& cluster = cb_backend_to_cluster(self);
|
|
5644
|
+
|
|
5645
|
+
Check_Type(bucket_name, T_STRING);
|
|
5646
|
+
Check_Type(scope_name, T_STRING);
|
|
5647
|
+
Check_Type(collection_name, T_STRING);
|
|
5648
|
+
if (!NIL_P(settings)) {
|
|
5649
|
+
Check_Type(settings, T_HASH);
|
|
5650
|
+
}
|
|
5651
|
+
if (!NIL_P(options)) {
|
|
5652
|
+
Check_Type(options, T_HASH);
|
|
5653
|
+
}
|
|
5654
|
+
|
|
5655
|
+
try {
|
|
5656
|
+
couchbase::core::operations::management::collection_update_request req{ cb_string_new(bucket_name),
|
|
5657
|
+
cb_string_new(scope_name),
|
|
5658
|
+
cb_string_new(collection_name) };
|
|
5659
|
+
cb_extract_timeout(req, options);
|
|
5660
|
+
|
|
5661
|
+
if (!NIL_P(settings)) {
|
|
5662
|
+
if (VALUE max_expiry = rb_hash_aref(settings, rb_id2sym(rb_intern("max_expiry"))); !NIL_P(max_expiry)) {
|
|
5663
|
+
if (TYPE(max_expiry) == T_FIXNUM) {
|
|
5664
|
+
req.max_expiry = FIX2UINT(max_expiry);
|
|
5665
|
+
} else {
|
|
5666
|
+
throw ruby_exception(rb_eArgError,
|
|
5667
|
+
rb_sprintf("collection max expiry must be an Integer, given %+" PRIsVALUE, max_expiry));
|
|
5668
|
+
}
|
|
5669
|
+
}
|
|
5670
|
+
if (VALUE history = rb_hash_aref(settings, rb_id2sym(rb_intern("history"))); !NIL_P(history)) {
|
|
5671
|
+
req.history = RTEST(history);
|
|
5672
|
+
}
|
|
5673
|
+
}
|
|
5674
|
+
|
|
5675
|
+
auto barrier = std::make_shared<std::promise<couchbase::core::operations::management::collection_update_response>>();
|
|
5676
|
+
auto f = barrier->get_future();
|
|
5677
|
+
cluster->execute(req, [barrier](couchbase::core::operations::management::collection_update_response&& resp) {
|
|
5678
|
+
barrier->set_value(std::move(resp));
|
|
5679
|
+
});
|
|
5680
|
+
auto resp = cb_wait_for_future(f);
|
|
5681
|
+
if (resp.ctx.ec) {
|
|
5682
|
+
cb_throw_error_code(
|
|
5683
|
+
resp.ctx,
|
|
5684
|
+
fmt::format(
|
|
5685
|
+
R"(unable update the collection "{}.{}" on the bucket "{}")", req.scope_name, req.collection_name, req.bucket_name));
|
|
5686
|
+
}
|
|
5687
|
+
return ULL2NUM(resp.uid);
|
|
5688
|
+
} catch (const std::system_error& se) {
|
|
5689
|
+
rb_exc_raise(cb_map_error_code(se.code(), fmt::format("failed to perform {}: {}", __func__, se.what()), false));
|
|
5690
|
+
} catch (const ruby_exception& e) {
|
|
5691
|
+
rb_exc_raise(e.exception_object());
|
|
5692
|
+
}
|
|
5693
|
+
return Qnil;
|
|
5694
|
+
}
|
|
5695
|
+
|
|
5039
5696
|
static VALUE
|
|
5040
5697
|
cb_Backend_collection_drop(VALUE self, VALUE bucket_name, VALUE scope_name, VALUE collection_name, VALUE options)
|
|
5041
5698
|
{
|
|
@@ -8577,10 +9234,20 @@ cb_Backend_form_encode(VALUE self, VALUE data)
|
|
|
8577
9234
|
return cb_str_new(encoded);
|
|
8578
9235
|
}
|
|
8579
9236
|
|
|
9237
|
+
static VALUE
|
|
9238
|
+
cb_Backend_enable_protocol_logger_to_save_network_traffic_to_file(VALUE /* self */, VALUE path)
|
|
9239
|
+
{
|
|
9240
|
+
Check_Type(path, T_STRING);
|
|
9241
|
+
couchbase::core::logger::configuration configuration{};
|
|
9242
|
+
configuration.filename = cb_string_new(path);
|
|
9243
|
+
couchbase::core::logger::create_protocol_logger(configuration);
|
|
9244
|
+
return Qnil;
|
|
9245
|
+
}
|
|
9246
|
+
|
|
8580
9247
|
static void
|
|
8581
9248
|
init_backend(VALUE mCouchbase)
|
|
8582
9249
|
{
|
|
8583
|
-
VALUE cBackend = rb_define_class_under(mCouchbase, "Backend",
|
|
9250
|
+
VALUE cBackend = rb_define_class_under(mCouchbase, "Backend", rb_cObject);
|
|
8584
9251
|
rb_define_alloc_func(cBackend, cb_Backend_allocate);
|
|
8585
9252
|
rb_define_method(cBackend, "open", VALUE_FUNC(cb_Backend_open), 3);
|
|
8586
9253
|
rb_define_method(cBackend, "close", VALUE_FUNC(cb_Backend_close), 0);
|
|
@@ -8604,7 +9271,10 @@ init_backend(VALUE mCouchbase)
|
|
|
8604
9271
|
rb_define_method(cBackend, "document_remove", VALUE_FUNC(cb_Backend_document_remove), 5);
|
|
8605
9272
|
rb_define_method(cBackend, "document_remove_multi", VALUE_FUNC(cb_Backend_document_remove_multi), 5);
|
|
8606
9273
|
rb_define_method(cBackend, "document_lookup_in", VALUE_FUNC(cb_Backend_document_lookup_in), 6);
|
|
9274
|
+
rb_define_method(cBackend, "document_lookup_in_any_replica", VALUE_FUNC(cb_Backend_document_lookup_in_any_replica), 6);
|
|
9275
|
+
rb_define_method(cBackend, "document_lookup_in_all_replicas", VALUE_FUNC(cb_Backend_document_lookup_in_all_replicas), 6);
|
|
8607
9276
|
rb_define_method(cBackend, "document_mutate_in", VALUE_FUNC(cb_Backend_document_mutate_in), 6);
|
|
9277
|
+
rb_define_method(cBackend, "document_scan_create", VALUE_FUNC(cb_Backend_document_scan_create), 5);
|
|
8608
9278
|
rb_define_method(cBackend, "document_query", VALUE_FUNC(cb_Backend_document_query), 2);
|
|
8609
9279
|
rb_define_method(cBackend, "document_touch", VALUE_FUNC(cb_Backend_document_touch), 6);
|
|
8610
9280
|
rb_define_method(cBackend, "document_exists", VALUE_FUNC(cb_Backend_document_exists), 5);
|
|
@@ -8640,6 +9310,7 @@ init_backend(VALUE mCouchbase)
|
|
|
8640
9310
|
rb_define_method(cBackend, "scope_create", VALUE_FUNC(cb_Backend_scope_create), 3);
|
|
8641
9311
|
rb_define_method(cBackend, "scope_drop", VALUE_FUNC(cb_Backend_scope_drop), 3);
|
|
8642
9312
|
rb_define_method(cBackend, "collection_create", VALUE_FUNC(cb_Backend_collection_create), 5);
|
|
9313
|
+
rb_define_method(cBackend, "collection_update", VALUE_FUNC(cb_Backend_collection_update), 5);
|
|
8643
9314
|
rb_define_method(cBackend, "collection_drop", VALUE_FUNC(cb_Backend_collection_drop), 4);
|
|
8644
9315
|
|
|
8645
9316
|
rb_define_method(cBackend, "query_index_get_all", VALUE_FUNC(cb_Backend_query_index_get_all), 2);
|
|
@@ -8706,6 +9377,10 @@ init_backend(VALUE mCouchbase)
|
|
|
8706
9377
|
rb_define_singleton_method(cBackend, "query_escape", VALUE_FUNC(cb_Backend_query_escape), 1);
|
|
8707
9378
|
rb_define_singleton_method(cBackend, "path_escape", VALUE_FUNC(cb_Backend_path_escape), 1);
|
|
8708
9379
|
rb_define_singleton_method(cBackend, "form_encode", VALUE_FUNC(cb_Backend_form_encode), 1);
|
|
9380
|
+
rb_define_singleton_method(cBackend,
|
|
9381
|
+
"enable_protocol_logger_to_save_network_traffic_to_file",
|
|
9382
|
+
VALUE_FUNC(cb_Backend_enable_protocol_logger_to_save_network_traffic_to_file),
|
|
9383
|
+
1);
|
|
8709
9384
|
}
|
|
8710
9385
|
|
|
8711
9386
|
void
|