Bisjob
Bisjob

Reputation: 828

Azure Durable Orchestration - LockAsync

I'm trying to make some locking operations in an Azure durable orchestration. But I can't figure out how to lock entities.

Lets consider this simple example :

public class Function1
{
    [FunctionName(nameof(RunLockOrchestratorHttp))]
    public async Task<IActionResult> RunLockOrchestratorHttp(
        [HttpTrigger(AuthorizationLevel.Function, "post", Route = "RunLockOrchestratorHttp")] HttpRequest req,
        [DurableClient] IDurableOrchestrationClient starter)
    {
        string id = await starter.StartNewAsync(nameof(LockOrchestrator), null, "two");
        return new OkObjectResult($"LockOrchestrator started with id {id}");
    }

    [FunctionName(nameof(LockOrchestrator))]
    public async Task LockOrchestrator([OrchestrationTrigger] IDurableOrchestrationContext context)
    {
        var ctx = context.GetInput<string>();

        Console.WriteLine($"LockOrchestrator {context.InstanceId} with context {ctx} : START");

        // Create a locker according to context
        var entity = new EntityId(nameof(LockOrchestrator), ctx);
        using (var locker = await context.LockAsync(entity))
        {
            // Never enter here
            Console.WriteLine($"LockOrchestrator {context.InstanceId} : lock {entity.EntityName}_{entity.EntityKey} obtained");
            await context.CallActivityAsync(nameof(Activity), ctx);
        }
        Console.WriteLine($"LockOrchestrator {context.InstanceId} : lock {entity.EntityName}_{entity.EntityKey} released");
    }

    public async Task Activity([ActivityTrigger] string ctx)
    {
        switch (ctx)
        {
            case "one":
                Console.WriteLine($"Activity : wait one");
                await Task.Delay(10000);
                break;
            case "two":
                Console.WriteLine($"Activity : wait two");
                await Task.Delay(20000);
                break;
            default:
                Console.WriteLine($"Activity : wait default");
                await Task.Delay(1000);
                break;
        }
    }
}

When I run this code, I can see the log

LockOrchestrator e0c1698674a14b8191faabb7fd3eca69 with context two : START

But then nothing, I never enter in the using{} statement, where I put the comment // Never enter here

What am I missing ?

Thanks in advance !

Upvotes: 0

Views: 1640

Answers (1)

MeDeveloper
MeDeveloper

Reputation: 196

I see you are trying to lock an entity however, I don't see a definition for that entity. You'll have to define either class based or function based entity first.

For example, if you define an entity class called Counter your code will work.

[JsonObject(MemberSerialization.OptIn)]
public class Counter
{
    [JsonProperty("value")]
    public int Value { get; set; }

    [FunctionName(nameof(Counter))]
    public static Task Run([EntityTrigger] IDurableEntityContext ctx)
        => ctx.DispatchAsync<Counter>();
}

Instantiate your entity as:

 // Create a locker according to context
    var entity = new EntityId("Counter", ctx);

Also, add FunctionName annotation for your activity function to avoid run time error.

[FunctionName("Activity")]
public async Task Activity([ActivityTrigger] string ctx)

Now this is just an example for entity class. Define entity class based on your needs and try it out.

You may want to read more on durable entities here https://learn.microsoft.com/en-us/azure/azure-functions/durable/durable-functions-dotnet-entities

Upvotes: 2

Related Questions