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)); } }
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); }
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); } }
public string?Map(Type type) => _inner.Map(type);