public async Task PublishAsync(EventPublishData data, PublishPreferences preferences) { var eventDesc = new EventDescriptor { Service = data.Service, Event = data.Event }; var subscribers = _eventSubscriber.GetSubscribers(eventDesc).ToList(); if (subscribers.Count == 0) { return; } foreach (var subscriber in subscribers) { var invokeData = new MethodInvocationData { IntentId = _idGenerator.NewId(), Service = subscriber.Service, Method = subscriber.Method, Parameters = data.Parameters, FlowContext = data.FlowContext, Caller = new CallerDescriptor(data.Service, data.Event, data.IntentId) }; InvokeInBackground(invokeData, preferences); } }
public static void Write(Message message, EventPublishData data, PublishPreferences preferences, ISerializer serializer) { message.Data["IntentId"] = data.IntentId; message.Data["Service"] = data.Service.Clone(); message.Data["Event"] = data.Event.Clone(); message.Data["Format"] = serializer.Format; message.Data["Parameters"] = serializer.SerializeToString(data.Parameters); message.Data["Caller"] = data.Caller?.Clone(); message.Data["SkipLocal"] = preferences.SkipLocalSubscribers; }
public Task PublishAsync(EventPublishData data, PublishPreferences preferences) { var message = new Message { Type = MessageType.Event, }; EventPublishDataTransformer.Write(message, data, preferences, _serializer); _messageHub.Schedule(message); return(Task.CompletedTask); }
public async Task PublishAsync(RaiseEventIntent intent) { var eventData = new EventPublishData { IntentId = intent.Id, Service = intent.Service, Event = intent.Event, Parameters = intent.Parameters }; if (_transitionScope.IsActive) { var context = (ITransitionContext)_transitionScope.CurrentMonitor.Context; eventData.FlowContext = context.FlowContext; eventData.Caller = context.CurrentAsCaller(); } var publisher = _eventPublisherProvider.GetPublisher(intent.Service, intent.Event); await publisher.PublishAsync(eventData, default); }
public async Task PublishAsync(EventPublishData data, PublishPreferences preferences) { var exchangeName = _settings.ExchangeName .Replace("{serviceName}", data.Service.Name) .Replace("{eventName}", data.Event.Name); // TODO: declare once? what's the penalty? _channel.ExchangeDeclare( exchangeName, type: "fanout", durable: true, autoDelete: false, arguments: null); var properties = CreateMessageProperties(_channel); properties.Type = MessageTypes.Event; SetIntentId(properties, data.IntentId); SetFormat(properties, _serializer); properties.Headers.Add("X-Service-Name", data.Service.Name); properties.Headers.Add("X-Event-Name", data.Event.Name); if (preferences.SkipLocalSubscribers) { properties.Headers.Add("X-Skip-Local", true); } var payload = SerializePayload(data); _channel.BasicPublish( exchange: exchangeName, routingKey: "", basicProperties: properties, body: payload); _channel.WaitForConfirms(); // no async version :( }
public async Task ReactAsync(EventPublishData data, ICommunicatorMessage message) { var eventDesc = new EventDescriptor { Service = data.Service, Event = data.Event }; var subscribers = _eventSubscriber.GetSubscribers(eventDesc).ToList(); if (subscribers.Count == 0) { return; } var publisherServiceReference = _serviceResolver.Resolve(data.Service); var publisherEventReference = _eventResolver.Resolve(publisherServiceReference.Definition, data.Event); var behaviorSettings = _communicationSettingsProvider.GetEventSettings(publisherEventReference.Definition, external: false); //------------------------------------------------------------------------------- // MESSGE DE-DUPLICATION //------------------------------------------------------------------------------- if (behaviorSettings.Deduplicate && !message.CommunicatorTraits.HasFlag(CommunicationTraits.MessageDeduplication) && (message.IsRetry != false || string.IsNullOrEmpty(message.RequestId))) { // TODO: if has message de-dup'er, check if a dedup // return new InvokeRoutineResult { Outcome = InvocationOutcome.Deduplicated }; } //------------------------------------------------------------------------------- // UNIT OF WORK //------------------------------------------------------------------------------- // TODO: Unit of Work - check if there is cached/stored data if (message.IsRetry != false) { // TODO: If has entities in transitions and they have been already committed, // skip method transition and re-try sending commands and events. } foreach (var subscriber in subscribers) { // Skip external services if (!_serviceResolver.TryResolve(subscriber.Service, out var subscriberServiceReference) || subscriberServiceReference.Definition.Type == ServiceType.External) { continue; } var invokeData = new MethodInvocationData { IntentId = _idGenerator.NewId(), Service = subscriber.Service, Method = subscriber.Method, Parameters = data.Parameters, FlowContext = data.FlowContext, Caller = new CallerDescriptor(data.Service, data.Event, data.IntentId) }; // TODO: think about fanning out depending on the communication mechanism, number of subscribers per event, and settings. await RunAsync(invokeData, message); } }
public async Task PublishAsync(EventPublishData data, PublishPreferences preferences) { await LocalPublisher.PublishAsync(data, default); await ExternalPublisher.PublishAsync(data, new PublishPreferences { SkipLocalSubscribers = true }); }