예제 #1
0
        private async Task Subscribe(CancellationToken cancellationToken)
        {
            if (Interlocked.CompareExchange(ref _subscribed, 1, 0) == 1)
            {
                return;
            }

            var registration = _stoppedRegistration;

            if (registration != null)
            {
                await registration.Value.DisposeAsync();
            }

            Interlocked.Exchange(ref _subscription, await _eventStore.SubscribeToAllAsync(
                                     Position.Start,
                                     ProjectAsync,
                                     subscriptionDropped: (_, reason, ex) => {
                if (reason == SubscriptionDroppedReason.Disposed)
                {
                    return;
                }

                Log.Error(ex, "Subscription dropped: {reason}", reason);
            },
                                     filterOptions: new SubscriptionFilterOptions(EventTypeFilter.ExcludeSystemEvents()),
                                     userCredentials: new UserCredentials("admin", "changeit"),
                                     cancellationToken: _stopped.Token));

            _stoppedRegistration = _stopped.Token.Register(_subscription.Dispose);

            Task ProjectAsync(StreamSubscription s, ResolvedEvent e, CancellationToken ct)
            {
                var type = _messageTypeMapper.Map(e.Event.EventType);

                if (type == null)
                {
                    return(Task.CompletedTask);
                }
                var message = JsonSerializer.Deserialize(
                    e.Event.Data.Span, type, TransactoSerializerOptions.Events);

                return(_projector.ProjectAsync(_target, Envelope.Create(message, e.OriginalEvent.Position), ct));
            }
        }
예제 #2
0
        public async ValueTask <GeneralLedger> Get(CancellationToken cancellationToken = default)
        {
            if (_unitOfWork.TryGet(GeneralLedger.Identifier, out var a) && a is GeneralLedger generalLedger)
            {
                return(generalLedger);
            }

            await using var events = _eventStore.ReadStreamAsync(Direction.Backwards,
                                                                 GeneralLedger.Identifier, StreamPosition.End, int.MaxValue, cancellationToken: cancellationToken);

            generalLedger = GeneralLedger.Factory();

            var            stack          = new Stack <object>();
            bool           lastEventRead  = false;
            StreamPosition streamPosition = default;

            await foreach (var resolvedEvent in events)
            {
                if (!lastEventRead)
                {
                    streamPosition = resolvedEvent.OriginalEvent.EventNumber;
                    lastEventRead  = true;
                }

                var @event = JsonSerializer.Deserialize(resolvedEvent.OriginalEvent.Data.Span,
                                                        _messageTypeMapper.Map(resolvedEvent.OriginalEvent.EventType),
                                                        TransactoSerializerOptions.Events);
                stack.Push(@event);

                if (@event is GeneralLedgerOpened || @event is AccountingPeriodClosed)
                {
                    break;
                }
            }

            generalLedger.LoadFromHistory(stack);

            _unitOfWork.Attach(GeneralLedger.Identifier, generalLedger, streamPosition.ToInt64());

            return(generalLedger);
        }
        public MessageType Recognize(Stream bodyStream)
        {
            var document = XDocument.Load(bodyStream);
            var xmlNode  = document.Root;

            if (xmlNode == null)
            {
                throw new InvalidOperationException("body xml format incorrect.");
            }

            var msgTypeNode = xmlNode.Element(MsgTypeNodeName);

            if (msgTypeNode == null)
            {
                throw new InvalidOperationException("cannot found MsgType node.");
            }

            var msgTypeText = msgTypeNode.Value;

            var msgType = _messageTypeMapper.Map(msgTypeText);

            return(msgType);
        }
예제 #4
0
        public async ValueTask <Optional <TAggregateRoot> > GetById(string identifier,
                                                                    CancellationToken cancellationToken = default)
        {
            var streamName = identifier;

            if (_unitOfWork.TryGet(streamName, out var a) && a is TAggregateRoot aggregate)
            {
                return(new Optional <TAggregateRoot>(aggregate));
            }

            try {
                await using var events = _eventStore.ReadStreamAsync(Direction.Forwards,
                                                                     streamName, StreamPosition.Start,
                                                                     configureOperationOptions: options => options.TimeoutAfter = TimeSpan.FromMinutes(20),
                                                                     cancellationToken: cancellationToken);

                aggregate = _factory();

                var version = await aggregate.LoadFromHistory(events.Select(e =>
                                                                            JsonSerializer.Deserialize(e.OriginalEvent.Data.Span,
                                                                                                       _messageTypeMapper.Map(e.OriginalEvent.EventType),
                                                                                                       _serializerOptions)));

                _unitOfWork.Attach(streamName, aggregate, version);

                return(aggregate);
            } catch (StreamNotFoundException) {
                return(Optional <TAggregateRoot> .Empty);
            }
        }
예제 #5
0
 public string?Map(Type type) => _inner.Map(type);