public BatchOperation(ILogger logger, KeyEntity key, CloudTable table) { this.batchOperation = new TableBatchOperation(); this.logger = logger; this.key = key; this.table = table; }
public async Task <TransactionalStorageLoadResponse <TState> > Load() { try { var keyTask = ReadKey(); var statesTask = ReadStates(); key = await keyTask.ConfigureAwait(false); states = await statesTask.ConfigureAwait(false); if (string.IsNullOrEmpty(key.ETag)) { if (logger.IsEnabled(LogLevel.Debug)) { logger.LogDebug($"{partition} Loaded v0, fresh"); } // first time load return(new TransactionalStorageLoadResponse <TState>()); } else { if (!FindState(this.key.CommittedSequenceId, out var pos)) { var error = $"Storage state corrupted: no record for committed state"; logger.LogCritical(error); throw new InvalidOperationException(error); } var committedState = states[pos].Value.GetState <TState>(this.jsonSettings); var PrepareRecordsToRecover = new List <PendingTransactionState <TState> >(); for (int i = 0; i < states.Count; i++) { var kvp = states[i]; // pending states for already committed transactions can be ignored if (kvp.Key <= key.CommittedSequenceId) { continue; } // upon recovery, local non-committed transactions are considered aborted if (kvp.Value.TransactionManager == null) { break; } PrepareRecordsToRecover.Add(new PendingTransactionState <TState>() { SequenceId = kvp.Key, State = kvp.Value.GetState <TState>(this.jsonSettings), TimeStamp = kvp.Value.TransactionTimestamp, TransactionId = kvp.Value.TransactionId, TransactionManager = kvp.Value.TransactionManager }); } // clear the state strings... no longer needed, ok to GC now for (int i = 0; i < states.Count; i++) { states[i].Value.StateJson = null; } if (logger.IsEnabled(LogLevel.Debug)) { logger.LogDebug($"{partition} Loaded v{this.key.CommittedSequenceId} rows={string.Join(",", states.Select(s => s.Key.ToString("x16")))}"); } return(new TransactionalStorageLoadResponse <TState>(this.key.ETag, committedState, this.key.CommittedSequenceId, this.key.Metadata, PrepareRecordsToRecover)); } } catch (Exception ex) { this.logger.LogError("Transactional state load failed {Exception}.", ex); throw; } }