예제 #1
0
        public async Task DeleteAsync(Guid id)
        {
            var job = state.Value.Jobs.FirstOrDefault(x => x.Id == id);

            if (job == null)
            {
                throw new DomainObjectNotFoundException(id.ToString(), typeof(IBackupJob));
            }

            if (currentJob == job)
            {
                currentTask?.Cancel();
            }
            else
            {
                var jobId = job.Id.ToString();

                await Safe.DeleteAsync(backupArchiveLocation, jobId, log);

                await Safe.DeleteAsync(assetStore, jobId, log);

                state.Value.Jobs.Remove(job);

                await state.WriteAsync();
            }
        }
예제 #2
0
        private async Task CleanupAsync()
        {
            await Safe.DeleteAsync(backupArchiveLocation, CurrentJob.Id, log);

            if (CurrentJob.AppId != Guid.Empty)
            {
                foreach (var handler in handlers)
                {
                    await Safe.CleanupRestoreAsync(handler, CurrentJob.AppId, CurrentJob.Id, log);
                }
            }
        }
예제 #3
0
        private async Task CleanupAsync(IEnumerable <BackupHandler> handlers)
        {
            await Safe.DeleteAsync(backupArchiveLocation, CurrentJob.Id.ToString(), log);

            if (CurrentJob.AppId != Guid.Empty)
            {
                foreach (var handler in handlers)
                {
                    await Safe.CleanupRestoreErrorAsync(handler, CurrentJob.AppId, CurrentJob.Id, log);
                }
            }
        }
예제 #4
0
        private async Task RecoverAfterRestartAsync()
        {
            foreach (var job in state.Jobs)
            {
                if (!job.Stopped.HasValue)
                {
                    job.Stopped = clock.GetCurrentInstant();

                    await Safe.DeleteAsync(backupArchiveLocation, job.Id, log);

                    await Safe.DeleteAsync(assetStore, job.Id, log);

                    job.Status = JobStatus.Failed;

                    await WriteAsync();
                }
            }
        }
예제 #5
0
        private async Task ProcessAsync(BackupStateJob job, CancellationToken ct)
        {
            var jobId = job.Id.ToString();

            var handlers = CreateHandlers();

            var lastTimestamp = job.Started;

            try
            {
                using (var stream = await backupArchiveLocation.OpenStreamAsync(jobId))
                {
                    using (var writer = new BackupWriter(serializer, stream, true))
                    {
                        await eventStore.QueryAsync(async storedEvent =>
                        {
                            var @event = eventDataFormatter.Parse(storedEvent.Data);

                            writer.WriteEvent(storedEvent);

                            foreach (var handler in handlers)
                            {
                                await handler.BackupEventAsync(@event, Key, writer);
                            }

                            job.HandledEvents = writer.WrittenEvents;
                            job.HandledAssets = writer.WrittenAttachments;

                            lastTimestamp = await WritePeriodically(lastTimestamp);
                        }, SquidexHeaders.AppId, Key.ToString(), null, ct);

                        foreach (var handler in handlers)
                        {
                            await handler.BackupAsync(Key, writer);
                        }

                        foreach (var handler in handlers)
                        {
                            await handler.CompleteBackupAsync(Key, writer);
                        }
                    }

                    stream.Position = 0;

                    ct.ThrowIfCancellationRequested();

                    await assetStore.UploadAsync(jobId, 0, null, stream, false, ct);
                }

                job.Status = JobStatus.Completed;
            }
            catch (Exception ex)
            {
                log.LogError(ex, jobId, (ctx, w) => w
                             .WriteProperty("action", "makeBackup")
                             .WriteProperty("status", "failed")
                             .WriteProperty("backupId", ctx));

                job.Status = JobStatus.Failed;
            }
            finally
            {
                await Safe.DeleteAsync(backupArchiveLocation, jobId, log);

                job.Stopped = clock.GetCurrentInstant();

                await state.WriteAsync();

                currentTask = null;
                currentJob  = null;
            }
        }
예제 #6
0
        public async Task RunAsync()
        {
            if (currentTask != null)
            {
                throw new DomainException("Another backup process is already running.");
            }

            if (state.Jobs.Count >= MaxBackups)
            {
                throw new DomainException($"You cannot have more than {MaxBackups} backups.");
            }

            var job = new BackupStateJob
            {
                Id      = Guid.NewGuid(),
                Started = clock.GetCurrentInstant(),
                Status  = JobStatus.Started
            };

            currentTask = new CancellationTokenSource();
            currentJob  = job;

            var lastTimestamp = job.Started;

            state.Jobs.Insert(0, job);

            await WriteAsync();

            try
            {
                using (var stream = await backupArchiveLocation.OpenStreamAsync(job.Id))
                {
                    using (var writer = new BackupWriter(serializer, stream, true))
                    {
                        await eventStore.QueryAsync(async storedEvent =>
                        {
                            var @event = eventDataFormatter.Parse(storedEvent.Data);

                            writer.WriteEvent(storedEvent);

                            foreach (var handler in handlers)
                            {
                                await handler.BackupEventAsync(@event, appId, writer);
                            }

                            job.HandledEvents = writer.WrittenEvents;
                            job.HandledAssets = writer.WrittenAttachments;

                            lastTimestamp = await WritePeriodically(lastTimestamp);
                        }, SquidexHeaders.AppId, appId.ToString(), null, currentTask.Token);

                        foreach (var handler in handlers)
                        {
                            await handler.BackupAsync(appId, writer);
                        }

                        foreach (var handler in handlers)
                        {
                            await handler.CompleteBackupAsync(appId, writer);
                        }
                    }

                    stream.Position = 0;

                    currentTask.Token.ThrowIfCancellationRequested();

                    await assetStore.UploadAsync(job.Id.ToString(), 0, null, stream, currentTask.Token);
                }

                job.Status = JobStatus.Completed;
            }
            catch (Exception ex)
            {
                log.LogError(ex, w => w
                             .WriteProperty("action", "makeBackup")
                             .WriteProperty("status", "failed")
                             .WriteProperty("backupId", job.Id.ToString()));

                job.Status = JobStatus.Failed;
            }
            finally
            {
                await Safe.DeleteAsync(backupArchiveLocation, job.Id, log);

                job.Stopped = clock.GetCurrentInstant();

                await WriteAsync();

                currentTask = null;
                currentJob  = null;
            }
        }