Share queue with two or more stateful services within Service Fabric

580 views Asked by At

Is it possible to share a queue between 2 or more stateful services, or do I need to directly call it via tcp/http to put a message on its own internal queue?

For example; say I have my first service that puts an order on a queue based on a condition:

public sealed class Service1 : StatefulService
{
    public Service1(StatefulServiceContext context, IReliableStateManagerReplica reliableStateManagerReplica)
        : base(context, reliableStateManagerReplica)
    { }

    protected override async Task RunAsync(CancellationToken cancellationToken)
    {
        var customerQueue = await this.StateManager.GetOrAddAsync<IReliableQueue<Order>>("orders");

        while (true)
        {
            cancellationToken.ThrowIfCancellationRequested();

            using (var tx = this.StateManager.CreateTransaction())
            {
                if (true /* some logic here */)
                {
                    await customerQueue.EnqueueAsync(tx, new Order());
                }

                await tx.CommitAsync();
            }
        }
    }
}

Then my second service reads from that queue and then continues the processing.

public sealed class Service2 : StatefulService
{
    public Service2(StatefulServiceContext context, IReliableStateManagerReplica reliableStateManagerReplica)
        : base(context, reliableStateManagerReplica)
    { }

    protected override async Task RunAsync(CancellationToken cancellationToken)
    {
        var customerQueue = await this.StateManager.GetOrAddAsync<IReliableQueue<Order>>("orders");

        while (true)
        {
            cancellationToken.ThrowIfCancellationRequested();

            using (var tx = this.StateManager.CreateTransaction())
            {
                var value = await customerQueue.TryDequeueAsync(tx);
                if (value.HasValue)
                {
                    // Continue processing the order.
                }

                await tx.CommitAsync();
            }
        }
    }
}

I can't see much within the documentation on this, I can see that GetOrAddAsync method can take in a uri but I've seen no examples on how this works or if you can even do cross services?

The idea behind this is to split up the processing on to separate queues so that we don't get in a inconsistent state when we try to re-try a message.

1

There are 1 answers

1
LoekD On BEST ANSWER

There's no way to share state across services. The statemanager acts on a service partition level.

You could use an external queue for this purpose, like Service Bus.

You could also invert control, by using an Event Driven approach. Service 1 would raise an event, that Service 2 would use as a trigger to continue processing. The data to process could be inside the event, or data stored in another location, referenced to from the event.