internal static async IAsyncEnumerable <ReplayProgress> ReplayAsync(DocumentDatabase database, Stream replayStream) { using (var txs = new ReplayTxs()) using (database.DocumentsStorage.ContextPool.AllocateOperationContext(out DocumentsOperationContext context)) using (context.GetMemoryBuffer(out var buffer)) await using (var gZipStream = new GZipStream(replayStream, CompressionMode.Decompress, leaveOpen: true)) { var peepingTomStream = new PeepingTomStream(gZipStream, context); var state = new JsonParserState(); var parser = new UnmanagedJsonParser(context, state, "file"); var commandsProgress = 0L; var readers = UnmanagedJsonParserHelper.ReadArrayToMemoryAsync(context, peepingTomStream, parser, state, buffer); await using (var readersItr = readers.GetAsyncEnumerator()) { await ReadStartRecordingDetailsAsync(readersItr, context, peepingTomStream); while (await readersItr.MoveNextAsync()) { using (readersItr.Current) { if (readersItr.Current.TryGet(nameof(RecordingDetails.Type), out string strType) == false) { throw new ReplayTransactionsException($"Can't read {nameof(RecordingDetails.Type)} of replay detail", peepingTomStream); } if (Enum.TryParse <TxInstruction>(strType, true, out var type)) { switch (type) { case TxInstruction.BeginTx: database.DocumentsStorage.ContextPool.AllocateOperationContext(out txs.TxCtx); txs.TxCtx.OpenWriteTransaction(); break; case TxInstruction.Commit: txs.TxCtx.Transaction.Commit(); break; case TxInstruction.DisposeTx: txs.TxCtx.Dispose(); txs.TxCtx = null; break; case TxInstruction.BeginAsyncCommitAndStartNewTransaction: txs.PrevTx = txs.TxCtx.Transaction; txs.TxCtx.Transaction = txs.TxCtx.Transaction.BeginAsyncCommitAndStartNewTransaction(txs.TxCtx); break; case TxInstruction.EndAsyncCommit: txs.PrevTx.EndAsyncCommit(); break; case TxInstruction.DisposePrevTx: txs.PrevTx.Dispose(); txs.PrevTx = null; break; } continue; } try { var cmd = DeserializeCommand(context, database, strType, readersItr.Current, peepingTomStream); commandsProgress += cmd.ExecuteDirectly(txs.TxCtx); database.TxMerger.UpdateGlobalReplicationInfoBeforeCommit(txs.TxCtx); } catch (Exception) { //TODO To accept exceptions that was thrown while recording throw; } yield return(new ReplayProgress { CommandsProgress = commandsProgress }); } } } } }