Пример #1
0
        private async Task RunRoutineAsync(
            ITransitionCarrier transitionCarrier,
            TransitionDescriptor transitionDescriptor,
            CancellationToken ct)
        {
            using (_transitionScope.Enter(transitionDescriptor))
            {
                var transitionMonitor = _transitionScope.CurrentMonitor;

                var serviceId = await transitionCarrier.GetServiceIdAsync(ct);

                var routineDescriptor = await transitionCarrier.GetRoutineDescriptorAsync(ct);

                object             serviceInstance;
                IServiceDefinition serviceDefinition;

#warning IntrinsicRoutines must be registered in the service registry, but it needs the engine IoC to resolve.
                if (serviceId.ProxyName == nameof(IntrinsicRoutines))
                {
                    serviceInstance   = _intrinsicRoutines;
                    serviceDefinition = IntrinsicCommunicationModel.IntrinsicRoutinesServiceDefinition;
                }
                else
                {
                    serviceInstance   = _serviceProxyBuilder.Build(serviceId);
                    serviceDefinition = ((ServiceProxyContext)((IProxy)serviceInstance).Context).Definition;
                }

                var routineMethod = _routineMethodResolver.Resolve(serviceDefinition, routineDescriptor.MethodId);

                //var serviceStateContainer = _serviceStateValueContainerProvider.CreateContainer(serviceInstance);
                //var isStatefullService = serviceStateContainer.GetCount() > 0;
                //if (isStatefullService)
                //    await transitionCarrier.ReadServiceStateAsync(serviceStateContainer, ct);

                Task            completionTask;
                IValueContainer asmValueContainer = null;

                if (TryCreateAsyncStateMachine(routineMethod, out var asmInstance, out var asmMetadata))
                {
                    var isContinuation = transitionDescriptor.Type == TransitionType.ContinueRoutine;
                    asmValueContainer = await LoadRoutineStateAsync(transitionCarrier, asmInstance, asmMetadata, isContinuation, ct);

                    asmMetadata.Owner.FieldInfo?.SetValue(asmInstance, serviceInstance);

                    transitionMonitor.OnRoutineStart(
                        serviceId,
                        routineDescriptor,
                        serviceInstance,
                        routineMethod,
                        asmInstance);

                    try
                    {
#warning possibly need to create a proxy? on a sealed ASM class? How to capture Task.Delay if it's not immediate after first MoveNext?
                        asmInstance.MoveNext();
                        completionTask = GetCompletionTask(asmInstance, asmMetadata);
                    }
                    catch (Exception ex)
                    {
                        // The MoveNext() must not throw, but instead complete the task with an error.
                        // try-catch is added just in case for a non-compiler-generated state machine.
                        var taskResultType = TaskAccessor.GetTaskResultType(routineMethod.ReturnType);
                        completionTask = TaskAccessor.FromException(taskResultType, ex);
                    }
                }
Пример #2
0
        public async Task <BootstrapResult> BootstrapAsync(CancellationToken ct)
        {
            //_serviceRegistry.Register(
            //    new ServiceRegistrationInfo
            //    {
            //        Name = nameof(IntrinsicRoutines),
            //        QualifiedServiceTypeName = typeof(IntrinsicRoutines).AssemblyQualifiedName,
            //        QualifiedImplementationTypeName = typeof(IntrinsicRoutines).AssemblyQualifiedName,
            //        IsSingleton = true
            //    });

            //foreach (var serviceType in _appServiceDiscoveryFromCodeMarkup.DiscoverServiceTypes())
            //{
            //    ServiceRegistrationInfo registrationInfo;
            //    try
            //    {
            //        registrationInfo = _appServiceRegistrationInfoExtractor.Extract(serviceType);
            //    }
            //    catch
            //    {
            //        continue;
            //    }
            //    // TODO: fill in 'fabric' config?
            //    _serviceRegistry.Register(registrationInfo);
            //}

            //foreach (var registrationInfo in _appServiceDiscoveryFromRuntimeCollection.Services)
            //{
            //    // TODO: fill in 'fabric' config?
            //    _serviceRegistry.Register(registrationInfo);
            //}

            var appIocContainer = _appIocContainerProviders
                                  .Select(p => p.GetAppIocContainer())
                                  .FirstOrDefault(c => c != null);

            if (appIocContainer != null)
            {
                foreach (var bindingInfo in appIocContainer.DiscoverServices())
                {
                    var registrationInfo = new ServiceRegistrationInfo
                    {
                        QualifiedServiceTypeName        = bindingInfo.ServiceType.AssemblyQualifiedName,
                        QualifiedImplementationTypeName = bindingInfo.ImplementationType?.AssemblyQualifiedName,
                        IsExternal  = bindingInfo.IsExternal,
                        IsSingleton = true
                    };
                    // TODO: fill in 'fabric' config?
                    _serviceRegistry.Register(registrationInfo);
                }
            }

            if (appIocContainer == null)
            {
                appIocContainer = new BasicAppServiceIocContainer();
            }
            _appIocContainerHolder.Container = appIocContainer;

            foreach (var serviceRegistration in _serviceRegistry.AllRegistrations)
            {
                if (serviceRegistration.IsSingleton)
                {
                    var implementationType = serviceRegistration.ImplementationType;

                    if (implementationType == null && appIocContainer.TryGetImplementationType(
                            serviceRegistration.ServiceType, out implementationType) == true)
                    {
                        // TODO: properly update registration
                        ((ServiceRegistration)serviceRegistration).ImplementationType = implementationType;
                    }

                    if (!serviceRegistration.IsExternal && implementationType == null)
                    {
                        throw new InvalidOperationException(
                                  $"Could not find implementation type for service '{serviceRegistration.ServiceType}'.");
                    }

                    Func <object> proxyFactory = () =>
                    {
                        var serviceId = new ServiceId
                        {
                            ServiceName = serviceRegistration.ServiceName
                        };
                        var proxy = _serviceProxyBuilder.Build(serviceId);
                        return(proxy);
                    };

                    appIocContainer.RebindService(
                        serviceRegistration.ServiceType,
                        proxyFactory);

                    if (implementationType != null)
                    {
                        appIocContainer.RebindService(
                            implementationType,
                            proxyFactory);
                    }
                }
            }

            if (_fabric != null)
            {
                await _fabric.InitializeAsync(ct);
            }

            await _serviceRegistryUpdaterViaDiscovery.UpdateAsync(ct);

            if (_fabric != null && _servicePublishers.Length > 0)
            {
                var servicesToRegister = new List <ServiceRegistrationInfo>();

                foreach (var serviceRegistration in _serviceRegistry.AllRegistrations.Where(r => !r.IsExternal))
                {
                    var serviceId = new ServiceId {
                        ServiceName = serviceRegistration.ServiceName
                    };
                    if (_fabric.GetConnector(serviceId) is
                        IFabricConnectorWithConfiguration connectorWithConfiguration)
                    {
                        servicesToRegister.Add(new ServiceRegistrationInfo
                        {
                            Name = serviceRegistration.ServiceName,
                            QualifiedServiceTypeName = serviceRegistration.ServiceType.FullName,
                            IsSingleton            = serviceRegistration.IsSingleton,
                            IsExternal             = true,
                            ConnectorType          = connectorWithConfiguration.ConnectorType,
                            ConnectorConfiguration = connectorWithConfiguration.Configuration
                        });
                    }
                }

                if (servicesToRegister.Count > 0)
                {
                    foreach (var publisher in _servicePublishers)
                    {
                        await publisher.PublishAsync(servicesToRegister, ct);
                    }
                }
            }

            if (_fabric != null)
            {
                await _fabric.StartAsync(ct);
            }

            return(new BootstrapResult
            {
                Fabric = _fabric,
                AppIocContainer = _appIocContainerHolder.Container
            });
        }
Пример #3
0
        private async Task RunRoutineAsync(
            ITransitionCarrier transitionCarrier,
            ITransitionData transitionData,
            TransitionDescriptor transitionDescriptor,
            CancellationToken ct)
        {
            using (_transitionScope.Enter(transitionDescriptor))
            {
                var transitionMonitor = _transitionScope.CurrentMonitor;

                var serviceId = await transitionData.GetServiceIdAsync(ct);

                var routineDescriptor = await transitionData.GetRoutineDescriptorAsync(ct);

                var serviceInstance =
#warning IntrinsicRoutines must be registered in the service registry, but it needs the engine IoC to resolve.
                    serviceId.ProxyName == nameof(IntrinsicRoutines)
                    ? _intrinsicRoutines
                    : _serviceProxyBuilder.Build(serviceId);
#warning check if the serviceInstance proxy is an actual non-abstract class with implementation

                // Need exact underlying type of the service implementation type to call
                // the routine method directly without using the virtual method table.
                var serviceType   = (serviceInstance as IProxy)?.ObjectType ?? serviceInstance.GetType();
                var routineMethod = _routineMethodResolver.Resolve(serviceType, routineDescriptor.MethodId);

                var serviceStateContainer = _serviceStateValueContainerProvider.CreateContainer(serviceInstance);
                var isStatefullService    = serviceStateContainer.GetCount() > 0;
                if (isStatefullService)
                {
                    await transitionData.ReadServiceStateAsync(serviceStateContainer, ct);
                }

                Task            completionTask;
                IValueContainer asmValueContainer = null;

                if (TryCreateAsyncStateMachine(routineMethod, out var asmInstance, out var asmMetadata, out completionTask))
                {
                    var isContinuation = transitionDescriptor.Type == TransitionType.ContinueRoutine;
                    asmValueContainer = await LoadRoutineStateAsync(transitionData, asmInstance, asmMetadata, isContinuation, ct);

                    asmMetadata.Owner.FieldInfo?.SetValue(asmInstance, serviceInstance);

                    transitionMonitor.OnRoutineStart(
                        serviceId,
                        routineDescriptor,
                        serviceInstance,
                        routineMethod,
                        asmInstance);

                    try
                    {
#warning possibly need to create a proxy? on a sealed ASM class? How to capture Task.Delay if it's not immediate after first MoveNext?
                        asmInstance.MoveNext();
                    }
                    catch (Exception ex)
                    {
                        // The MoveNext() must not throw, but instead complete the task with an error.
                        // try-catch is added just in case for a non-compiler-generated state machine.
                        var taskResultType = TaskAccessor.GetTaskResultType(routineMethod.ReturnType);
                        completionTask = TaskAccessor.FromException(taskResultType, ex);
                    }
                }