private async Task Bail(TransactionalStatus status, bool force = false) { List <Task> pending = new List <Task>(); pending.Add(RWLock.AbortExecutingTransactions()); this.RWLock.AbortQueuedTransactions(); // abort all entries in the commit queue foreach (var entry in commitQueue.Elements) { pending.Add(NotifyOfAbort(entry, status)); } commitQueue.Clear(); await Task.WhenAll(pending); if (++failCounter >= 10 || force) { logger.Debug("StorageWorker triggering grain Deactivation"); this.deactivate(); } await this.Restore(); }
private async Task Bail(TransactionalStatus status, bool force = false) { await RWLock.AbortExecutingTransactions(); // abort all entries in the commit queue foreach (var entry in commitQueue.Elements) { await NotifyOfAbort(entry, status); } commitQueue.Clear(); this.RWLock.AbortQueuedTransactions(); if (++failCounter >= 10 || force) { logger.Debug("StorageWorker triggering grain Deactivation"); this.deactivate(); } else { await this.Restore(); } }
private async Task StorageWork() { try { if (problemFlag != TransactionalStatus.Ok) { RWLock.AbortExecutingTransactions(); // abort all entries in the commit queue foreach (var entry in commitQueue.Elements) { NotifyOfAbort(entry, problemFlag); } commitQueue.Clear(); if (problemFlag == TransactionalStatus.StorageConflict) { logger.Debug("deactivating after storage conflict"); this.deactivate(); this.RWLock.AbortQueuedTransactions(); } else { logger.Debug($"restoring state after status={problemFlag}"); // recover, clear storageFlag, then allow next queued transaction(s) to enter lock await NotifyOfRestore(); } } else { // count committable entries at the bottom of the commit queue int committableEntries = 0; while (committableEntries < commitQueue.Count && commitQueue[committableEntries].ReadyToCommit) { committableEntries++; } // process all committable entries, assembling a storage batch if (committableEntries > 0) { // process all committable entries, adding storage events to the storage batch CollectEventsForBatch(committableEntries); if (problemFlag != TransactionalStatus.Ok) { return; } if (logger.IsEnabled(LogLevel.Debug)) { var r = commitQueue.Count > committableEntries ? commitQueue[committableEntries].ToString() : ""; logger.Debug($"batchcommit={committableEntries} leave={commitQueue.Count - committableEntries} {r}"); } } else { // send or re-send messages and detect timeouts CheckProgressOfCommitQueue(); } // store the current storage batch, if it is not empty StorageBatch <TState> batchBeingSentToStorage = null; if (this.storageBatch.BatchSize > 0) { // get the next batch in place so it can be filled while we store the old one batchBeingSentToStorage = this.storageBatch; this.storageBatch = new StorageBatch <TState>(batchBeingSentToStorage); // perform the actual store, and record the e-tag this.storageBatch.ETag = await batchBeingSentToStorage.Store(storage); } if (committableEntries > 0) { // update stable state var lastCommittedEntry = commitQueue[committableEntries - 1]; this.stableState = lastCommittedEntry.State; this.stableSequenceNumber = lastCommittedEntry.SequenceNumber; if (logger.IsEnabled(LogLevel.Trace)) { logger.Trace($"Stable state version: {this.stableSequenceNumber}"); } // remove committed entries from commit queue commitQueue.RemoveFromFront(committableEntries); storageWorker.Notify(); // we have to re-check for work } if (batchBeingSentToStorage != null) { batchBeingSentToStorage.RunFollowUpActions(); storageWorker.Notify(); // we have to re-check for work } } } catch (InconsistentStateException e) { logger.Warn(888, $"reload from storage triggered by e-tag mismatch {e}"); problemFlag = TransactionalStatus.StorageConflict; } catch (Exception e) { logger.Warn(888, $"exception in storageWorker", e); problemFlag = TransactionalStatus.UnknownException; } finally { if (problemFlag == TransactionalStatus.Ok) { this.failCounter = 0; } else { // after exceptions, we try again, but with limits if (++failCounter < 10) { await Task.Delay(100); // this restarts the worker, which sees the problem flag and recovers. storageWorker.Notify(); } else { // bail out logger.Warn(999, $"storageWorker is bailing out"); } } } }