Skip to content
10 changes: 5 additions & 5 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ jobs:
- run:
name: Test
command:
dotnet test -c Release --filter Feature!=StreamTransaction
dotnet test -c Release --filter "Feature!=StreamTransaction&RunningMode!=Cluster"

"test-arangodb-3_5":
working_directory: ~/arangodb-net-standard
Expand All @@ -77,7 +77,7 @@ jobs:
- run:
name: Test
command:
dotnet test -c Release
dotnet test -c Release --filter RunningMode!=Cluster

"test-arangodb-3_6":
working_directory: ~/arangodb-net-standard
Expand All @@ -96,7 +96,7 @@ jobs:
- run:
name: Test
command:
dotnet test -c Release
dotnet test -c Release --filter RunningMode!=Cluster

"test-arangodb-3_7":
working_directory: ~/arangodb-net-standard
Expand All @@ -115,7 +115,7 @@ jobs:
- run:
name: Test
command:
dotnet test -c Release
dotnet test -c Release --filter RunningMode!=Cluster

"test-arangodb-3_8":
working_directory: ~/arangodb-net-standard
Expand All @@ -134,4 +134,4 @@ jobs:
- run:
name: Test
command:
dotnet test -c Release
dotnet test -c Release --filter RunningMode!=Cluster
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@ public CollectionApiClientTest(CollectionApiClientTestFixture fixture)
_adb = fixture.ArangoDBClient;
_collectionApi = _adb.Collection;
_testCollection = fixture.TestCollection;


}

public async Task InitializeAsync()
Expand Down Expand Up @@ -471,5 +469,65 @@ public async Task GetCollectionFiguresAsync_ShouldThrow_WhenCollectionNotFound()
});
Assert.Equal(HttpStatusCode.NotFound, exception.ApiError.Code);
}




[Fact]
public async Task GetChecksumAsync_ShouldSucceed()
{
var res = await _collectionApi.GetChecksumAsync(_testCollection);
Assert.NotNull(res.Checksum);
}

[Fact]
public async Task LoadIndexesIntoMemoryAsync_ShouldSucceed()
{
var res = await _collectionApi.PutLoadIndexesIntoMemoryAsync(_testCollection);
Assert.True(res.Result);
}

[Fact]
public async Task RecalculateCountAsync_ShouldSucceed()
{
var res = await _collectionApi.PutRecalculateCountAsync(_testCollection);
Assert.True(res.Result);
}

/// <summary>
/// This test will run only in a cluster
/// </summary>
/// <returns></returns>
[Fact]
[Trait("RunningMode", "Cluster")]
public async Task GetCollectionShardsAsync_ShouldSucceed()
{
var res = await _collectionApi.GetCollectionShardsAsync(_testCollection);
Assert.Equal(HttpStatusCode.OK, res.Code);
}

/// <summary>
/// This test will run only in a cluster
/// </summary>
/// <returns></returns>
[Fact]
[Trait("RunningMode", "Cluster")]
public async Task GetCollectionShardsWithDetailsAsync_ShouldSucceed()
{
var res = await _collectionApi.GetCollectionShardsWithDetailsAsync(_testCollection);
Assert.Equal(HttpStatusCode.OK, res.Code);
}

[Fact]
public async Task CompactCollectionDataAsync_ShouldSucceed()
{
var res = await _collectionApi.PutCompactCollectionDataAsync(_testCollection);
Assert.Equal(HttpStatusCode.OK, res.Code);
Assert.NotNull(res.GloballyUniqueId);
}




}
}
199 changes: 198 additions & 1 deletion arangodb-net-standard/CollectionApi/CollectionApiClient.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
using ArangoDBNetStandard.CollectionApi.Models;
using ArangoDBNetStandard.Serialization;
using ArangoDBNetStandard.Transport;
using System;
using System.Collections.Generic;
using System.Net;
using System.Threading.Tasks;

Expand Down Expand Up @@ -267,5 +269,200 @@ public virtual async Task<GetCollectionFiguresResponse> GetCollectionFiguresAsyn
throw await GetApiErrorException(response).ConfigureAwait(false);
};
}

/// <summary>
/// Get the checksum for a specific collection.
/// GET /_api/collection/{collection-name}/checksum
/// </summary>
/// <param name="collectionName">Name of the collection.</param>
/// <param name="query">Query options.</param>
/// <returns></returns>
public virtual async Task<GetChecksumResponse> GetChecksumAsync(string collectionName, GetChecksumQuery query = null)
{
if (string.IsNullOrWhiteSpace(collectionName))
{
throw new ArgumentException($"{nameof(collectionName)} is required", nameof(collectionName));
}
string uriString = _collectionApiPath + "/" + WebUtility.UrlEncode(collectionName) + "/checksum";
if (query != null)
{
uriString += "?" + query.ToQueryString();
}
using (var response = await _transport.GetAsync(uriString).ConfigureAwait(false))
{
if (response.IsSuccessStatusCode)
{
var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
return DeserializeJsonFromStream<GetChecksumResponse>(stream);
}
throw await GetApiErrorException(response).ConfigureAwait(false);
}
}

/// <summary>
/// Load Indexes into Memory.
/// Caches all index entries of this collection into the main memory.
/// Therefore it iterates over all indexes of the collection and
/// stores the indexed values, not the entire document data,
/// in memory.
/// PUT /_api/collection/{collection-name}/loadIndexesIntoMemory
/// </summary>
/// <param name="collectionName">Name of the collection.</param>
/// <returns></returns>
public virtual async Task<PutLoadIndexesIntoMemoryResponse> PutLoadIndexesIntoMemoryAsync(string collectionName)
{
if (string.IsNullOrWhiteSpace(collectionName))
{
throw new ArgumentException($"{nameof(collectionName)} is required", nameof(collectionName));
}
string uriString = _collectionApiPath + "/" + WebUtility.UrlEncode(collectionName) + "/loadIndexesIntoMemory";
using (var response = await _transport.PutAsync(uriString, new byte[] { }).ConfigureAwait(false))
{
if (response.IsSuccessStatusCode)
{
var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
return DeserializeJsonFromStream<PutLoadIndexesIntoMemoryResponse>(stream);
}
throw await GetApiErrorException(response).ConfigureAwait(false);
}
}

/// <summary>
/// Recalculates the document count of a collection.
/// PUT /_api/collection/{collection-name}/recalculateCount
/// </summary>
/// <param name="collectionName">Name of the collection.</param>
/// <returns></returns>
public virtual async Task<PutRecalculateCountResponse> PutRecalculateCountAsync(string collectionName)
{
if (string.IsNullOrWhiteSpace(collectionName))
{
throw new ArgumentException($"{nameof(collectionName)} is required", nameof(collectionName));
}
string uriString = _collectionApiPath + "/" + WebUtility.UrlEncode(collectionName) + "/recalculateCount";
using (var response = await _transport.PutAsync(uriString, new byte[] { }).ConfigureAwait(false))
{
if (response.IsSuccessStatusCode)
{
var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
return DeserializeJsonFromStream<PutRecalculateCountResponse>(stream);
}
throw await GetApiErrorException(response).ConfigureAwait(false);
}
}

/// <summary>
/// Returns the responsible shard for a document.
/// This method is only available in a cluster.
/// PUT /_api/collection/{collection-name}/responsibleShard
/// </summary>
/// <param name="collectionName">Name of the collection.</param>
/// <param name="body">
/// Body of the request consisting of key/value
/// pairs with at least the collection’s shard
/// key attributes set to some values.
/// </param>
/// <returns></returns>
public virtual async Task<PutDocumentShardResponse> PutDocumentShardAsync(string collectionName, Dictionary<string, object> body)
{
if (string.IsNullOrWhiteSpace(collectionName))
{
throw new ArgumentException($"{nameof(collectionName)} is required", nameof(collectionName));
}
if (body == null || body.Count < 1)
{
throw new ArgumentException($"{nameof(body)} is required", nameof(body));
}
string uriString = _collectionApiPath + "/" + WebUtility.UrlEncode(collectionName) + "/responsibleShard";
var content = GetContent(body, new ApiClientSerializationOptions(true, true));
using (var response = await _transport.PutAsync(uriString, content).ConfigureAwait(false))
{
if (response.IsSuccessStatusCode)
{
var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
return DeserializeJsonFromStream<PutDocumentShardResponse>(stream);
}
throw await GetApiErrorException(response).ConfigureAwait(false);
}
}

/// <summary>
/// Returns the shard ids of a collection.
/// This method is only available in a cluster Coordinator.
/// GET /_api/collection/{collection-name}/shards
/// </summary>
/// <param name="collectionName">Name of the collection.</param>
/// <returns></returns>
public virtual async Task<GetCollectionShardsResponse> GetCollectionShardsAsync(string collectionName)
{
if (string.IsNullOrWhiteSpace(collectionName))
{
throw new ArgumentException($"{nameof(collectionName)} is required", nameof(collectionName));
}
string uriString = _collectionApiPath + "/" + WebUtility.UrlEncode(collectionName) + "/shards";
using (var response = await _transport.GetAsync(uriString).ConfigureAwait(false))
{
if (response.IsSuccessStatusCode)
{
var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
return DeserializeJsonFromStream<GetCollectionShardsResponse>(stream);
}
throw await GetApiErrorException(response).ConfigureAwait(false);
}
}

/// <summary>
/// Returns the shard ids of a collection.
/// This method is only available in a cluster Coordinator.
/// The response also contains shard IDs as object attribute
/// keys, and the responsible servers for each shard mapped
/// to them. The leader shards will be first in the arrays.
/// GET /_api/collection/{collection-name}/shards?details=true
/// </summary>
/// <param name="collectionName">Name of the collection.</param>
/// <returns></returns>
public virtual async Task<GetCollectionShardsDetailedResponse> GetCollectionShardsWithDetailsAsync(string collectionName)
{
if (string.IsNullOrWhiteSpace(collectionName))
{
throw new ArgumentException($"{nameof(collectionName)} is required", nameof(collectionName));
}
string uriString = _collectionApiPath + "/" + WebUtility.UrlEncode(collectionName) + "/shards?details=true";
using (var response = await _transport.GetAsync(uriString).ConfigureAwait(false))
{
if (response.IsSuccessStatusCode)
{
var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
return DeserializeJsonFromStream<GetCollectionShardsDetailedResponse>(stream);
}
throw await GetApiErrorException(response).ConfigureAwait(false);
}
}

/// <summary>
/// Compacts the data of a collection in order to reclaim disk space.
/// The operation will compact the document and index data by rewriting
/// the underlying .sst files and only keeping the relevant entries.
/// PUT /_api/collection/{collection-name}/compact
/// </summary>
/// <param name="collectionName">Name of the collection.</param>
/// <returns></returns>
public virtual async Task<PutCompactCollectionDataResponse> PutCompactCollectionDataAsync(string collectionName)
{
if (string.IsNullOrWhiteSpace(collectionName))
{
throw new ArgumentException($"{nameof(collectionName)} is required", nameof(collectionName));
}
string uriString = _collectionApiPath + "/" + WebUtility.UrlEncode(collectionName) + "/compact";
using (var response = await _transport.PutAsync(uriString, new byte[] { }).ConfigureAwait(false))
{
if (response.IsSuccessStatusCode)
{
var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
return DeserializeJsonFromStream<PutCompactCollectionDataResponse>(stream);
}
throw await GetApiErrorException(response).ConfigureAwait(false);
}
}
}
}
}
Loading