orleans: Support returning IAsyncObservable from Grain methods

This is a feature request. I may implement it, but I am looking for input before I make an attempt.

Currently, Grains can return Task & Task<T> to consumers. This represents the asynchronous nature of distributed systems programming well and encapsulates the possibility of failure. Task<T> is restricted to returning only a single value, though.

Ideally, Grains should be able to return IObservable<T> or IAsyncObservable<T> (depending on whether or not back-pressure/ack is required) in addition to Task & Task<T>.

This differs from the Virtual Streams offered by Orleans in a few ways:

  1. Observables are temporary (like tasks), Streams are eternal (like grains)
  2. Observables are 1:1 by default, Streams may be many:many
  3. Observables can take parameters, Streams are identified by (type, key).

Semantics:

  • Observable methods are invoked on SubscribeAsync, not when the client obtains the IAsyncObservable<T>.
  • Silo failures are propagated to observers through OnErrorAsync. Clients can at that point re-SubscribeAsync, at which point the grain method is invoked again.

Any obvious issues which aren’t covered here?

Input is be greatly appreciated 😃

About this issue

  • Original URL
  • State: closed
  • Created 9 years ago
  • Comments: 18 (18 by maintainers)

Commits related to this issue

Most upvoted comments

I want to be able to return physical streams: streams which will break when the grain is deactivated, forcing the user to resubscribe in order to continue receiving values.

For example, I might want to return results to a search query from the grain. Eg, imagine I have an IChatRoomGrain and I want to return only messages which satisfy a custom query, for example, messages which contain the user’s name. The client can include the last known messageId in the request to ensure they don’t miss anything.

More generally when Bonsai is released, I want methods which take an expression, apply it to a stream (eg, traffic reports), and return the resulting stream.

Does that sound like desirable functionality to you?

Just to be clear again: we can, now, without any changes, return from the grain method Task<IAsyncStream<T>>, and since IAsyncStream<T> is also IAsyncObservable<T>, we can return Task<IAsyncObservable<T>>. So we already support “returning streams of values”.

@ReubenBond is asking for more. As I understood, he is asking for syntactic sugar of returning IAsyncObservable<T> instead of Task<IAsyncStream<T>> and being able to subscribe to the returned IAsyncObservable immediately, without first awaiting the Task.