Waiting for durable entity value to change

1.2k views Asked by At
[FunctionName("SetDurable")]
public static async Task<HttpResponseMessage> SetDurable(
        [HttpTrigger(AuthorizationLevel.Function, "get", Route = "SetDurable/{durable}")] HttpRequestMessage req,
        [DurableClient] IDurableEntityClient client,
        string durable)
        {
           var entityId = new EntityId(DurableEntitiesNames.BirSessionIdentificatorEntity, DurableEntitiesNames.BirSessionIdentificatorKey);
           await client.SignalEntityAsync<IBirSessionIdentificator>(entityId, identificator => identificator.Set(durable) );
           //await Task.Delay(2000);
           EntityStateResponse<JObject> stateResponse = await client.ReadEntityStateAsync<JObject>(entityId);
           var setResult = stateResponse.EntityState.ToObject<BirSessionIdentificatorResult>().Sid;
           return new HttpResponseMessage(HttpStatusCode.OK){Content = new StringContent($"{setResult}")};
    }
    

In Azure Functions v3 when i try to set the value of durable entity and then immediately try to read this value, it returns old value instead of the new value. But when i uncomment the Task.Delay and make it wait 2 seconds after setting the value of durable entity i get correct value while trying to read it.

Is there any way to await the completion of durable entity value setting operation?

1

There are 1 answers

5
Peter Bons On

Is there any way to await the completion of durable entity value setting operation?

No, at least not when using SignalEntityAsync. See the docs:

It's important to understand that the "signals" sent from the client are simply enqueued, to be processed asynchronously at a later time. In particular, the SignalEntityAsync usually returns before the entity even starts the operation, and it is not possible to get back the return value or observe exceptions. If stronger guarantees are required (e.g. for workflows), orchestrator functions should be used, which can wait for entity operations to complete, and can process return values and observe exceptions.

The bold part is your way out: you can use a proxy from within an orchestration to get access to the durable entity. That way you can await the operation. An example:

[FunctionName("DeleteCounter")]
public static async Task<HttpResponseMessage> DeleteCounter(
    [HttpTrigger(AuthorizationLevel.Function, "delete", Route = "Counter/{entityKey}")] HttpRequestMessage req,
    [DurableClient] IDurableEntityClient client,
    string entityKey)
{
    var entityId = new EntityId("Counter", entityKey);
    await client.SignalEntityAsync<ICounter>(entityId, proxy => proxy.Delete());    
    return req.CreateResponse(HttpStatusCode.Accepted);
}

here we await the call of the Delete method on the entity.