From 9b5d30c27fd92462faf7116e65c2bbc6bb902dee Mon Sep 17 00:00:00 2001 From: gjaczewski Date: Tue, 26 Dec 2023 15:28:30 +0000 Subject: [PATCH 1/2] Add a non-generic PostCursorAsync that returns basic statistics --- .../CursorApi/CursorApiClientTest.cs | 15 +++++ .../CursorApi/CursorApiClientTestFixture.cs | 18 ++++++ .../CursorApi/CursorApiClient.cs | 61 +++++++++++++++++++ .../CursorApi/ICursorApiClient.cs | 26 ++++++++ .../CursorApi/Models/CursorResponse.cs | 51 +--------------- .../CursorApi/Models/CursorResponseBase.cs | 58 ++++++++++++++++++ 6 files changed, 179 insertions(+), 50 deletions(-) create mode 100644 arangodb-net-standard/CursorApi/Models/CursorResponseBase.cs diff --git a/arangodb-net-standard.Test/CursorApi/CursorApiClientTest.cs b/arangodb-net-standard.Test/CursorApi/CursorApiClientTest.cs index dd01fe20..47b94519 100644 --- a/arangodb-net-standard.Test/CursorApi/CursorApiClientTest.cs +++ b/arangodb-net-standard.Test/CursorApi/CursorApiClientTest.cs @@ -18,6 +18,7 @@ namespace ArangoDBNetStandardTest.CursorApi public class CursorApiClientTest : IClassFixture { private ICursorApiClient _cursorApi; + private readonly string _testCollection; public class MyModel { @@ -27,6 +28,7 @@ public class MyModel public CursorApiClientTest(CursorApiClientTestFixture fixture) { _cursorApi = fixture.ArangoDBClient.Cursor; + _testCollection = fixture.TestCollection; } [Fact] @@ -351,5 +353,18 @@ public async Task DeleteCursorAsync_ShouldSucceed() var deleteResponse = await _cursorApi.DeleteCursorAsync(response.Id); } + + [Fact] + public async Task PostCursorAsync_ShouldSucceed_WhenInsertWithBaseCursorResponse() + { + string query = "FOR Name IN [\"Jon\",\"Snow\"] INSERT {Name: Name} INTO @@testCollection"; + var bindVars = new Dictionary { ["@testCollection"] = _testCollection }; + + CursorResponseBase response = await _cursorApi.PostCursorAsync(query, bindVars); + + Assert.Equal(2, response.Extra.Stats.WritesExecuted); + Assert.Equal(HttpStatusCode.Created, response.Code); + Assert.False(response.Error); + } } } diff --git a/arangodb-net-standard.Test/CursorApi/CursorApiClientTestFixture.cs b/arangodb-net-standard.Test/CursorApi/CursorApiClientTestFixture.cs index 3c452511..1ec8ae4a 100644 --- a/arangodb-net-standard.Test/CursorApi/CursorApiClientTestFixture.cs +++ b/arangodb-net-standard.Test/CursorApi/CursorApiClientTestFixture.cs @@ -1,4 +1,6 @@ using ArangoDBNetStandard; +using ArangoDBNetStandard.CollectionApi.Models; +using System; using System.Threading.Tasks; namespace ArangoDBNetStandardTest.CursorApi @@ -7,6 +9,8 @@ public class CursorApiClientTestFixture : ApiClientTestFixtureBase { public ArangoDBClient ArangoDBClient { get; private set; } + public string TestCollection { get; } = "TestCollection"; + public CursorApiClientTestFixture() { } @@ -21,6 +25,20 @@ public override async Task InitializeAsync() ArangoDBClient = GetArangoDBClient(dbName); await GetVersionAsync(ArangoDBClient); + + try + { + var response = await ArangoDBClient.Collection.PostCollectionAsync( + new PostCollectionBody + { + Name = TestCollection + }); + } + catch (ApiErrorException ex) when (ex.ApiError.ErrorNum == 1207) + { + // The collection must exist already, carry on... + Console.WriteLine(ex.Message); + } } } } diff --git a/arangodb-net-standard/CursorApi/CursorApiClient.cs b/arangodb-net-standard/CursorApi/CursorApiClient.cs index 60191545..920d938f 100644 --- a/arangodb-net-standard/CursorApi/CursorApiClient.cs +++ b/arangodb-net-standard/CursorApi/CursorApiClient.cs @@ -138,6 +138,67 @@ public virtual async Task> PostCursorAsync( } } + /// + /// Execute an AQL query and return basic statistics. + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// Optional. The stream transaction Id. + /// A CancellationToken to observe while waiting for the task to complete or to cancel the task. + /// + + public virtual async Task PostCursorAsync( + string query, + Dictionary bindVars = null, + PostCursorOptions options = null, + bool? count = null, + long? batchSize = null, + bool? cache = null, + long? memoryLimit = null, + int? ttl = null, + string transactionId = null, + CancellationToken token = default) + { + var headerProperties = new CursorHeaderProperties(); + if (!string.IsNullOrWhiteSpace(transactionId)) + { + headerProperties.TransactionId = transactionId; + } + + var postCursorBody = new PostCursorBody + { + Query = query, + BindVars = bindVars, + Options = options, + Count = count, + BatchSize = batchSize, + Cache = cache, + MemoryLimit = memoryLimit, + Ttl = ttl + }; + + var content = await GetContentAsync(postCursorBody, new ApiClientSerializationOptions(true, true)).ConfigureAwait(false); + var headerCollection = GetHeaderCollection(headerProperties); + using (var response = await _client.PostAsync(_cursorApiPath, + content, + headerCollection, + token).ConfigureAwait(false)) + { + if (response.IsSuccessStatusCode) + { + var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); + return await DeserializeJsonFromStreamAsync(stream).ConfigureAwait(false); + } + throw await GetApiErrorExceptionAsync(response).ConfigureAwait(false); + }; + } + /// /// Deletes an existing cursor and frees the resources associated with it. /// DELETE /_api/cursor/{cursor-identifier} diff --git a/arangodb-net-standard/CursorApi/ICursorApiClient.cs b/arangodb-net-standard/CursorApi/ICursorApiClient.cs index 135479f0..99b2e068 100644 --- a/arangodb-net-standard/CursorApi/ICursorApiClient.cs +++ b/arangodb-net-standard/CursorApi/ICursorApiClient.cs @@ -53,6 +53,32 @@ Task> PostCursorAsync( CursorHeaderProperties headerProperties = null, CancellationToken token = default); + /// + /// Execute an AQL query and return basic statistics. + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// Optional. The stream transaction Id. + /// A CancellationToken to observe while waiting for the task to complete or to cancel the task. + /// + Task PostCursorAsync( + string query, + Dictionary bindVars = null, + PostCursorOptions options = null, + bool? count = null, + long? batchSize = null, + bool? cache = null, + long? memoryLimit = null, + int? ttl = null, + string transactionId = null, + CancellationToken token = default); + /// /// Advances an existing query cursor and gets the next set of results. /// Replaces diff --git a/arangodb-net-standard/CursorApi/Models/CursorResponse.cs b/arangodb-net-standard/CursorApi/Models/CursorResponse.cs index 5b8d6e6a..990f584f 100644 --- a/arangodb-net-standard/CursorApi/Models/CursorResponse.cs +++ b/arangodb-net-standard/CursorApi/Models/CursorResponse.cs @@ -1,5 +1,4 @@ using System.Collections.Generic; -using System.Net; namespace ArangoDBNetStandard.CursorApi.Models { @@ -7,59 +6,11 @@ namespace ArangoDBNetStandard.CursorApi.Models /// Response from ArangoDB when creating a new cursor. /// /// - public class CursorResponse : ICursorResponse + public class CursorResponse : CursorResponseBase, ICursorResponse { - /// - /// Indicates whether an error occurred - /// - /// - /// Note that in cases where an error occurs, the ArangoDBNetStandard - /// client will throw an rather than - /// populating this property. A try/catch block should be used instead - /// for any required error handling. - /// - public bool Error { get; set; } - - /// - /// the total number of result documents available - /// (only available if the query was executed with the count attribute set) - /// - public long Count { get; set; } - - /// - /// The HTTP status code - /// - public HttpStatusCode Code { get; set; } - - /// - /// Optional object with extra information about the query result contained - /// in its sub-attribute. - /// For data-modification queries, the sub-attribute will contain the number of - /// modified documents and the number of documents that could not be modified - /// due to an error (if ignoreErrors query option is specified). - /// - public CursorResponseExtra Extra { get; set; } - - /// - /// Indicates whether the query result was served from the query cache or not. - /// If the query result is served from the query cache, the extra return attribute - /// will not contain any stats sub-attribute and no profile sub-attribute. - /// - public bool Cached { get; set; } - - /// - /// Whether there are more results available for the cursor on the server. - /// - public bool HasMore { get; set; } - /// /// Result documents (might be empty if query has no results). /// public IEnumerable Result { get; set; } - - /// - /// ID of temporary cursor created on the server (optional). - /// - public string Id { get; set; } } } diff --git a/arangodb-net-standard/CursorApi/Models/CursorResponseBase.cs b/arangodb-net-standard/CursorApi/Models/CursorResponseBase.cs new file mode 100644 index 00000000..f6a40520 --- /dev/null +++ b/arangodb-net-standard/CursorApi/Models/CursorResponseBase.cs @@ -0,0 +1,58 @@ +using System.Net; + +namespace ArangoDBNetStandard.CursorApi.Models +{ + /// + /// Base part of the cursor response from ArangoDB not containing a generic result. + /// + public class CursorResponseBase + { + /// + /// Indicates whether an error occurred + /// + /// + /// Note that in cases where an error occurs, the ArangoDBNetStandard + /// client will throw an rather than + /// populating this property. A try/catch block should be used instead + /// for any required error handling. + /// + public bool Error { get; set; } + + /// + /// the total number of result documents available + /// (only available if the query was executed with the count attribute set) + /// + public long Count { get; set; } + + /// + /// The HTTP status code + /// + public HttpStatusCode Code { get; set; } + + /// + /// Optional object with extra information about the query result contained + /// in its sub-attribute. + /// For data-modification queries, the sub-attribute will contain the number of + /// modified documents and the number of documents that could not be modified + /// due to an error (if ignoreErrors query option is specified). + /// + public CursorResponseExtra Extra { get; set; } + + /// + /// Indicates whether the query result was served from the query cache or not. + /// If the query result is served from the query cache, the extra return attribute + /// will not contain any stats sub-attribute and no profile sub-attribute. + /// + public bool Cached { get; set; } + + /// + /// Whether there are more results available for the cursor on the server. + /// + public bool HasMore { get; set; } + + /// + /// ID of temporary cursor created on the server (optional). + /// + public string Id { get; set; } + } +} From 9b9607273cdcec025b3ce0b1c91693b3e29b696a Mon Sep 17 00:00:00 2001 From: Ross Mills Date: Wed, 3 Jan 2024 13:06:23 +0000 Subject: [PATCH 2/2] Update CursorApiClient.cs - removed unwanted blank line --- arangodb-net-standard/CursorApi/CursorApiClient.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arangodb-net-standard/CursorApi/CursorApiClient.cs b/arangodb-net-standard/CursorApi/CursorApiClient.cs index 920d938f..385161dd 100644 --- a/arangodb-net-standard/CursorApi/CursorApiClient.cs +++ b/arangodb-net-standard/CursorApi/CursorApiClient.cs @@ -152,7 +152,6 @@ public virtual async Task> PostCursorAsync( /// Optional. The stream transaction Id. /// A CancellationToken to observe while waiting for the task to complete or to cancel the task. /// - public virtual async Task PostCursorAsync( string query, Dictionary bindVars = null, @@ -271,4 +270,4 @@ public virtual async Task> PostAdvanceCursorAsync(string cu } } } -} \ No newline at end of file +}