protected override async Task ProcessMessage(Message <string, string> message) { var @event = GrainStateModifyingEvent.Deserialize(message.Value); if (GrainProviders.TryGetValue(@event.GrainType, out var provider)) { var grain = (IStateProjectorGrain)provider(GrainFactory, @event.GrainKey); await _waitPolicy.ExecuteAsync( async (cancellationToken, context) => { var currentVersion = await grain.GetCurrentVersionAsync(); return(currentVersion == @event.GrainVersion); }, new Dictionary <string, object> { { EventTypeContextKey, nameof(GrainStateModifyingEvent) }, { GrainTypeContextKey, @event.GrainType }, { GrainKeyContextKey, @event.GrainKey }, { GrainVersionContextKey, @event.GrainVersion }, }, CancellationToken.None, true); await grain.ProjectStateAsync(); } else { throw new ApplicationException( $"Unknown grain type {@event.GrainType} used in {nameof(GrainStateModifyingEvent)}. " + $"Please check {nameof(DataProjectionDispatchingGrain)} configuration."); } }
public async Task Invoke(IIncomingGrainCallContext context) { var attribute = context.ImplementationMethod.GetCustomAttribute <StateModificationAttribute>(); if (attribute != null) { if (context.Grain is IStateProjectorGrain stateProjectorGrain) { var grainType = context.ImplementationMethod.DeclaringType.FullName; var grainKey = context.Grain.GetPrimaryKeyLong(); var grainVersion = await stateProjectorGrain.GetCurrentVersionAsync(); var @event = new GrainStateModifyingEvent(grainType, grainKey, grainVersion); var message = @event.Serialize(); var messageKey = $"{grainType}|{grainKey}"; await _messageSender.SendAsync(_kafkaOptions.DataProjectionDispatchingTopic, messageKey, message); } } await context.Invoke(); }