Skip to content

Commit

Permalink
feat: dictionary increment stub (#143)
Browse files Browse the repository at this point in the history
This introduces a stub command and response object for
`DictionaryIncrement`. A user interacts with a numeric dictionary
value using `DictionaryIncrementAsync`. Additionally a user may reset,
set, or get values using the normal `DictionarySet` and
`DictionaryGet` commands, operating on string representations of
integers.

See the documentation for `DictionaryIncrementAsync` for examples.
  • Loading branch information
malandis authored Sep 9, 2022
1 parent 18502cc commit a7b7bc9
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
namespace Momento.Sdk.Incubating.Responses;

public enum CacheDictionaryIncrementStatus
{
OK,
PARSE_ERROR
}

public class CacheDictionaryIncrementResponse
{
public CacheDictionaryIncrementStatus Status { get; private set; }
public long? Value { get; private set; }

public CacheDictionaryIncrementResponse()
{
Status = CacheDictionaryIncrementStatus.OK;
Value = 42;
}
}
47 changes: 47 additions & 0 deletions src/Momento.Sdk/Incubating/SimpleCacheClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,53 @@ public async Task<CacheDictionarySetBatchResponse> DictionarySetBatchAsync(strin
return await this.dataClient.DictionarySetBatchAsync(cacheName, dictionaryName, items, refreshTtl, ttlSeconds);
}

/// <summary>
/// <para>Add an integer quantity to a dictionary value.</para>
///
/// <para>Incrementing the value of a missing field sets the value to <paramref name="amount"/>.</para>
/// <para>Incrementing a value that is not an integer or not the string representation of an integer
/// results in <see cref="CacheDictionaryIncrementResponse.Status"/> equal to <see cref="CacheDictionaryIncrementStatus.PARSE_ERROR"/>.</para>
/// </summary>
/// <inheritdoc cref="DictionarySetAsync(string, string, byte[], byte[], bool, uint?)" path="remark"/>
/// <param name="cacheName">Name of the cache to store the dictionary in.</param>
/// <param name="dictionaryName">The dictionary to set.</param>
/// <param name="field"></param>
/// <param name="refreshTtl">Update the dictionary TTL if the dictionary already exists.</param>
/// <param name="amount">The quantity to add to the value. May be positive, negative, or zero. Defaults to 1.</param>
/// <param name="ttlSeconds">TTL for the dictionary in cache. This TTL takes precedence over the TTL used when initializing a cache client. Defaults to client TTL.</param>
/// <returns>Task representing the result of the cache operation.</returns>
/// <exception cref="NotImplementedException">This method is a stub. Do not invoke.</exception>
/// <exception cref="ArgumentNullException">Any of <paramref name="cacheName"/>, <paramref name="dictionaryName"/>, <paramref name="field"/> is <see langword="null"/>.</exception>
/// <example>
/// The following illustrates a typical workflow:
/// <code>
/// var response = client.DictionaryIncrementAsync("my cache", "my dictionary", "counter", amount: 42, refreshTtl: false);
/// Console.WriteLine($"Current value is {response.Value}");
///
/// // Reset the counter. Note we use the string representation of an integer.
/// client.DictionarySetAsync("my cache", "my dictionary", "counter", "0", refreshTtl: false);
///
/// // Retrieve the counter. The integer is represented as a string.
/// var response = client.DictionaryGetAsync("my cache", "my dictionary", "counter");
/// Console.WriteLine(response.String());
///
/// // Here we try incrementing a value that isn't an integer. This results in an error.
/// client.DictionarySetAsync("my cache", "my dictionary", "counter", "0123ABC", refreshTtl: false);
/// var response = client.DictionaryIncrementAsync("my cache", "my dictionary", "counter", amount: 42, refreshTtl: false);
///
/// // response.Status is PARSE_ERROR and response.Value is null
/// Console.WriteLine($"Status is {response.Status}");
/// </code>
/// </example>
public async Task<CacheDictionaryIncrementResponse> DictionaryIncrementAsync(string cacheName, string dictionaryName, string field, bool refreshTtl, long amount = 1, uint? ttlSeconds = null)
{
Utils.ArgumentNotNull(cacheName, nameof(cacheName));
Utils.ArgumentNotNull(dictionaryName, nameof(dictionaryName));
Utils.ArgumentNotNull(field, nameof(field));

throw new NotImplementedException();
}

/// <summary>
/// Get several values from a dictionary.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,15 @@ public async Task DictionarySetGetAsync_FieldIsByteArrayValueIsByteArray_Refresh
Assert.Equal(value, response.ByteArray);
}

[Theory]
[InlineData(null, "my-dictionary", "field")]
[InlineData("cache", null, "field")]
[InlineData("cache", "my-dictionary", null)]
public async Task DictionaryIncrementAsync_NullChecksFieldIsString_ThrowsException(string cacheName, string dictionaryName, string field)
{
await Assert.ThrowsAsync<ArgumentNullException>(async () => await client.DictionaryIncrementAsync(cacheName, dictionaryName, field, refreshTtl: true));
}

[Theory]
[InlineData(null, "my-dictionary", "my-field")]
[InlineData("cache", null, "my-field")]
Expand Down

0 comments on commit a7b7bc9

Please sign in to comment.