dotnet / orleans

Cloud Native application framework for .NET

Home Page:https://docs.microsoft.com/dotnet/orleans

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Distributed Sagas implementation?

asterius1 opened this issue · comments

Distributed Sagas seems like a very good fit in Orleans and viable alternative to Transactions.

talk on Distributed Sagas by Caitie McCaffrey

So far I haven't seen any open source implementation (orleans or not) see @cryeke's tweet

Do you know of any implementation that is or plans to be open source?
Also are there any plans of adding Distributed Sagas to Orleans?

I think there's space for both, as transactions are designed to solve short term consistency issues, where sagas are designed for more longer running tasks.

I've open sourced my scratch pad on sagas here: https://github.com/creyke/Orleans.Sagas

My thoughts so far:

  • Sagas seem to fit virtual actors well... it seems logical (as one option) for an individual actor instance to persist it's own saga state, and therefore for a saga to be represented as a grain, rather than as some other construct.
  • Activities would maybe not be grains, but rather have access to other grains.
  • A pool of reminder grains would need to keep these saga grains alive until they have completed or fully compensated (not in sample currently).

@creyke I'm not sure why you need a reminder pool? The reminder service itself is fully sharded storage-wise (you can shard underlying storage) and distributed across silos (over a grain key space). Trying to build such a reminder pool will be a venture similar to building an Orleans reminder service.

Just want to hear comments from Orleans team on reminders scalablity when using Azure storage as I'm under impression that reminder service (when properly sharded) can easily handle 100K reminders per second (respecting azure limits of course)

That makes things a lot easier. So the saga execution controller doesn't need to be centralised... each grain can take care of itself.

I'm experimenting with a builder pattern... trying to work out the application level programming model first...

// returns a builder.
var saga = GrainFactory.CreateSaga();

// can now access and store a unique id (Guid) if required for later reference.
var id = saga.Id;

// adding activities locally.
saga.AddActivity<BookHireCarActivity>(new BookHireCarConfig());
saga.AddActivity<BookHotelActivity>(new BookHotelConfig());
saga.AddActivity<BookPlaneActivity>(new BookPlaneConfig());

// idempotent; submits the activities to a saga grain and awaits a response the saga has been registered.
await saga.Execute();

Justification being the activities type information, and associated configuration instances will need to be persisted in the grain's state (in case of a failure), so to minimise failure points, the execution should arguably serialize these locally and submit them as a payload to the SagaGrain. A reference to the Saga Grain itself could still be created manually to check progress (if required).

Updated after a review from @ReubenBond - thanks!

All recommendations here taken on board with exception of the latter discussion regarding generics etc which probably requires a bit more thought before there's a clear route forward.

After my "investigations", I'm confident no changes to the Orleans runtime or framework would be required to support sagas. Orleans already offers all of the main functionality required. Therefore I would recommend keeping it as a library, and I'm happy to continue supporting it / moving it forward.

I'd recommend closing this, and then raising requirements as issues on Orleans.Sagas.