Exemplo n.º 1
0
        public override ValueTask <IDispatchResult> ProcessAsync <TMessage>(DispatchDataDictionary <TMessage> dispatchData,
                                                                            Func <DispatchDataDictionary <TMessage>, ValueTask <IDispatchResult> > next,
                                                                            CancellationToken cancellation)
        {
            var message = dispatchData.Message;
            var validationResultsBuilder = new ValidationResultsBuilder();
            var properties = typeof(TMessage).GetProperties().Where(p => p.CanRead && p.GetIndexParameters().Length == 0);

            foreach (var property in properties)
            {
                ValidateMember(validationResultsBuilder, property, property.GetValue(message));
            }

            for (var curr = typeof(TMessage); curr != typeof(object); curr = curr.BaseType)
            {
                var fields = curr.GetFields();

                foreach (var field in fields)
                {
                    ValidateMember(validationResultsBuilder, field, field.GetValue(message));
                }
            }

            var validationResults = validationResultsBuilder.GetValidationResults();

            if (validationResults.Any())
            {
                return(new ValueTask <IDispatchResult>(new ValidationFailureDispatchResult(validationResults)));
            }

            return(next(dispatchData));
        }
        private async ValueTask <IDispatchResult> InternalDispatchAsync(
            DispatchDataDictionary dispatchData,
            bool publish,
            CancellationToken cancellation)
        {
            var routes            = GetRoutes(dispatchData.MessageType);
            var serializedMessage = new Message();

            SerializeDispatchData(serializedMessage, dispatchData);

            var serializedResults = await _messageRouter.RouteAsync(routes, serializedMessage, publish, cancellation);

            var results = serializedResults.Select(p => DeserializeDispatchResult(p)).ToList();

            if (results.Count == 0)
            {
                if (publish)
                {
                    return(new SuccessDispatchResult());
                }

                return(new DispatchFailureDispatchResult(dispatchData.MessageType));
            }

            if (results.Count == 1)
            {
                var result = results.First();

                return(result);
            }

            return(new AggregateDispatchResult(results));
        }
        private async ValueTask <IDispatchResult> InternalDispatchAsync(
            DispatchDataDictionary dispatchData,
            bool publish,
            EndPointAddress endPoint,
            CancellationToken cancellation)
        {
            if (endPoint == await GetLocalEndPointAsync(cancellation))
            {
                var(result, _) = await TryDispatchLocalAsync(dispatchData, publish, allowRouteDescend : true, localDispatch : true, cancellation);

                return(result);
            }
            else
            {
                var route             = new Route(_typeConversion.SerializeType(dispatchData.MessageType));
                var serializedMessage = new Message();

                SerializeDispatchData(serializedMessage, dispatchData);

                var serializedResult = await _messageRouter.RouteAsync(route, serializedMessage, publish, endPoint, cancellation);

                var result = DeserializeDispatchResult(serializedResult);

                return(result);
            }
        }
        private void SerializeDispatchData(IMessage message, DispatchDataDictionary dispatchData)
        {
            Assert(message != null);
            Assert(dispatchData != null);

            if (_logger.IsEnabled(LogLevel.Trace))
            {
                var stringBuffer = new StringBuilder();

                using (var loggerWriter = new StringWriter(stringBuffer))
                    using (var loggerJsonWriter = new JsonTextWriter(loggerWriter))
                    {
                        Serializer.Serialize(loggerJsonWriter, dispatchData, typeof(DispatchDataDictionary));
                    }

                _logger.LogTrace($"Sending message: {stringBuffer.ToString()}");
            }

            using (var stream = message.PushFrame().OpenStream())
                using (var writer = new StreamWriter(stream))
                    using (var jsonWriter = new JsonTextWriter(writer))
                    {
                        Serializer.Serialize(jsonWriter, dispatchData, typeof(DispatchDataDictionary));
                    }
        }
        public ValueTask <IDispatchResult> DispatchAsync(
            DispatchDataDictionary dispatchData,
            bool publish,
            CancellationToken cancellation = default)
        {
            if (dispatchData == null)
            {
                throw new ArgumentNullException(nameof(dispatchData));
            }

            return(InternalDispatchAsync(dispatchData, publish, cancellation));
        }
        public async ValueTask <IDispatchResult> DispatchLocalAsync(
            DispatchDataDictionary dispatchData,
            bool publish,
            CancellationToken cancellation)
        {
            if (dispatchData == null)
            {
                throw new ArgumentNullException(nameof(dispatchData));
            }

            var(dispatchResult, _) = await TryDispatchLocalAsync(dispatchData, publish, allowRouteDescend : true, localDispatch : true, cancellation);

            return(dispatchResult);
        }
Exemplo n.º 7
0
        public static ValueTask <IDispatchResult> DispatchLocalAsync(
            this IMessageDispatcher messageDispatcher,
            DispatchDataDictionary dispatchData,
            bool publish,
            CancellationToken cancellation = default)
        {
            if (messageDispatcher == null)
            {
                throw new ArgumentNullException(nameof(messageDispatcher));
            }

            if (_isRemoteMessageDispatcher(messageDispatcher))
            {
                return(_dispatchLocalAsync(messageDispatcher, dispatchData, publish, cancellation));
            }

            return(messageDispatcher.DispatchAsync(dispatchData, publish, cancellation));
        }
        private async ValueTask <BlazorModuleManifest> GetModuleManifestCoreAsync(ModuleIdentifier module, CancellationToken cancellation)
        {
            var endPoint = await GetEndPointAsync(module, cancellation);

            var dispatchData = new DispatchDataDictionary <Query <BlazorModuleManifest> >(new Query <BlazorModuleManifest>());
            var queryResult  = await _messageDispatcher.DispatchAsync(dispatchData, publish : false, endPoint, cancellation);

            if (!queryResult.IsSuccessWithResult <BlazorModuleManifest>(out var manifest))
            {
                throw new Exception($"Unable to load manifest for {module}."); // TODO
            }

            _manifestCache.TryAdd(module, manifest);

            _logger.LogTrace($"Successfully loaded manifest for module {module}.");

            return(manifest);
        }
        private async ValueTask <(IDispatchResult result, bool handlersFound)> TryDispatchLocalAsync(
            DispatchDataDictionary dispatchData,
            bool publish,
            bool allowRouteDescend,
            bool localDispatch,
            CancellationToken cancellation)
        {
            var localEndPoint = await GetLocalEndPointAsync(cancellation);

            _logger?.LogInformation($"End-point '{localEndPoint}': Dispatching message of type {dispatchData.MessageType} locally.");

            try
            {
                return(await _localMessageDispatcher.TryDispatchAsync(dispatchData, publish, localDispatch, allowRouteDescend, cancellation));
            }
            finally
            {
                _logger?.LogDebug($"End-point '{localEndPoint}': Dispatched message of type {dispatchData.MessageType} locally.");
            }
        }
Exemplo n.º 10
0
            public MessageDispatchContext(
                IServiceProvider dispatchServices,
                DispatchDataDictionary dispatchData,
                bool publish,
                bool isLocalDispatch)
            {
                if (dispatchServices == null)
                {
                    throw new ArgumentNullException(nameof(dispatchServices));
                }

                if (dispatchData == null)
                {
                    throw new ArgumentNullException(nameof(dispatchData));
                }

                DispatchServices = dispatchServices;
                DispatchData     = dispatchData;
                IsPublish        = publish;
                IsLocalDispatch  = isLocalDispatch;
            }
Exemplo n.º 11
0
        private async ValueTask <BlazorModuleManifest?> GetModuleManifestCoreAsync(ModuleIdentifier module, CancellationToken cancellation)
        {
            var moduleProperties = await _modulePropertiesLookup.LookupAsync(module, cancellation);

            if (moduleProperties == null)
            {
                _logger?.LogError($"Unable to load manifest for {module}. The module properties could not be fetched.");
                return(null);
            }

            foreach (var endPoint in moduleProperties.EndPoints)
            {
                var dispatchData = new DispatchDataDictionary <Query <BlazorModuleManifest> >(new Query <BlazorModuleManifest>());
                var queryResult  = await _messageDispatcher.DispatchAsync(dispatchData, publish : false, endPoint, cancellation);

                if (!queryResult.IsSuccessWithResult <BlazorModuleManifest>(out var manifest))
                {
                    _logger?.LogWarning($"Unable to load manifest for {module} from end-point {endPoint}.");

                    continue;
                }

                _cache.TryAdd(module, manifest);
                _logger?.LogDebug($"Successfully loaded manifest for module {module}.");
                return(manifest);
            }

            if (moduleProperties.EndPoints.Any())
            {
                _logger?.LogError($"Unable to load manifest for {module}. No end-point matched.");
            }
            else
            {
                _logger?.LogError($"Unable to load manifest for {module}. No end-points available.");
            }

            return(null);
        }
Exemplo n.º 12
0
        public override async ValueTask <IDispatchResult> ProcessAsync <TMessage>(DispatchDataDictionary <TMessage> dispatchData,
                                                                                  Func <DispatchDataDictionary <TMessage>, ValueTask <IDispatchResult> > next,
                                                                                  CancellationToken cancellation)
        {
            var message    = dispatchData.Message;
            var handler    = Context.MessageHandler;
            var descriptor = EntityMessageHandlerContextDescriptor.GetDescriptor(handler.GetType());

            if (!descriptor.IsEntityMessageHandler)
            {
                return(await next(dispatchData));
            }

            if (!TryGetEntityLookup(message, descriptor, out var entityLookup))
            {
                return(await next(dispatchData));
            }

            var messageAccessor       = GetMessageAccessor();
            var checkConcurrencyToken = messageAccessor.TryGetConcurrencyToken(message, out var concurrencyToken);

            do
            {
                var entity = await entityLookup(cancellation);

                var createsEntityAttribute = Context.MessageHandlerAction.Member.GetCustomAttribute <CreatesEntityAttribute>();

                if (entity == null)
                {
                    if (createsEntityAttribute == null ||
                        !createsEntityAttribute.CreatesEntity)
                    {
                        return(new EntityNotFoundDispatchResult(descriptor.EntityType));
                    }
                }
                else
                {
                    if (createsEntityAttribute != null &&
                        createsEntityAttribute.CreatesEntity &&
                        !createsEntityAttribute.AllowExisingEntity)
                    {
                        if (!_entityPropertyAccessor.TryGetId(descriptor.EntityType, entity, out var id))
                        {
                            return(new EntityAlreadyPresentDispatchResult(descriptor.EntityType));
                        }
                        else
                        {
                            return(new EntityAlreadyPresentDispatchResult(descriptor.EntityType, id));
                        }
                    }

                    if (checkConcurrencyToken &&
                        concurrencyToken != _entityPropertyAccessor.GetConcurrencyToken(descriptor.EntityType, entity))
                    {
                        return(new ConcurrencyIssueDispatchResult());
                    }

                    descriptor.SetHandlerEntity(handler, entity);
                }

                var originalEntity = entity;
                var dispatchResult = await next(dispatchData);

                if (!dispatchResult.IsSuccess)
                {
                    return(dispatchResult);
                }

                var markedAsDeleted = descriptor.IsMarkedAsDeleted(handler);
                entity = descriptor.GetHandlerEntity(handler);

                try
                {
                    // The Store/Delete calls must be protected to be called with a null entity.
                    if (entity != null || originalEntity != null) // TODO: Do we care about events etc. here?
                    {
                        if (!_entityPropertyAccessor.TryGetId(descriptor.EntityType, entity ?? originalEntity, out var id))
                        {
                            return(new FailureDispatchResult("Unable to determine the id of the specified entity."));
                        }

                        if (markedAsDeleted || entity == null)
                        {
                            await _entityStorageEngine.DeleteAsync(descriptor.EntityType, entity ?? originalEntity, id);
                        }
                        else if (await _entityStorageEngine.TryStoreAsync(descriptor.EntityType, entity, id))
                        {
                            dispatchResult = AddAdditionalResultData(descriptor, entity, dispatchResult);
                        }
                        else
                        {
                            continue;
                        }
                    }
                }
                catch (ConcurrencyException)
                {
                    Assert(false);
                    continue;
                }
                catch (StorageException exc)
                {
                    return(new StorageIssueDispatchResult(exc));
                }
                catch (Exception exc)
                {
                    return(new FailureDispatchResult(exc));
                }

                return(dispatchResult);
            }while (!checkConcurrencyToken);

            return(new ConcurrencyIssueDispatchResult());
        }
Exemplo n.º 13
0
        private ValueTask <IDispatchResult> DispatchEventAsync(object evt, CancellationToken cancellation)
        {
            var dispatchData = DispatchDataDictionary.Create(evt.GetType(), evt);

            return(_eventDispatcher.DispatchLocalAsync(dispatchData, publish: true, cancellation));
        }