Search code examples
orleans

Create stream and grain with the same name in Orleans


I have a grain using a string key. I want this grain to have reference to the stream with the same name.

public class StreamGrain : Grain, IGrainWithStringKey
{
  protected IAsyncStream<IPointModel> _dataStream = null;
  protected IAsyncStream<ITransactionModel> _actionStream = null;

  public override Task OnActivateAsync()
  {
    var identity = this.GetPrimaryKey(); // this.GetPrimaryKeyString();
    var streamProvider = GetStreamProvider("Inputs");

    _dataStream = streamProvider.GetStream<IPointModel>(identity, "Points");
    _actionStream = streamProvider.GetStream<ITransactionModel>(identity, "Transactions");

    return base.OnActivateAsync();
  }
}

Meanwhile, when I try to connect the grain with the stream using GetPrimaryKey, I'm getting this error because grain is using a string as a key, not GUID. At the same time, seems that streams in Orleans can be referenced only by GUID. So, there is no way to call a grain and related stream using the same name.

The question

How can I connect a grain and a stream using the same name? In other words, no matter how many times a grain was activated or deactivated, I want to get the reference to the same stream.


Solution

  • Looks like at the moment streams in Orleans can be referenced only by GUID. Orleans team mentioned that ability to give string names to streams may be added in the next release. For now, here is the hacky way of matching string grain name with stream's GUID.

    String => MD5 => GUID
    
    public override Task OnActivateAsync()
    {
      using (var provider = MD5.Create())
      {
        var name = this.GetPrimaryKeyString();
        var streamProvider = GetStreamProvider(nameof(NameEnum.Inputs));
        var identity = new Guid(provider.ComputeHash(Encoding.ASCII.GetBytes(name)));
    
        _dataStream = streamProvider.GetStream<IPointModel>(identity, nameof(NameEnum.Points));
        _actionStream = streamProvider.GetStream<ITransactionModel>(identity, nameof(NameEnum.Transactions));
      }
    
      return base.OnActivateAsync();
    }
    

    Feel free to suggest anything better.