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
                                        });
                                    }
                                }
                            }
                        }
        }