private async Task RegisterWorkflowQueues(Type userDefinedIGrain, Type userDefinedGrainImpl) { if (this.IsInSilo) { await IndexFactory.RegisterIndexWorkflowQueues(this.siloIndexManager, userDefinedIGrain, userDefinedGrainImpl); } }
private static bool?CreateIndexesForASingleInterface(ApplicationPartsIndexableGrainLoader loader, IndexRegistry registry, Type propertiesClassType, Type grainInterfaceType, Type grainClassType, ConsistencyScheme consistencyScheme, bool?grainIndexesAreEager) { // All the properties in TProperties are scanned for Index annotation. // If found, the index is created using the information provided in the annotation. var indexesOnInterface = new NamedIndexMap(propertiesClassType); foreach (var propInfo in propertiesClassType.GetProperties()) { var indexAttrs = propInfo.GetCustomAttributes <IndexAttribute>(inherit: false); foreach (var indexAttr in indexAttrs) { var indexName = IndexUtils.PropertyNameToIndexName(propInfo.Name); if (indexesOnInterface.ContainsKey(indexName)) { throw new InvalidOperationException($"An index named {indexName} already exists for user-defined grain interface {grainInterfaceType.Name}"); } var indexType = (Type)indexTypeProperty.GetValue(indexAttr); if (consistencyScheme == ConsistencyScheme.Transactional) { var transactionalVariantAttr = indexType.GetCustomAttribute <TransactionalIndexVariantAttribute>(); if (transactionalVariantAttr != null) { indexType = transactionalVariantAttr.TransactionalIndexType; } } if (indexType.IsGenericTypeDefinition) { // For the (Active|Total) constructors that take (Active|Total)IndexType parameters, leaving the indexType's key type and interface type // generic arguments as "<,>", this fills them in. indexType = indexType.MakeGenericType(propInfo.PropertyType, grainInterfaceType); } // If it's not eager, then it's configured to be lazily updated var isEager = (bool)isEagerProperty.GetValue(indexAttr); if (!grainIndexesAreEager.HasValue) { grainIndexesAreEager = isEager; } var isUnique = (bool)isUniqueProperty.GetValue(indexAttr); ValidateSingleIndex(indexAttr, grainInterfaceType, grainClassType, propertiesClassType, propInfo, grainIndexesAreEager, consistencyScheme, isEager: isEager, isUnique: isUnique); // Multiple bools, so use param names for safety var maxEntriesPerBucket = (int)maxEntriesPerBucketProperty.GetValue(indexAttr); if (loader != null) { loader.CreateIndex(propertiesClassType, grainInterfaceType, indexesOnInterface, propInfo, indexName, indexType, isEager, isUnique, maxEntriesPerBucket); } else { IndexFactory.ValidateIndexType(indexType, propInfo, out _, out _); } } } registry[grainInterfaceType] = indexesOnInterface; return(grainIndexesAreEager); }
private async Task RegisterWorkflowQueues(Type grainInterfaceType, Type grainClassType, bool isFaultTolerant) { if (this.IsInSilo) { await IndexFactory.RegisterIndexWorkflowQueues(this.siloIndexManager, grainInterfaceType, grainClassType, isFaultTolerant); } }
/// <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); } } } } } }