Skip to content

Commit

Permalink
Use TimeSpan instead of int seconds, and only expose TTLExpireTime in
Browse files Browse the repository at this point in the history
change metadata

Signed-off-by: joshvanl <me@joshvanl.dev>
  • Loading branch information
JoshVanL committed Oct 17, 2023
1 parent f3866e7 commit ea9999b
Show file tree
Hide file tree
Showing 8 changed files with 46 additions and 68 deletions.
4 changes: 2 additions & 2 deletions examples/Actor/ActorClient/Program.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// ------------------------------------------------------------------------
// ------------------------------------------------------------------------
// Copyright 2021 The Dapr Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -47,7 +47,7 @@ public static async Task Main(string[] args)
var proxy = ActorProxy.Create<IDemoActor>(actorId, "DemoActor");

Console.WriteLine("Making call using actor proxy to save data.");
await proxy.SaveData(data);
await proxy.SaveData(data, TimeSpan.FromMinutes(10));
Console.WriteLine("Making call using actor proxy to get data.");
var receivedData = await proxy.GetData();
Console.WriteLine($"Received data is {receivedData}.");
Expand Down
8 changes: 4 additions & 4 deletions examples/Actor/DemoActor/DemoActor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,12 @@ public DemoActor(ActorHost host, BankService bank)
this.bank = bank;
}

public async Task SaveData(MyData data, int? ttlInSeconds = null)
public async Task SaveData(MyData data, TimeSpan ttl)
{
Console.WriteLine($"This is Actor id {this.Id} with data {data}.");

// Set State using StateManager, state is saved after the method execution.
await this.StateManager.SetStateAsync<MyData>(StateName, data, ttlInSeconds: ttlInSeconds);
await this.StateManager.SetStateAsync<MyData>(StateName, data, ttl);
}

public Task<MyData> GetData()
Expand Down Expand Up @@ -100,7 +100,7 @@ public async Task ReceiveReminderAsync(string reminderName, byte[] state, TimeSp
// This method is invoked when an actor reminder is fired.
var actorState = await this.StateManager.GetStateAsync<MyData>(StateName);
actorState.PropertyB = $"Reminder triggered at '{DateTime.Now:yyyy-MM-ddTHH:mm:ss}'";
await this.StateManager.SetStateAsync<MyData>(StateName, actorState, ttlInSeconds: 360);
await this.StateManager.SetStateAsync<MyData>(StateName, actorState, ttl: TimeSpan.FromMinutes(5));
}

class TimerParams
Expand Down Expand Up @@ -164,7 +164,7 @@ public async Task TimerCallback(byte[] data)
{
var state = await this.StateManager.GetStateAsync<MyData>(StateName);
state.PropertyA = $"Timer triggered at '{DateTime.Now:yyyyy-MM-ddTHH:mm:s}'";
await this.StateManager.SetStateAsync<MyData>(StateName, state, ttlInSeconds: 360);
await this.StateManager.SetStateAsync<MyData>(StateName, state, ttl: TimeSpan.FromMinutes(5));
var timerParams = JsonSerializer.Deserialize<TimerParams>(data);
Console.WriteLine("Timer parameter1: " + timerParams.IntParam);
Console.WriteLine("Timer parameter2: " + timerParams.StringParam);
Expand Down
4 changes: 2 additions & 2 deletions examples/Actor/IDemoActor/IDemoActor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ public interface IDemoActor : IActor
/// Method to save data.
/// </summary>
/// <param name="data">DAta to save.</param>
/// <param name="ttlInSeconds">Optional TTL in seconds.</param>
/// <param name="ttl">TTL of state key.</param>
/// <returns>A task that represents the asynchronous save operation.</returns>
Task SaveData(MyData data, int? ttlInSeconds = null);
Task SaveData(MyData data, TimeSpan ttl);

/// <summary>
/// Method to get data.
Expand Down
23 changes: 0 additions & 23 deletions src/Dapr.Actors/Runtime/ActorStateChange.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,28 +81,5 @@ public ActorStateChange(string stateName, Type type, object value, StateChangeKi
/// If null, the state will not expire.
/// </remarks>
public DateTimeOffset? TTLExpireTime { get; }

/// <summary>
/// Gets the time to live in seconds for the state.
/// </summary>
/// <value>
/// The time to live for the state.
/// </value>
/// <remarks>
/// If null, the state will not expire.
/// </remarks>
public int? TTLInSeconds {
get
{
if (this.TTLExpireTime.HasValue)
{
return (int)Math.Ceiling((this.TTLExpireTime.Value - DateTime.UtcNow).TotalSeconds);
}
else
{
return null;
}
}
}
}
}
44 changes: 22 additions & 22 deletions src/Dapr.Actors/Runtime/ActorStateManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,11 @@ public async Task AddStateAsync<T>(string stateName, T value, CancellationToken
}
}

public async Task AddStateAsync<T>(string stateName, T value, int ttlInSeconds, CancellationToken cancellationToken)
public async Task AddStateAsync<T>(string stateName, T value, TimeSpan ttl, CancellationToken cancellationToken)
{
EnsureStateProviderInitialized();

if (!(await this.TryAddStateAsync(stateName, value, ttlInSeconds, cancellationToken)))
if (!(await this.TryAddStateAsync(stateName, value, ttl, cancellationToken)))
{
throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, SR.ActorStateAlreadyExists, stateName));
}
Expand Down Expand Up @@ -87,7 +87,7 @@ public async Task<bool> TryAddStateAsync<T>(string stateName, T value, Cancellat
return true;
}

public async Task<bool> TryAddStateAsync<T>(string stateName, T value, int ttlInSeconds, CancellationToken cancellationToken = default)
public async Task<bool> TryAddStateAsync<T>(string stateName, T value, TimeSpan ttl, CancellationToken cancellationToken = default)
{
ArgumentVerifier.ThrowIfNull(stateName, nameof(stateName));

Expand All @@ -102,7 +102,7 @@ public async Task<bool> TryAddStateAsync<T>(string stateName, T value, int ttlIn
// Check if the property was marked as remove in the cache
if (stateMetadata.ChangeKind == StateChangeKind.Remove)
{
stateChangeTracker[stateName] = StateMetadata.Create(value, StateChangeKind.Update, ttlInSeconds: ttlInSeconds);
stateChangeTracker[stateName] = StateMetadata.Create(value, StateChangeKind.Update, ttl: ttl);
return true;
}

Expand All @@ -114,7 +114,7 @@ public async Task<bool> TryAddStateAsync<T>(string stateName, T value, int ttlIn
return false;
}

stateChangeTracker[stateName] = StateMetadata.Create(value, StateChangeKind.Add, ttlInSeconds: ttlInSeconds);
stateChangeTracker[stateName] = StateMetadata.Create(value, StateChangeKind.Add, ttl: ttl);
return true;
}

Expand Down Expand Up @@ -156,7 +156,7 @@ public async Task<ConditionalValue<T>> TryGetStateAsync<T>(string stateName, Can
var conditionalResult = await this.TryGetStateFromStateProviderAsync<T>(stateName, cancellationToken);
if (conditionalResult.HasValue)
{
stateChangeTracker.Add(stateName, StateMetadata.Create(conditionalResult.Value.Value, StateChangeKind.None, conditionalResult.Value.TTLExpireTime));
stateChangeTracker.Add(stateName, StateMetadata.Create(conditionalResult.Value.Value, StateChangeKind.None, ttlExpireTime: conditionalResult.Value.TTLExpireTime));
}

return new ConditionalValue<T>(false, default);
Expand Down Expand Up @@ -191,7 +191,7 @@ public async Task SetStateAsync<T>(string stateName, T value, CancellationToken
}
}

public async Task SetStateAsync<T>(string stateName, T value, int ttlInSeconds, CancellationToken cancellationToken)
public async Task SetStateAsync<T>(string stateName, T value, TimeSpan ttl, CancellationToken cancellationToken)
{
ArgumentVerifier.ThrowIfNull(stateName, nameof(stateName));

Expand All @@ -212,11 +212,11 @@ public async Task SetStateAsync<T>(string stateName, T value, int ttlInSeconds,
}
else if (await this.actor.Host.StateProvider.ContainsStateAsync(this.actorTypeName, this.actor.Id.ToString(), stateName, cancellationToken))
{
stateChangeTracker.Add(stateName, StateMetadata.Create(value, StateChangeKind.Update, ttlInSeconds: ttlInSeconds));
stateChangeTracker.Add(stateName, StateMetadata.Create(value, StateChangeKind.Update, ttl: ttl));
}
else
{
stateChangeTracker[stateName] = StateMetadata.Create(value, StateChangeKind.Add, ttlInSeconds: ttlInSeconds);
stateChangeTracker[stateName] = StateMetadata.Create(value, StateChangeKind.Add, ttl: ttl);
}
}

Expand Down Expand Up @@ -306,7 +306,7 @@ public async Task<T> GetOrAddStateAsync<T>(string stateName, T value, Cancellati
return value;
}

public async Task<T> GetOrAddStateAsync<T>(string stateName, T value, int ttlInSeconds, CancellationToken cancellationToken)
public async Task<T> GetOrAddStateAsync<T>(string stateName, T value, TimeSpan ttl, CancellationToken cancellationToken)
{
EnsureStateProviderInitialized();

Expand All @@ -320,7 +320,7 @@ public async Task<T> GetOrAddStateAsync<T>(string stateName, T value, int ttlInS
var changeKind = this.IsStateMarkedForRemove(stateName) ? StateChangeKind.Update : StateChangeKind.Add;

var stateChangeTracker = GetContextualStateTracker();
stateChangeTracker[stateName] = StateMetadata.Create(value, changeKind, ttlInSeconds: ttlInSeconds);
stateChangeTracker[stateName] = StateMetadata.Create(value, changeKind, ttl: ttl);
return value;
}

Expand Down Expand Up @@ -375,7 +375,7 @@ public async Task<T> AddOrUpdateStateAsync<T>(
string stateName,
T addValue,
Func<string, T, T> updateValueFactory,
int ttlInSeconds,
TimeSpan ttl,
CancellationToken cancellationToken = default)
{
ArgumentVerifier.ThrowIfNull(stateName, nameof(stateName));
Expand All @@ -391,7 +391,7 @@ public async Task<T> AddOrUpdateStateAsync<T>(
// Check if the property was marked as remove in the cache
if (stateMetadata.ChangeKind == StateChangeKind.Remove)
{
stateChangeTracker[stateName] = StateMetadata.Create(addValue, StateChangeKind.Update, ttlInSeconds: ttlInSeconds);
stateChangeTracker[stateName] = StateMetadata.Create(addValue, StateChangeKind.Update, ttl: ttl);
return addValue;
}

Expand All @@ -410,12 +410,12 @@ public async Task<T> AddOrUpdateStateAsync<T>(
if (conditionalResult.HasValue)
{
var newValue = updateValueFactory.Invoke(stateName, conditionalResult.Value.Value);
stateChangeTracker.Add(stateName, StateMetadata.Create(newValue, StateChangeKind.Update, ttlInSeconds: ttlInSeconds));
stateChangeTracker.Add(stateName, StateMetadata.Create(newValue, StateChangeKind.Update, ttl: ttl));

return newValue;
}

stateChangeTracker[stateName] = StateMetadata.Create(addValue, StateChangeKind.Add, ttlInSeconds: ttlInSeconds);
stateChangeTracker[stateName] = StateMetadata.Create(addValue, StateChangeKind.Add, ttl: ttl);
return addValue;
}

Expand Down Expand Up @@ -529,17 +529,17 @@ private Dictionary<string, StateMetadata> GetContextualStateTracker()

private sealed class StateMetadata
{
private StateMetadata(object value, Type type, StateChangeKind changeKind, DateTimeOffset? ttlExpireTime = null, int? ttlInSeconds = null)
private StateMetadata(object value, Type type, StateChangeKind changeKind, DateTimeOffset? ttlExpireTime = null, TimeSpan? ttl = null)
{
this.Value = value;
this.Type = type;
this.ChangeKind = changeKind;

if (ttlExpireTime.HasValue && ttlInSeconds.HasValue) {
throw new ArgumentException("Cannot specify both TTLExpireTime and TTLInSeconds");
if (ttlExpireTime.HasValue && ttl.HasValue) {
throw new ArgumentException("Cannot specify both TTLExpireTime and TTL");
}
if (ttlInSeconds.HasValue) {
this.TTLExpireTime = DateTime.UtcNow.AddSeconds(ttlInSeconds.Value);
if (ttl.HasValue) {
this.TTLExpireTime = DateTime.UtcNow.Add(ttl.Value);
} else {
this.TTLExpireTime = ttlExpireTime;
}
Expand All @@ -553,9 +553,9 @@ private StateMetadata(object value, Type type, StateChangeKind changeKind, DateT

public DateTimeOffset? TTLExpireTime { get; set; }

public static StateMetadata Create<T>(T value, StateChangeKind changeKind, DateTimeOffset? ttlExpireTime = null, int? ttlInSeconds = null)
public static StateMetadata Create<T>(T value, StateChangeKind changeKind, DateTimeOffset? ttlExpireTime = null, TimeSpan? ttl = null)
{
return new StateMetadata(value, typeof(T), changeKind, ttlExpireTime, ttlInSeconds);
return new StateMetadata(value, typeof(T), changeKind, ttlExpireTime, ttl);
}

public static StateMetadata CreateForRemove()
Expand Down
7 changes: 4 additions & 3 deletions src/Dapr.Actors/Runtime/DaprStateProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -134,10 +134,11 @@ private async Task DoStateChangesTransactionallyAsync(string actorType, string a
JsonSerializer.Serialize(writer, stateChange.Value, stateChange.Type, jsonSerializerOptions);
}

var ttlInSeconds = stateChange.TTLInSeconds;
if (ttlInSeconds.HasValue) {
writer.WriteString("ttlInSeconds", ttlInSeconds.Value.ToString());
if (stateChange.TTLExpireTime.HasValue) {
var ttl = (int)Math.Ceiling((stateChange.TTLExpireTime.Value - DateTime.UtcNow).TotalSeconds);
writer.WriteString("ttlInSeconds", ttl.ToString());
}

break;
default:
break;
Expand Down
Loading

0 comments on commit ea9999b

Please sign in to comment.