예제 #1
0
        /// <summary>
        /// Configure silo to use indexing using a configure action.
        /// </summary>
        public static ISiloHostBuilder UseIndexing(this ISiloHostBuilder builder, Action <IndexingOptions> configureOptions = null)
        {
            // This is necessary to get the configured NumWorkflowQueuesPerInterface for IndexFactory.RegisterIndexWorkflowQueueGrainServices.
            var indexingOptions = new IndexingOptions();

            configureOptions?.Invoke(indexingOptions);

            return(builder.AddSimpleMessageStreamProvider(IndexingConstants.INDEXING_STREAM_PROVIDER_NAME)
                   .AddMemoryGrainStorage(IndexingConstants.INDEXING_WORKFLOWQUEUE_STORAGE_PROVIDER_NAME)
                   .AddMemoryGrainStorage(IndexingConstants.INDEXING_STORAGE_PROVIDER_NAME)
                   .AddMemoryGrainStorage(IndexingConstants.MEMORY_STORAGE_PROVIDER_NAME)
                   .ConfigureApplicationParts(parts => parts.AddApplicationPart(typeof(SiloBuilderExtensions).Assembly))
                   .ConfigureServices(services => services.UseIndexing(indexingOptions))
                   .ConfigureServices((context, services) => ApplicationPartsIndexableGrainLoader.RegisterGrainServices(context, services, indexingOptions))
                   .UseTransactions());
        }
        /// <summary>
        /// Configure silo services to use indexing using a configuration builder.
        /// </summary>
        private static IServiceCollection UseIndexing(this IServiceCollection services, IndexingOptions indexingOptions)
        {
            services.AddOptions <IndexingOptions>(IndexingConstants.INDEXING_OPTIONS_NAME).Configure(options => options.ShallowCopyFrom(indexingOptions));

            services.AddSingleton <IndexFactory>()
            .AddFromExisting <IIndexFactory, IndexFactory>();
            services.AddSingleton <SiloIndexManager>()
            .AddFromExisting <ILifecycleParticipant <ISiloLifecycle>, SiloIndexManager>();
            services.AddFromExisting <IndexManager, SiloIndexManager>();

            // Facet Factory and Mappers
            services.AddTransient <IIndexedStateFactory, IndexedStateFactory>()
            .AddSingleton(typeof(IAttributeToFactoryMapper <NonFaultTolerantWorkflowIndexedStateAttribute>),
                          typeof(NonFaultTolerantWorkflowIndexedStateAttributeMapper))
            .AddSingleton(typeof(IAttributeToFactoryMapper <FaultTolerantWorkflowIndexedStateAttribute>),
                          typeof(FaultTolerantWorkflowIndexedStateAttributeMapper))
            .AddSingleton(typeof(IAttributeToFactoryMapper <TransactionalIndexedStateAttribute>),
                          typeof(TransactionalIndexedStateAttributeMapper));
            return(services);
        }
예제 #3
0
        /// <summary>
        /// This method crawls the assemblies and looks for the index definitions (determined by extending the <see cref="IIndexableGrain{TProperties}"/>
        /// interface and adding annotations to properties in TProperties), and registers the grain services needed for queues and PerSilo partitioning.
        /// </summary>
        /// <remarks>This two-step approach (RegisterGrainServices and then CreateIndexRegistry) is necessary because GrainServices should be
        /// registered to the IServiceCollection before Silo construction and the rest of Index creation requires the IServiceProvider which
        /// is created as part of Silo construction.</remarks>
        /// <returns>An index registry for the silo. </returns>
        internal static void RegisterGrainServices(HostBuilderContext context, IServiceCollection services, IndexingOptions indexingOptions)
        {
            var indexedClasses    = new HashSet <Type>();
            var indexedInterfaces = new HashSet <Type>();

            foreach (var grainClassType in GetIndexedConcreteGrainClasses(context.GetApplicationPartManager()))
            {
                var consistencyScheme = grainClassType.GetConsistencyScheme();
                if (consistencyScheme == ConsistencyScheme.Transactional)
                {
                    continue;
                }

                var indexedInterfacesAndProperties = EnumerateIndexedInterfacesForAGrainClassType(grainClassType).ToList();
                foreach (var(grainInterfaceType, propertiesClassType) in indexedInterfacesAndProperties)
                {
                    if (indexedInterfaces.Contains(grainInterfaceType))
                    {
                        continue;
                    }
                    indexedInterfaces.Add(grainInterfaceType);

                    var createQueues = consistencyScheme != ConsistencyScheme.Transactional;
                    foreach (var propInfo in propertiesClassType.GetProperties())
                    {
                        var indexName  = IndexUtils.PropertyNameToIndexName(propInfo.Name);
                        var indexAttrs = propInfo.GetCustomAttributes <IndexAttribute>(inherit: false);
                        foreach (var indexAttr in indexAttrs)
                        {
                            if (createQueues && !(bool)isEagerProperty.GetValue(indexAttr))
                            {
                                // Queues are per-interface, not per-index.
                                IndexFactory.RegisterIndexWorkflowQueueGrainServices(services, grainInterfaceType, indexingOptions,
                                                                                     consistencyScheme == ConsistencyScheme.FaultTolerantWorkflow);
                            }
                            createQueues = false;

                            var indexType = (Type)indexTypeProperty.GetValue(indexAttr);
                            var regMethod = indexType.GetCustomAttribute <PerSiloIndexGrainServiceClassAttribute>(inherit: false)
                                            ?.GrainServiceClassType
                                            ?.GetMethod("RegisterGrainService", BindingFlags.Static | BindingFlags.NonPublic);
                            if (regMethod != null)  // Static method so cannot use an interface
                            {
                                var regDelegate = (Action <IServiceCollection, Type, string>)Delegate.CreateDelegate(typeof(Action <IServiceCollection, Type, string>), regMethod);
                                regDelegate(services, grainInterfaceType, indexName);
                            }
                        }
                    }
                }
            }
        }
예제 #4
0
 internal static void RegisterIndexWorkflowQueueGrainServices(IServiceCollection services, Type grainInterfaceType, IndexingOptions indexingOptions, bool isFaultTolerant)
 {
     for (int i = 0; i < indexingOptions.NumWorkflowQueuesPerInterface; ++i)
     {
         var seq = i;    // Captured by the lambda
         services.AddGrainService(sp => new IndexWorkflowQueueGrainService(sp.GetRequiredService <SiloIndexManager>(), grainInterfaceType, seq, isFaultTolerant));
         services.AddGrainService(sp => new IndexWorkflowQueueHandlerGrainService(sp.GetRequiredService <SiloIndexManager>(), grainInterfaceType, seq, isFaultTolerant));
     }
 }