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 static Task <bool?> CreateIndexesForASingleInterface(ApplicationPartsIndexableGrainLoader loader, IndexRegistry registry, Type propertiesArgType, Type userDefinedIGrain, Type userDefinedGrainImpl, 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. NamedIndexMap indexesOnGrain = new NamedIndexMap(); var interfaceHasLazyIndex = false; // Use a separate value from grainIndexesAreEager in case we change to allow mixing eager and lazy on a single grain. foreach (PropertyInfo propInfo in propertiesArgType.GetProperties()) { var indexAttrs = propInfo.GetCustomAttributes <IndexAttribute>(inherit: false); foreach (var indexAttr in indexAttrs) { string indexName = "__" + propInfo.Name; if (indexesOnGrain.ContainsKey(indexName)) { throw new InvalidOperationException($"An index named {indexName} already exists for user-defined grain interface {userDefinedIGrain.Name}"); } Type indexType = (Type)indexTypeProperty.GetValue(indexAttr); if (indexType.IsGenericTypeDefinition) { indexType = indexType.MakeGenericType(propInfo.PropertyType, userDefinedIGrain); } // If it's not eager, then it's configured to be lazily updated bool isEager = (bool)isEagerProperty.GetValue(indexAttr); if (!isEager) { interfaceHasLazyIndex = true; } if (!grainIndexesAreEager.HasValue) { grainIndexesAreEager = isEager; } bool isUnique = (bool)isUniqueProperty.GetValue(indexAttr); ValidateSingleIndex(indexAttr, userDefinedIGrain, userDefinedGrainImpl, propertiesArgType, propInfo, grainIndexesAreEager, isEager, isUnique); int maxEntriesPerBucket = (int)maxEntriesPerBucketProperty.GetValue(indexAttr); if (loader != null) { await loader.CreateIndex(propertiesArgType, userDefinedIGrain, indexesOnGrain, propInfo, indexName, indexType, isEager, isUnique, maxEntriesPerBucket); } } } registry[userDefinedIGrain] = indexesOnGrain; if (interfaceHasLazyIndex && loader != null) { await loader.RegisterWorkflowQueues(userDefinedIGrain, userDefinedGrainImpl); } return(grainIndexesAreEager); }