private async Task PersistState() { //create a write-request ID, which is used for group commit int writeRequestId = ++_writeRequestIdGen; //add the write-request ID to the pending write requests _pendingWriteRequests.Add(writeRequestId); //wait before any previous write is done using (await _writeLock.LockAsync()) { // If the write request is not there, it was handled by another worker before we obtained the lock. if (_pendingWriteRequests.Contains(writeRequestId)) { //clear all pending write requests, as this attempt will do them all. _pendingWriteRequests.Clear(); //write the state back to the storage unconditionally var grainTypeName = "Orleans.Indexing.IndexWorkflowQueue-" + IndexUtils.GetFullTypeName(_grainInterfaceType); var saveETag = this.queueState.ETag; try { this.queueState.ETag = StorageProviderUtils.ANY_ETAG; await StorageProvider.WriteStateAsync(grainTypeName, _lazyParent.Value, this.queueState); } finally { if (this.queueState.ETag == StorageProviderUtils.ANY_ETAG) { this.queueState.ETag = saveETag; } } } } }
private static void ValidateSingleIndex(IndexAttribute indexAttr, Type grainInterfaceType, Type grainClassType, Type propertiesArgType, PropertyInfo propInfo, bool?grainIndexesAreEager, ConsistencyScheme consistencyScheme, bool isEager, bool isUnique) { var indexType = (Type)indexTypeProperty.GetValue(indexAttr); var isTotalIndex = indexType.IsTotalIndex(); var isPerSiloIndex = indexType.IsPartitionedPerSiloIndex(); var isFaultTolerantWorkflow = consistencyScheme == ConsistencyScheme.FaultTolerantWorkflow; if (indexAttr is ActiveIndexAttribute && isUnique) { // See comments in ActiveIndexAttribute for details of why this is disallowed. throw new InvalidOperationException($"An active Index cannot be configured to be unique, because multiple activations, persisting, and deactivations can create duplicates." + $" Active Index of type {IndexUtils.GetFullTypeName(indexType)} is defined to be unique on property {propInfo.Name}" + $" of class {IndexUtils.GetFullTypeName(propertiesArgType)} on {IndexUtils.GetFullTypeName(grainInterfaceType)} grain interface."); } if (isPerSiloIndex && isUnique) { throw new InvalidOperationException($"Unique indexes cannot be partitioned per silo because uniqueness across silos is currently not enforced." + $" Partitioned Per Silo Index of type {IndexUtils.GetFullTypeName(indexType)} is defined to be unique on property {propInfo.Name}" + $" of class {IndexUtils.GetFullTypeName(propertiesArgType)} on {IndexUtils.GetFullTypeName(grainInterfaceType)} grain interface."); } if (isFaultTolerantWorkflow && isEager) { throw new InvalidOperationException($"A workflow-fault-tolerant grain implementation cannot be configured to eagerly update its indexes." + $" The only option for updating the indexes of a fault-tolerant indexable grain is lazy updating." + $" The index of type {IndexUtils.GetFullTypeName(indexType)} is defined to be updated eagerly on property {propInfo.Name}" + $" of class {IndexUtils.GetFullTypeName(propertiesArgType)} on {IndexUtils.GetFullTypeName(grainClassType)} grain implementation class."); } if (isFaultTolerantWorkflow && indexType.IsActiveIndex()) { throw new InvalidOperationException($"An Active index cannot be workflow-fault-tolerant, because it will continually be reactivated as part of the fault-tolerant workflow." + $" The Active index of type {IndexUtils.GetFullTypeName(indexType)} on property {propInfo.Name}" + $" of class {IndexUtils.GetFullTypeName(propertiesArgType)} on {IndexUtils.GetFullTypeName(grainClassType)} grain implementation class" + $" which uses workflow-fault-tolerant indexing."); } if (grainIndexesAreEager.HasValue && grainIndexesAreEager.Value != isEager) { throw new InvalidOperationException($"Some indexes on {IndexUtils.GetFullTypeName(grainClassType)} grain implementation class are defined as eager while others are lazy." + $" The index of type {IndexUtils.GetFullTypeName(indexType)} is defined to be updated {(isEager ? "eagerly" : "lazily")} on property { propInfo.Name}" + $" of property class {IndexUtils.GetFullTypeName(propertiesArgType)} on {IndexUtils.GetFullTypeName(grainInterfaceType)} grain interface," + $" while previous indexes have been configured to be updated {(isEager ? "lazily" : "eagerly")}." + $" You must fix this by configuring all indexes to be updated lazily or eagerly." + $" Note: If you have at least one Total Index among your indexes, this must be lazy, and thus all other indexes must be lazy also."); } if (!VerifyNullValue(propInfo, isUnique, out string convertErrMsg)) { throw new InvalidOperationException($"The index of type {IndexUtils.GetFullTypeName(indexType)} on {IndexUtils.GetFullTypeName(grainClassType)} grain implementation class" + $" failed verification. " + convertErrMsg); } }
private static void ValidateSingleIndex(IndexAttribute indexAttr, Type userDefinedIGrain, Type userDefinedGrainImpl, Type propertiesArgType, PropertyInfo propInfo, bool?grainIndexesAreEager, bool isEager, bool isUnique) { bool isFaultTolerant = IsSubclassOfRawGenericType(typeof(IndexableGrain <,>), userDefinedGrainImpl); Type indexType = (Type)indexTypeProperty.GetValue(indexAttr); bool isTotalIndex = typeof(ITotalIndex).IsAssignableFrom(indexType); if (indexAttr is ActiveIndexAttribute && isUnique) { // See comments in ActiveIndexAttribute for details of why this is disallowed. throw new InvalidOperationException($"An active Index cannot be configured to be unique, because multiple activations, persisting, and deactivations can create duplicates." + $" Active Index of type {IndexUtils.GetFullTypeName(indexType)} is defined to be unique on property {propInfo.Name}" + $" of class {IndexUtils.GetFullTypeName(propertiesArgType)} on {IndexUtils.GetFullTypeName(userDefinedIGrain)} grain interface."); } if (isTotalIndex && isEager) { throw new InvalidOperationException($"A Total Index cannot be configured to be updated eagerly. The only option for updating a Total Index is lazy updating." + $" Total Index of type {IndexUtils.GetFullTypeName(indexType)} is defined to be updated eagerly on property {propInfo.Name}" + $" of class {IndexUtils.GetFullTypeName(propertiesArgType)} on {IndexUtils.GetFullTypeName(userDefinedIGrain)} grain interface."); } if (isFaultTolerant && isEager) { throw new InvalidOperationException($"A fault-tolerant grain implementation cannot be configured to eagerly update its indexes." + $" The only option for updating the indexes of a fault-tolerant indexable grain is lazy updating." + $" The index of type {IndexUtils.GetFullTypeName(indexType)} is defined to be updated eagerly on property {propInfo.Name}" + $" of class {IndexUtils.GetFullTypeName(propertiesArgType)} on {IndexUtils.GetFullTypeName(userDefinedGrainImpl)} grain implementation class."); } if (grainIndexesAreEager.HasValue && grainIndexesAreEager.Value != isEager) { throw new InvalidOperationException($"Some indexes on {IndexUtils.GetFullTypeName(userDefinedGrainImpl)} grain implementation class are defined as eager while others are lazy." + $" The index of type {IndexUtils.GetFullTypeName(indexType)} is defined to be updated {(isEager ? "eagerly" : "lazily")} on property { propInfo.Name}" + $" of property class {IndexUtils.GetFullTypeName(propertiesArgType)} on {IndexUtils.GetFullTypeName(userDefinedIGrain)} grain interface," + $" while previous indexs have been configured to be updated {(isEager ? "lazily" : "eagerly")}." + $" You must fix this by configuring all indexes to be updated lazily or eagerly." + $" Note: If you have at least one Total Index among your indexes, this must be lazy, and thus all other indexes must be lazy also."); } if (!VerifyNullValue(propInfo, isUnique, out string convertErrMsg)) { throw new InvalidOperationException($"The index of type {IndexUtils.GetFullTypeName(indexType)} on {IndexUtils.GetFullTypeName(userDefinedGrainImpl)} grain implementation class" + $" failed verification. " + convertErrMsg); } }
internal IndexWorkflowQueueBase(SiloIndexManager siloIndexManager, Type grainInterfaceType, int queueSequenceNumber, SiloAddress silo, bool isDefinedAsFaultTolerantGrain, Func <GrainReference> parentFunc, GrainReference recoveryGrainReference = null) { queueState = new IndexWorkflowQueueState(); _grainInterfaceType = grainInterfaceType; _queueSeqNum = queueSequenceNumber; _grainTypeName = "Orleans.Indexing.IndexWorkflowQueue-" + IndexUtils.GetFullTypeName(_grainInterfaceType); _workflowRecordsTail = null; __handler = null; _isHandlerWorkerIdle = 1; _isDefinedAsFaultTolerantGrain = isDefinedAsFaultTolerantGrain; this._recoveryGrainReference = recoveryGrainReference; _writeLock = new AsyncLock(); _writeRequestIdGen = 0; _pendingWriteRequests = new HashSet <int>(); _silo = silo; SiloIndexManager = siloIndexManager; _lazyParent = new Lazy <GrainReference>(parentFunc, true); }
internal async static Task <IndexRegistry> GetIndexRegistry(ApplicationPartsIndexableGrainLoader loader, Type[] grainTypes) { var registry = new IndexRegistry(); foreach (var grainType in grainTypes) { if (registry.ContainsKey(grainType)) { throw new InvalidOperationException($"Precondition violated: GetGrainClassIndexes should not encounter a duplicate type ({IndexUtils.GetFullTypeName(grainType)})"); } await GetIndexesForASingleGrainType(loader, registry, grainType); } return(registry); }
internal static IndexRegistry GetIndexRegistry(ApplicationPartsIndexableGrainLoader loader, IEnumerable <Type> grainClassTypes) { var registry = new IndexRegistry(); foreach (var grainClassType in grainClassTypes) { if (registry.ContainsGrainType(grainClassType)) { throw new InvalidOperationException($"Precondition violated: GetIndexRegistry should not encounter a duplicate grain class type ({IndexUtils.GetFullTypeName(grainClassType)})"); } GetIndexesForASingleGrainType(loader, registry, grainClassType); } return(registry); }
public static string CreateIndexWorkflowQueuePrimaryKey(Type grainInterfaceType, int queueSeqNum) => IndexUtils.GetFullTypeName(grainInterfaceType) + "-" + queueSeqNum;