コード例 #1
0
ファイル: BackupGrain.cs プロジェクト: xiaopohou/squidex
        public async Task RunAsync()
        {
            if (currentTask != null)
            {
                throw new DomainException("Another backup process is already running.");
            }

            if (state.Value.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;

            state.Value.Jobs.Insert(0, job);

            await state.WriteAsync();

            Process(job, currentTask.Token);
        }
コード例 #2
0
ファイル: BackupGrain.cs プロジェクト: vtan31/squidex
 private async Task CleanupArchiveAsync(BackupStateJob job)
 {
     try
     {
         await backupArchiveLocation.DeleteArchiveAsync(job.Id);
     }
     catch (Exception ex)
     {
         log.LogError(ex, w => w
                      .WriteProperty("action", "deleteArchive")
                      .WriteProperty("status", "failed")
                      .WriteProperty("backupId", job.Id.ToString()));
     }
 }
コード例 #3
0
ファイル: BackupGrain.cs プロジェクト: vtan31/squidex
 private async Task CleanupBackupAsync(BackupStateJob job)
 {
     try
     {
         await assetStore.DeleteAsync(job.Id.ToString(), 0, null);
     }
     catch (Exception ex)
     {
         log.LogError(ex, w => w
                      .WriteProperty("action", "deleteBackup")
                      .WriteProperty("status", "failed")
                      .WriteProperty("backupId", job.Id.ToString()));
     }
 }
コード例 #4
0
ファイル: BackupGrain.cs プロジェクト: vtan31/squidex
        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()
            };

            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 EventStreamWriter(stream))
                    {
                        await eventStore.QueryAsync(async @event =>
                        {
                            var eventData = @event.Data;

                            if (eventData.Type == "AssetCreatedEvent" ||
                                eventData.Type == "AssetUpdatedEvent")
                            {
                                var parsedEvent = eventDataFormatter.Parse(eventData);

                                var assetVersion = 0L;
                                var assetId      = Guid.Empty;

                                if (parsedEvent.Payload is AssetCreated assetCreated)
                                {
                                    assetId      = assetCreated.AssetId;
                                    assetVersion = assetCreated.FileVersion;
                                }

                                if (parsedEvent.Payload is AssetUpdated asetUpdated)
                                {
                                    assetId      = asetUpdated.AssetId;
                                    assetVersion = asetUpdated.FileVersion;
                                }

                                await writer.WriteEventAsync(eventData, async attachmentStream =>
                                {
                                    await assetStore.DownloadAsync(assetId.ToString(), assetVersion, null, attachmentStream);
                                });

                                job.HandledAssets++;
                            }
                            else
                            {
                                await writer.WriteEventAsync(eventData);
                            }

                            job.HandledEvents++;

                            var now = clock.GetCurrentInstant();

                            if ((now - lastTimestamp) >= UpdateDuration)
                            {
                                lastTimestamp = now;

                                await WriteAsync();
                            }
                        }, SquidexHeaders.AppId, appId.ToString(), null, currentTask.Token);
                    }

                    stream.Position = 0;

                    currentTask.Token.ThrowIfCancellationRequested();

                    await assetStore.UploadAsync(job.Id.ToString(), 0, null, stream, currentTask.Token);
                }
            }
            catch (Exception ex)
            {
                log.LogError(ex, w => w
                             .WriteProperty("action", "makeBackup")
                             .WriteProperty("status", "failed")
                             .WriteProperty("backupId", job.Id.ToString()));

                job.IsFailed = true;
            }
            finally
            {
                await CleanupArchiveAsync(job);

                job.Stopped = clock.GetCurrentInstant();

                await WriteAsync();

                currentTask = null;
                currentJob  = null;
            }
        }
コード例 #5
0
ファイル: BackupGrain.cs プロジェクト: xiaopohou/squidex
        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
ファイル: BackupGrain.cs プロジェクト: xiaopohou/squidex
 private void Process(BackupStateJob job, CancellationToken ct)
 {
     ProcessAsync(job, ct).Forget();
 }
コード例 #7
0
ファイル: BackupGrain.cs プロジェクト: purnadika/squidex
        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;
            }
        }
コード例 #8
0
        public async Task StartNewAsync()
        {
            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()
            };

            currentTask = new CancellationTokenSource();
            currentJob  = job;

            state.Jobs.Add(job);

            await WriteAsync();

            try
            {
                using (var stream = await backupArchiveLocation.OpenStreamAsync(job.Id))
                {
                    using (var writer = new EventStreamWriter(stream))
                    {
                        await eventStore.QueryAsync(async @event =>
                        {
                            var eventData = @event.Data;

                            if (eventData.Type == nameof(AssetCreated) ||
                                eventData.Type == nameof(AssetUpdated))
                            {
                                var parsedEvent = eventDataFormatter.Parse(eventData);

                                var assetVersion = 0L;
                                var assetId      = Guid.Empty;

                                if (parsedEvent.Payload is AssetCreated assetCreated)
                                {
                                    assetId      = assetCreated.AssetId;
                                    assetVersion = assetCreated.FileVersion;
                                }

                                if (parsedEvent.Payload is AssetUpdated asetUpdated)
                                {
                                    assetId      = asetUpdated.AssetId;
                                    assetVersion = asetUpdated.FileVersion;
                                }

                                await writer.WriteEventAsync(eventData, async attachmentStream =>
                                {
                                    await assetStore.DownloadAsync(assetId.ToString(), assetVersion, null, attachmentStream);
                                });
                            }
                            else
                            {
                                await writer.WriteEventAsync(eventData);
                            }
                        }, "AppId", appId, null, currentTask.Token);
                    }

                    stream.Position = 0;

                    currentTask.Token.ThrowIfCancellationRequested();

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

                    currentTask.Token.ThrowIfCancellationRequested();
                }
            }
            catch
            {
                job.Failed = true;
            }
            finally
            {
                job.Stopped = clock.GetCurrentInstant();

                await WriteAsync();

                currentTask = null;
                currentJob  = null;
            }
        }
コード例 #9
0
 private async Task CleanupAsync(BackupStateJob job)
 {
     await backupArchiveLocation.DeleteArchiveAsync(job.Id);
 }