Пример #1
0
    /// <inheritdoc />
    public async Task <ScopedFilterStreamProcessor> Create(
        TypeFilterWithEventSourcePartitionDefinition filterDefinition,
        StreamProcessorId streamProcessorId,
        CancellationToken cancellationToken)
    {
        var processorState = await GetOrCreateStreamProcessorState(
            streamProcessorId,
            StreamProcessorState.New,
            cancellationToken)
                             .ConfigureAwait(false);

        if (processorState is not StreamProcessorState unpartitionedProcessorState)
        {
            throw new ExpectedUnpartitionedStreamProcessorState(streamProcessorId);
        }
        // TODO: This is not needed when using the fast event handler.
        NotifyStream(streamProcessorId.ScopeId, filterDefinition, processorState.Position);
        return(_createFilterStreamProcessor(
                   _eventLogStream.Subscribe(
                       streamProcessorId.ScopeId,
                       processorState.Position.Value,
                       new ReadOnlyCollection <ArtifactId>(filterDefinition.Types.ToList()),
                       CancellationToken.None),
                   streamProcessorId,
                   filterDefinition.Partitioned,
                   unpartitionedProcessorState));
    }
Пример #2
0
 /// <summary>
 /// Converts the <see cref="IFilterDefinition" /> to <see cref="AbstractFilterDefinition" />.
 /// </summary>
 /// <param name="filterDefinition">The <see cref="IFilterDefinition" />.</param>
 /// <returns>Converted <see cref="AbstractFilterDefinition" />.</returns>
 public static AbstractFilterDefinition ToStoreRepresentation(this IFilterDefinition filterDefinition)
 {
     return(filterDefinition switch
     {
         TypeFilterWithEventSourcePartitionDefinition definition =>
         new TypePartitionFilterDefinition(definition.Types.Select(_ => _.Value)),
         PublicFilterDefinition => new RemoteFilterDefinition(),
         FilterDefinition => new RemoteFilterDefinition(),
         _ => throw new UnsupportedFilterDefinitionType(filterDefinition)
     });
Пример #3
0
 void NotifyStream(ScopeId scopeId, TypeFilterWithEventSourcePartitionDefinition filterDefinition, StreamPosition position)
 {
     if (position == StreamPosition.Start)
     {
         return;
     }
     if (filterDefinition.Public)
     {
         _streamWatcher.NotifyForEvent(filterDefinition.TargetStream, position - 1);
     }
     else
     {
         _streamWatcher.NotifyForEvent(scopeId, filterDefinition.TargetStream, position - 1);
     }
 }
Пример #4
0
        /// <inheritdoc/>
        public override async Task Connect(
            IAsyncStreamReader <EventHandlerClientToRuntimeMessage> runtimeStream,
            IServerStreamWriter <EventHandlerRuntimeToClientMessage> clientStream,
            ServerCallContext context)
        {
            _logger.Debug("Connecting Event Handler");
            using var cts = CancellationTokenSource.CreateLinkedTokenSource(_hostApplicationLifetime.ApplicationStopping, context.CancellationToken);
            var cancellationToken = cts.Token;
            var dispatcher        = _reverseCallDispatchers.GetFor <EventHandlerClientToRuntimeMessage, EventHandlerRuntimeToClientMessage, EventHandlerRegistrationRequest, EventHandlerRegistrationResponse, HandleEventRequest, EventHandlerResponse>(
                runtimeStream,
                clientStream,
                context,
                _ => _.RegistrationRequest,
                (serverMessage, registrationResponse) => serverMessage.RegistrationResponse = registrationResponse,
                (serverMessage, request) => serverMessage.HandleRequest = request,
                _ => _.HandleResult,
                _ => _.CallContext,
                (request, context) => request.CallContext = context,
                _ => _.CallContext,
                (message, ping) => message.Ping = ping,
                message => message.Pong);

            _logger.Trace("Waiting for connection arguments...");
            if (!await dispatcher.ReceiveArguments(cancellationToken).ConfigureAwait(false))
            {
                const string message = "Event Handlers connection arguments were not received";
                _logger.Warning(message);
                var failure = new Failure(EventHandlersFailures.NoEventHandlerRegistrationReceived, message);
                await WriteFailedRegistrationResponse(dispatcher, failure, cancellationToken).ConfigureAwait(false);

                return;
            }

            _logger.Trace("Received connection arguments");
            var arguments        = dispatcher.Arguments;
            var executionContext = arguments.CallContext.ExecutionContext.ToExecutionContext();

            _logger.Trace("Setting execution context{NewLine}{ExecutionContext}", System.Environment.NewLine, executionContext);
            _executionContextManager.CurrentFor(executionContext);

            var sourceStream = StreamId.EventLog;

            _logger.Trace("Received Source Stream '{SourceStream}'", sourceStream);
            var eventHandlerId = arguments.EventHandlerId.To <EventProcessorId>();

            _logger.Trace("Received Event Handler '{EventHandler}'", eventHandlerId);
            StreamId targetStream = eventHandlerId.Value;
            var      scopeId      = arguments.ScopeId.To <ScopeId>();

            _logger.Trace("Received Scope '{Scope}'", scopeId);
            var types = arguments.Types_.Select(_ => _.Id.To <ArtifactId>());

            _logger.Trace("Received Types: [{Types}]'", string.Join(", ", types.Select(_ => $"'{_}'")));
            var partitioned = arguments.Partitioned;

            _logger.Trace("Event Handler '{EventHandler}' {PartitionedString}", eventHandlerId, partitioned ? "is partitioned" : "is not partitioned");
            if (targetStream.IsNonWriteable)
            {
                _logger.Warning("Cannot register Event Handler '{EventHandler}' because it is an invalid Stream Id", eventHandlerId);
                var failure = new Failure(
                    EventHandlersFailures.CannotRegisterEventHandlerOnNonWriteableStream,
                    $"Cannot register Event Handler: '{eventHandlerId}' because it is an invalid Stream Id");
                await WriteFailedRegistrationResponse(dispatcher, failure, cancellationToken).ConfigureAwait(false);

                return;
            }

            _logger.Debug("Connecting Event Handler '{EventHandlerId}'", eventHandlerId);
            var filterDefinition         = new TypeFilterWithEventSourcePartitionDefinition(sourceStream, targetStream, types, partitioned);
            var filteredStreamDefinition = new StreamDefinition(filterDefinition);
            Func <IFilterProcessor <TypeFilterWithEventSourcePartitionDefinition> > getFilterProcessor = () => new TypeFilterWithEventSourcePartition(
                scopeId,
                filterDefinition,
                _getEventsToStreamsWriter(),
                _loggerManager.CreateLogger <TypeFilterWithEventSourcePartition>());
            var tryRegisterFilterStreamProcessor = TryRegisterFilterStreamProcessor <TypeFilterWithEventSourcePartitionDefinition>(
                scopeId,
                eventHandlerId,
                getFilterProcessor,
                cancellationToken);

            if (!tryRegisterFilterStreamProcessor.Success)
            {
                if (tryRegisterFilterStreamProcessor.HasException)
                {
                    var exception = tryRegisterFilterStreamProcessor.Exception;
                    _logger.Warning(exception, "An error occurred while registering Event Handler '{EventHandlerId}'", eventHandlerId);
                    ExceptionDispatchInfo.Capture(exception).Throw();
                }
                else
                {
                    _logger.Debug("Failed to register Event Handler '{EventHandlerId}'. Filter already registered", eventHandlerId);
                    var failure = new Failure(
                        FiltersFailures.FailedToRegisterFilter,
                        $"Failed to register Event Handler: {eventHandlerId}. Filter already registered.");
                    await WriteFailedRegistrationResponse(dispatcher, failure, cancellationToken).ConfigureAwait(false);

                    return;
                }
            }

            using var filterStreamProcessor = tryRegisterFilterStreamProcessor.Result;

            var tryRegisterEventProcessorStreamProcessor = TryRegisterEventProcessorStreamProcessor(
                scopeId,
                eventHandlerId,
                filteredStreamDefinition,
                () => new EventProcessor(
                    scopeId,
                    eventHandlerId,
                    dispatcher,
                    _loggerManager.CreateLogger <EventProcessor>()),
                cancellationToken);

            if (!tryRegisterEventProcessorStreamProcessor.Success)
            {
                if (tryRegisterEventProcessorStreamProcessor.HasException)
                {
                    var exception = tryRegisterEventProcessorStreamProcessor.Exception;
                    _logger.Warning(exception, "An error occurred while registering Event Handler' {EventHandlerId}", eventHandlerId);
                    ExceptionDispatchInfo.Capture(exception).Throw();
                }
                else
                {
                    _logger.Warning("Failed to register Event Handler: {eventHandlerId}. Event Processor already registered on Source Stream '{SourceStreamId}'", eventHandlerId, eventHandlerId);
                    var failure = new Failure(
                        FiltersFailures.FailedToRegisterFilter,
                        $"Failed to register Event Handler: {eventHandlerId}. Event Processor already registered on Source Stream: '{eventHandlerId}'");
                    await WriteFailedRegistrationResponse(dispatcher, failure, cancellationToken).ConfigureAwait(false);

                    return;
                }
            }

            using var eventProcessorStreamProcessor = tryRegisterEventProcessorStreamProcessor.Result;

            var tryStartEventHandler = await TryStartEventHandler(
                dispatcher,
                filterStreamProcessor,
                eventProcessorStreamProcessor,
                scopeId,
                filterDefinition,
                getFilterProcessor,
                cancellationToken).ConfigureAwait(false);

            if (!tryStartEventHandler.Success)
            {
                cts.Cancel();
                if (tryStartEventHandler.HasException)
                {
                    var exception = tryStartEventHandler.Exception;
                    _logger.Debug(exception, "An error occurred while starting Event Handler '{EventHandlerId}' in Scope {ScopeId}", eventHandlerId, scopeId);
                    ExceptionDispatchInfo.Capture(exception).Throw();
                }
                else
                {
                    _logger.Warning("Could not start Event Handler '{EventHandlerId}' in Scope: {ScopeId}", eventHandlerId, scopeId);
                    return;
                }
            }

            var tasks = tryStartEventHandler.Result;

            try
            {
                await Task.WhenAny(tasks).ConfigureAwait(false);

                if (TryGetException(tasks, out var ex))
                {
                    _logger.Warning(ex, "An error occurred while running Event Handler '{EventHandlerId}' in Scope: '{ScopeId}'", eventHandlerId, scopeId);
                    ExceptionDispatchInfo.Capture(ex).Throw();
                }
            }
            finally
            {
                cts.Cancel();
                await Task.WhenAll(tasks).ConfigureAwait(false);

                _logger.Debug("Event Handler: '{EventHandler}' in Scope: '{ScopeId}' disconnected", eventHandlerId, scopeId);
            }
        }