public override Task Invoke(IIncomingLogicalMessageContext context, Func <Task> next)
        {
            var command = context.Message.Instance as ICommand;

            if (command == null)
            {
                return(next());
            }

            Commands.Mark(context.Message.MessageType.FullName);

            var mutators = context.Builder.BuildAll <ICommandMutator>();

            if (!mutators.Any())
            {
                return(next());
            }

            IMutating mutated = new Mutating(command, context.Headers);

            foreach (var mutator in mutators)
            {
                Logger.Write(LogLevel.Debug, () => $"Mutating incoming command {context.Message.MessageType.FullName} with mutator {mutator.GetType().FullName}");
                mutated = mutator.MutateIncoming(mutated);
            }

            // Todo: maybe have a small bool to set if they actually changed headers, save some cycles
            foreach (var header in mutated.Headers)
            {
                context.Headers[header.Key] = header.Value;
            }
            context.UpdateMessageInstance(mutated.Message);

            return(next());
        }
示例#2
0
        public override Task Invoke(IOutgoingLogicalMessageContext context, Func <Task> next)
        {
            var @event = context.Message.Instance as IEvent;

            if (@event == null)
            {
                return(next());
            }

            Events.Mark(context.Message.MessageType.FullName);

            var mutators = context.Builder.BuildAll <IEventMutator>();

            if (!mutators.Any())
            {
                return(next());
            }

            IMutating mutated = new Mutating(@event, context.Headers ?? new Dictionary <string, string>());

            foreach (var mutator in mutators)
            {
                Logger.Write(LogLevel.Debug, () => $"Mutating outgoing event {context.Message.MessageType.FullName} with mutator {mutator.GetType().FullName}");
                mutated = mutator.MutateOutgoing(mutated);
            }

            foreach (var header in mutated.Headers)
            {
                context.Headers[header.Key] = header.Value;
            }
            context.UpdateMessage(mutated.Message);

            return(next());
        }
        public override Task Invoke(IOutgoingLogicalMessageContext context, Func <Task> next)
        {
            // Set aggregates.net message and corr id
            if (context.Headers.ContainsKey(Headers.MessageId))
            {
                context.Headers[$"{Defaults.PrefixHeader}.{Defaults.MessageIdHeader}"] = context.Headers[Headers.MessageId];
            }
            if (context.Headers.ContainsKey(Headers.CorrelationId))
            {
                context.Headers[$"{Defaults.PrefixHeader}.{Defaults.CorrelationIdHeader}"] = context.Headers[Headers.CorrelationId];
            }

            if (context.GetMessageIntent() == MessageIntentEnum.Reply)
            {
                return(next());
            }

            IMutating mutated = new Mutating(context.Message.Instance, context.Headers ?? new Dictionary <string, string>());

            var mutators = MutationManager.Registered.ToList();

            if (!mutators.Any())
            {
                return(next());
            }

            IContainer container;

            if (!context.Extensions.TryGet <IContainer>(out container))
            {
                container = Configuration.Settings.Container.GetChildContainer();
            }

            foreach (var type in mutators)
            {
                try
                {
                    var mutator = (IMutate)container.Resolve(type);
                    mutated = mutator.MutateOutgoing(mutated);
                }
                catch (Exception e)
                {
                    Logger.WarnEvent("MutateFailure", e, "Failed to run mutator {Mutator}", type.FullName);
                }
            }

            foreach (var header in mutated.Headers)
            {
                context.Headers[header.Key] = header.Value;
            }
            context.UpdateMessage(mutated.Message);

            return(next());
        }
示例#4
0
        public override Task Invoke(IIncomingLogicalMessageContext context, Func <Task> next)
        {
            if (context.GetMessageIntent() == MessageIntentEnum.Reply)
            {
                return(next());
            }

            IMutating mutated = new Mutating(context.Message.Instance, context.Headers ?? new Dictionary <string, string>());

            var mutators = MutationManager.Registered.ToList();

            if (!mutators.Any())
            {
                return(next());
            }

            IContainer container;

            if (!context.Extensions.TryGet <IContainer>(out container))
            {
                container = Configuration.Settings.Container;
            }

            foreach (var type in mutators)
            {
                try
                {
                    var mutator = (IMutate)container.Resolve(type);
                    mutated = mutator.MutateIncoming(mutated);
                }
                catch (Exception e)
                {
                    Logger.WarnEvent("MutateFailure", e, "Failed to run mutator {Mutator}", type.FullName);
                }
            }

            foreach (var header in mutated.Headers)
            {
                context.Headers[header.Key] = header.Value;
            }
            context.UpdateMessageInstance(mutated.Message);

            return(next());
        }
示例#5
0
        private IWritableEvent MakeWritableEvent(IEvent @event, IDictionary <string, string> headers, bool version = true)
        {
            var writable = new WritableEvent
            {
                Descriptor = new EventDescriptor
                {
                    EntityType = typeof(T).AssemblyQualifiedName,
                    StreamType = StreamType,
                    Bucket     = Bucket,
                    StreamId   = StreamId,
                    Timestamp  = DateTime.UtcNow,
                    Version    = version ? StreamVersion + 1 : StreamVersion,
                    Headers    = headers ?? new Dictionary <string, string>()
                },
                EventId = UnitOfWork.NextEventId(_commitId),
                Event   = @event
            };

            var mutators = _builder.BuildAll <IEventMutator>();

            if (!mutators.Any())
            {
                return(writable);
            }

            IMutating mutated = new Mutating(writable.Event, writable.Descriptor.Headers);

            foreach (var mutate in mutators)
            {
                Logger.Write(LogLevel.Debug, () => $"Mutating outgoing event {@event.GetType().FullName} with mutator {mutate.GetType().FullName}");
                mutated = mutate.MutateOutgoing(mutated);
            }

            foreach (var header in mutated.Headers)
            {
                writable.Descriptor.Headers[header.Key] = header.Value;
            }
            writable.Event = mutated.Message;

            return(writable);
        }
示例#6
0
        public override Task Invoke(IIncomingLogicalMessageContext context, Func <Task> next)
        {
            _metrics.Mark("Incoming Messages", Unit.Message);

            IMutating mutated = new Mutating(context.Message.Instance, context.Headers ?? new Dictionary <string, string>());

            var mutators = MutationManager.Registered.ToList();

            if (!mutators.Any())
            {
                return(next());
            }

            IContainer container;

            if (!context.Extensions.TryGet <IContainer>(out container))
            {
                container = Configuration.Settings.Container;
            }

            foreach (var type in mutators)
            {
                var mutator = (IMutate)container.TryResolve(type);
                if (mutator == null)
                {
                    continue;
                }

                Logger.Write(LogLevel.Debug, () => $"Mutating incoming message {context.Message.MessageType.FullName} with mutator {type.FullName}");
                mutated = mutator.MutateIncoming(mutated);
            }

            foreach (var header in mutated.Headers)
            {
                context.Headers[header.Key] = header.Value;
            }
            context.UpdateMessageInstance(mutated.Message);

            return(next());
        }
示例#7
0
        public async Task WriteStream <T>(Guid commitId, IEventStream stream, IDictionary <string, string> commitHeaders) where T : class, IEventSource
        {
            var streamName = _streamGen(typeof(T), StreamTypes.Domain, stream.Bucket, stream.StreamId, stream.Parents);

            Logger.Write(LogLevel.Debug,
                         () =>
                         $"Writing {stream.Uncommitted.Count()} events to stream {stream.StreamId} bucket {stream.Bucket} with commit id {commitId}");

            if (await CheckFrozen <T>(stream.Bucket, stream.StreamId, stream.Parents).ConfigureAwait(false))
            {
                throw new FrozenException();
            }

            Saved.Mark();

            var events = stream.Uncommitted.Select(writable =>
            {
                IMutating mutated = new Mutating(writable.Event, writable.Descriptor.Headers);
                foreach (var mutate in _mutators)
                {
                    Logger.Write(LogLevel.Debug,
                                 () => $"Mutating outgoing event {writable.Event.GetType()} with mutator {mutate.GetType().FullName}");
                    mutated = mutate.MutateOutgoing(mutated);
                }

                // Todo: have some bool that is set true if they modified headers
                if (_mutators.Any())
                {
                    foreach (var header in mutated.Headers)
                    {
                        writable.Descriptor.Headers[header.Key] = header.Value;
                    }
                }
                return((IFullEvent) new WritableEvent
                {
                    Descriptor = writable.Descriptor,
                    Event = mutated.Message,
                    EventId = UnitOfWork.NextEventId(commitId)
                });
            }).ToList();

            var oobs = stream.Oobs.ToDictionary(x => x.Id, x => x);

            foreach (var oob in stream.PendingOobs)
            {
                oobs[oob.Id] = oob;
            }

            var domainEvents = events.Where(x => x.Descriptor.StreamType == StreamTypes.Domain);
            var oobEvents    = events.Where(x => x.Descriptor.StreamType == StreamTypes.OOB);

            if (domainEvents.Any())
            {
                _cache.Evict(streamName);

                Logger.Write(LogLevel.Debug,
                             () => $"Event stream [{stream.StreamId}] in bucket [{stream.Bucket}] committing {domainEvents.Count()} events");
                await _store.WriteEvents(streamName, domainEvents, commitHeaders, expectedVersion : stream.CommitVersion)
                .ConfigureAwait(false);
            }
            if (stream.PendingOobs.Any())
            {
                await _store.WriteMetadata(streamName, custom : new Dictionary <string, string>
                {
                    [OobMetadataKey] = JsonConvert.SerializeObject(oobs.Values)
                }).ConfigureAwait(false);
            }

            if (stream.PendingSnapshot != null)
            {
                Logger.Write(LogLevel.Debug,
                             () => $"Event stream [{stream.StreamId}] in bucket [{stream.Bucket}] committing snapshot");
                await _snapstore.WriteSnapshots <T>(stream.Bucket, stream.StreamId, stream.Parents, stream.StreamVersion, stream.PendingSnapshot, commitHeaders).ConfigureAwait(false);
            }
            if (oobEvents.Any())
            {
                Logger.Write(LogLevel.Debug,
                             () => $"Event stream [{stream.StreamId}] in bucket [{stream.Bucket}] publishing {oobEvents.Count()} out of band events");

                foreach (var group in oobEvents.GroupBy(x => x.Descriptor.Headers[Defaults.OobHeaderKey]))
                {
                    // OOB events of the same stream name don't need to all be written to the same stream
                    // if we parallelize the events into 10 known streams we can take advantage of internal
                    // ES optimizations and ES sharding
                    var vary      = _random.Next(10) + 1;
                    var oobstream = $"{streamName}-{group.Key}.{vary}";


                    var definition = oobs[group.Key];
                    if (definition.Transient ?? false)
                    {
                        await _publisher.Publish <T>(oobstream, group, commitHeaders).ConfigureAwait(false);
                    }
                    else if (definition.DaysToLive.HasValue)
                    {
                        var version = await _store.WriteEvents(oobstream, group, commitHeaders).ConfigureAwait(false);

                        // if new stream, write metadata
                        if (version == (group.Count() - 1))
                        {
                            await _store.WriteMetadata(oobstream, maxAge : TimeSpan.FromDays(definition.DaysToLive.Value)).ConfigureAwait(false);
                        }
                    }
                    else
                    {
                        await _store.WriteEvents(oobstream, group, commitHeaders).ConfigureAwait(false);
                    }
                }
            }
        }
示例#8
0
        public Task <long> WriteEvents(string stream, IFullEvent[] events,
                                       IDictionary <string, string> commitHeaders, long?expectedVersion = null)
        {
            var mutators = MutationManager.Registered.ToList();

            var translatedEvents = events.Select(e =>
            {
                IMutating mutated = new Mutating(e.Event, e.Descriptor.Headers ?? new Dictionary <string, string>());

                // use async local container first if one exists
                // (is set by unit of work - it creates a child container which mutators might need)
                IContainer container = Configuration.Settings.LocalContainer.Value;
                if (container == null)
                {
                    container = Configuration.Settings.Container;
                }

                foreach (var type in mutators)
                {
                    var mutator = (IMutate)container.TryResolve(type);
                    if (mutator == null)
                    {
                        Logger.WarnEvent("MutateFailure", "Failed to construct mutator {Mutator}", type.FullName);
                        continue;
                    }

                    mutated = mutator.MutateOutgoing(mutated);
                }
                var mappedType = e.Event.GetType();
                if (!mappedType.IsInterface)
                {
                    mappedType = _mapper.GetMappedTypeFor(mappedType) ?? mappedType;
                }

                var descriptor = new EventDescriptor
                {
                    EventId       = e.EventId ?? Guid.NewGuid(),
                    CommitHeaders = (commitHeaders ?? new Dictionary <string, string>()).Merge(new Dictionary <string, string>
                    {
                        [Defaults.InstanceHeader]          = Defaults.Instance.ToString(),
                        [Defaults.EndpointHeader]          = Configuration.Settings.Endpoint,
                        [Defaults.EndpointVersionHeader]   = Configuration.Settings.EndpointVersion.ToString(),
                        [Defaults.AggregatesVersionHeader] = Configuration.Settings.AggregatesVersion.ToString(),
                        [Defaults.MachineHeader]           = Environment.MachineName,
                    }),
                    Compressed = _compress.HasFlag(Compression.Events),
                    EntityType = e.Descriptor.EntityType,
                    StreamType = e.Descriptor.StreamType,
                    Bucket     = e.Descriptor.Bucket,
                    StreamId   = e.Descriptor.StreamId,
                    Parents    = e.Descriptor.Parents,
                    Version    = e.Descriptor.Version,
                    Timestamp  = e.Descriptor.Timestamp,
                    Headers    = e.Descriptor.Headers,
                };

                var eventType = _registrar.GetVersionedName(mappedType);
                foreach (var header in mutated.Headers)
                {
                    e.Descriptor.Headers[header.Key] = header.Value;
                }


                var @event = _serializer.Serialize(mutated.Message);

                if (_compress.HasFlag(Compression.Events))
                {
                    descriptor.Compressed = true;
                    @event = @event.Compress();
                }
                var metadata = _serializer.Serialize(descriptor);

                return(new EventData(
                           descriptor.EventId,
                           eventType,
                           !descriptor.Compressed,
                           @event,
                           metadata
                           ));
            }).ToArray();

            return(DoWrite(stream, translatedEvents, expectedVersion));
        }