Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 15 additions & 2 deletions BackupJobOptions.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
namespace BackupService;

public enum BackupMode
{
Full,
ArchivesOnly,
RemoteZip
}

public class BackupJobOptions
{
public string Name { get; set; } = "Backup";
Expand All @@ -16,5 +23,11 @@ public class BackupJobOptions
public int? HistoryCopies { get; set; }
public int RetentionDays { get; set; } = 7;
public int OperationTimeoutMinutes { get; set; } = 10;
public int CompletionTimeoutMinutes { get; set; } = 180;
}
public int CompletionTimeoutMinutes { get; set; } = 180;
public BackupMode Mode { get; set; } = BackupMode.Full;
public string? RemoteTriggerUrl { get; set; }

public int RemoteTriggerPollIntervalSeconds { get; set; } = 5;

public int RemoteTriggerTimeoutSeconds { get; set; } = 600;
}
358 changes: 321 additions & 37 deletions FtpBackupRunner.cs

Large diffs are not rendered by default.

48 changes: 48 additions & 0 deletions RemoteTriggerEndpoint/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
using System.IO.Compression;
using System.Threading.Channels;
using Microsoft.Extensions.FileProviders;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddSingleton(Channel.CreateUnbounded<ZipRequest>());
builder.Services.AddHostedService<ZipWorker>();

builder.Services.AddLogging();
builder.Services.AddCors();

var app = builder.Build();

var archivesDir = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "archives");
Directory.CreateDirectory(archivesDir);

app.UseStaticFiles(new StaticFileOptions
{
FileProvider = new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), "wwwroot")),
RequestPath = ""
});

app.MapPost("/trigger", async (TriggerDto dto, Channel<ZipRequest> channel) =>
{
if (dto == null || string.IsNullOrWhiteSpace(dto.SourcePath))
return Results.BadRequest(new { error = "sourcePath is required" });

if (!Directory.Exists(dto.SourcePath))
return Results.BadRequest(new { error = "sourcePath does not exist on server" });

var fileName = string.IsNullOrWhiteSpace(dto.ArchiveName)
? $"{Path.GetFileName(dto.SourcePath).Replace(Path.DirectorySeparatorChar, '_')}-{DateTime.UtcNow:yyyyMMddHHmmss}.zip"
: dto.ArchiveName!;

var outputPath = Path.Combine(archivesDir, fileName);

var req = new ZipRequest(dto.SourcePath, outputPath, dto.Overwrite ?? false);
await channel.Writer.WriteAsync(req);

return Results.Accepted($"/archives/{Uri.EscapeDataString(fileName)}");
});

app.Run();

public record TriggerDto(string SourcePath, string? ArchiveName, bool? Overwrite);

public record ZipRequest(string SourcePath, string OutputPath, bool Overwrite);
7 changes: 7 additions & 0 deletions RemoteTriggerEndpoint/RemoteTriggerEndpoint.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
</Project>
45 changes: 45 additions & 0 deletions RemoteTriggerEndpoint/ZipWorker.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
using System.IO.Compression;
using System.Threading.Channels;

public class ZipWorker : BackgroundService
{
private readonly Channel<ZipRequest> _channel;
private readonly ILogger<ZipWorker> _logger;

public ZipWorker(Channel<ZipRequest> channel, ILogger<ZipWorker> logger)
{
_channel = channel;
_logger = logger;
}

protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
await foreach (var req in _channel.Reader.ReadAllAsync(stoppingToken))
{
try
{
_logger.LogInformation("ZipWorker: creating archive {file}", req.OutputPath);

if (File.Exists(req.OutputPath) && !req.Overwrite)
{
_logger.LogInformation("ZipWorker: {file} already exists and overwrite=false, skipping.", req.OutputPath);
continue;
}

var tmp = req.OutputPath + ".tmp";
if (File.Exists(tmp)) File.Delete(tmp);

ZipFile.CreateFromDirectory(req.SourcePath, tmp, CompressionLevel.Optimal, includeBaseDirectory: false);

if (File.Exists(req.OutputPath)) File.Delete(req.OutputPath);
File.Move(tmp, req.OutputPath);

_logger.LogInformation("ZipWorker: created archive {file}", req.OutputPath);
}
catch (Exception ex)
{
_logger.LogError(ex, "ZipWorker: failed to create archive {file}", req.OutputPath);
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"runtimeTarget": {
"name": ".NETCoreApp,Version=v8.0",
"signature": ""
},
"compilationOptions": {},
"targets": {
".NETCoreApp,Version=v8.0": {
"RemoteTriggerEndpoint/1.0.0": {
"runtime": {
"RemoteTriggerEndpoint.dll": {}
}
}
}
},
"libraries": {
"RemoteTriggerEndpoint/1.0.0": {
"type": "project",
"serviceable": false,
"sha512": ""
}
}
}
Binary file not shown.
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"runtimeOptions": {
"tfm": "net8.0",
"frameworks": [
{
"name": "Microsoft.NETCore.App",
"version": "8.0.0"
},
{
"name": "Microsoft.AspNetCore.App",
"version": "8.0.0"
}
],
"configProperties": {
"System.GC.Server": true,
"System.Runtime.Serialization.EnableUnsafeBinaryFormatterSerialization": false
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"Version":1,"ManifestType":"Build","Endpoints":[]}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

using System;
using System.Reflection;

[assembly: System.Reflection.AssemblyCompanyAttribute("RemoteTriggerEndpoint")]
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0")]
[assembly: System.Reflection.AssemblyProductAttribute("RemoteTriggerEndpoint")]
[assembly: System.Reflection.AssemblyTitleAttribute("RemoteTriggerEndpoint")]
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]

// Wygenerowane przez klasę WriteCodeFragment programu MSBuild.

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
c272ed4b597ee6e8cc88eef93ac227774648223d16434dc024e68a45b8771445
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
is_global = true
build_property.TargetFramework = net8.0
build_property.TargetFrameworkIdentifier = .NETCoreApp
build_property.TargetFrameworkVersion = v8.0
build_property.TargetPlatformMinVersion =
build_property.UsingMicrosoftNETSdkWeb = true
build_property.ProjectTypeGuids =
build_property.InvariantGlobalization =
build_property.PlatformNeutralAssembly =
build_property.EnforceExtendedAnalyzerRules =
build_property._SupportedPlatformList = Linux,macOS,Windows
build_property.RootNamespace = RemoteTriggerEndpoint
build_property.RootNamespace = RemoteTriggerEndpoint
build_property.ProjectDir = C:\Users\tvxma\Desktop\projekty\RemoteBackup-reposytoryArch\RemoteTriggerEndpoint\
build_property.EnableComHosting =
build_property.EnableGeneratedComInterfaceComImportInterop =
build_property.RazorLangVersion = 8.0
build_property.SupportLocalizedComponentNames =
build_property.GenerateRazorMetadataSourceChecksumAttributes =
build_property.MSBuildProjectDirectory = C:\Users\tvxma\Desktop\projekty\RemoteBackup-reposytoryArch\RemoteTriggerEndpoint
build_property._RazorSourceGeneratorDebug =
build_property.EffectiveAnalysisLevelStyle = 8.0
build_property.EnableCodeStyleSeverity =
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// <auto-generated/>
global using Microsoft.AspNetCore.Builder;
global using Microsoft.AspNetCore.Hosting;
global using Microsoft.AspNetCore.Http;
global using Microsoft.AspNetCore.Routing;
global using Microsoft.Extensions.Configuration;
global using Microsoft.Extensions.DependencyInjection;
global using Microsoft.Extensions.Hosting;
global using Microsoft.Extensions.Logging;
global using System;
global using System.Collections.Generic;
global using System.IO;
global using System.Linq;
global using System.Net.Http;
global using System.Net.Http.Json;
global using System.Threading;
global using System.Threading.Tasks;
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
683e58331f2c1cf8d1da9d9ff3c2fc0502cb8a2cfbe359476087724399d7f780
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
C:\Users\tvxma\Desktop\projekty\RemoteBackup-reposytoryArch\RemoteTriggerEndpoint\bin\Debug\net8.0\RemoteTriggerEndpoint.staticwebassets.endpoints.json
C:\Users\tvxma\Desktop\projekty\RemoteBackup-reposytoryArch\RemoteTriggerEndpoint\bin\Debug\net8.0\RemoteTriggerEndpoint.exe
C:\Users\tvxma\Desktop\projekty\RemoteBackup-reposytoryArch\RemoteTriggerEndpoint\bin\Debug\net8.0\RemoteTriggerEndpoint.deps.json
C:\Users\tvxma\Desktop\projekty\RemoteBackup-reposytoryArch\RemoteTriggerEndpoint\bin\Debug\net8.0\RemoteTriggerEndpoint.runtimeconfig.json
C:\Users\tvxma\Desktop\projekty\RemoteBackup-reposytoryArch\RemoteTriggerEndpoint\bin\Debug\net8.0\RemoteTriggerEndpoint.dll
C:\Users\tvxma\Desktop\projekty\RemoteBackup-reposytoryArch\RemoteTriggerEndpoint\bin\Debug\net8.0\RemoteTriggerEndpoint.pdb
C:\Users\tvxma\Desktop\projekty\RemoteBackup-reposytoryArch\RemoteTriggerEndpoint\obj\Debug\net8.0\rpswa.dswa.cache.json
C:\Users\tvxma\Desktop\projekty\RemoteBackup-reposytoryArch\RemoteTriggerEndpoint\obj\Debug\net8.0\RemoteTriggerEndpoint.GeneratedMSBuildEditorConfig.editorconfig
C:\Users\tvxma\Desktop\projekty\RemoteBackup-reposytoryArch\RemoteTriggerEndpoint\obj\Debug\net8.0\RemoteTriggerEndpoint.AssemblyInfoInputs.cache
C:\Users\tvxma\Desktop\projekty\RemoteBackup-reposytoryArch\RemoteTriggerEndpoint\obj\Debug\net8.0\RemoteTriggerEndpoint.AssemblyInfo.cs
C:\Users\tvxma\Desktop\projekty\RemoteBackup-reposytoryArch\RemoteTriggerEndpoint\obj\Debug\net8.0\RemoteTriggerEndpoint.csproj.CoreCompileInputs.cache
C:\Users\tvxma\Desktop\projekty\RemoteBackup-reposytoryArch\RemoteTriggerEndpoint\obj\Debug\net8.0\RemoteTriggerEndpoint.MvcApplicationPartsAssemblyInfo.cache
C:\Users\tvxma\Desktop\projekty\RemoteBackup-reposytoryArch\RemoteTriggerEndpoint\obj\Debug\net8.0\rjimswa.dswa.cache.json
C:\Users\tvxma\Desktop\projekty\RemoteBackup-reposytoryArch\RemoteTriggerEndpoint\obj\Debug\net8.0\rjsmrazor.dswa.cache.json
C:\Users\tvxma\Desktop\projekty\RemoteBackup-reposytoryArch\RemoteTriggerEndpoint\obj\Debug\net8.0\rjsmcshtml.dswa.cache.json
C:\Users\tvxma\Desktop\projekty\RemoteBackup-reposytoryArch\RemoteTriggerEndpoint\obj\Debug\net8.0\scopedcss\bundle\RemoteTriggerEndpoint.styles.css
C:\Users\tvxma\Desktop\projekty\RemoteBackup-reposytoryArch\RemoteTriggerEndpoint\obj\Debug\net8.0\staticwebassets.build.json
C:\Users\tvxma\Desktop\projekty\RemoteBackup-reposytoryArch\RemoteTriggerEndpoint\obj\Debug\net8.0\staticwebassets.build.json.cache
C:\Users\tvxma\Desktop\projekty\RemoteBackup-reposytoryArch\RemoteTriggerEndpoint\obj\Debug\net8.0\staticwebassets.development.json
C:\Users\tvxma\Desktop\projekty\RemoteBackup-reposytoryArch\RemoteTriggerEndpoint\obj\Debug\net8.0\staticwebassets.build.endpoints.json
C:\Users\tvxma\Desktop\projekty\RemoteBackup-reposytoryArch\RemoteTriggerEndpoint\obj\Debug\net8.0\swae.build.ex.cache
C:\Users\tvxma\Desktop\projekty\RemoteBackup-reposytoryArch\RemoteTriggerEndpoint\obj\Debug\net8.0\RemoteTriggerEndpoint.dll
C:\Users\tvxma\Desktop\projekty\RemoteBackup-reposytoryArch\RemoteTriggerEndpoint\obj\Debug\net8.0\refint\RemoteTriggerEndpoint.dll
C:\Users\tvxma\Desktop\projekty\RemoteBackup-reposytoryArch\RemoteTriggerEndpoint\obj\Debug\net8.0\RemoteTriggerEndpoint.pdb
C:\Users\tvxma\Desktop\projekty\RemoteBackup-reposytoryArch\RemoteTriggerEndpoint\obj\Debug\net8.0\RemoteTriggerEndpoint.genruntimeconfig.cache
C:\Users\tvxma\Desktop\projekty\RemoteBackup-reposytoryArch\RemoteTriggerEndpoint\obj\Debug\net8.0\ref\RemoteTriggerEndpoint.dll
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
1651134bb6d3c843ccd52f285d20ffeee9357de5a9d99a2920dc2622d692307d
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"GlobalPropertiesHash":"6iAtOFnl21laiyUNpyBTAO6IYN1zDBOoyxacXNSEYt0=","FingerprintPatternsHash":"gq3WsqcKBUGTSNle7RKKyXRIwh7M8ccEqOqYvIzoM04=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["dodu8R7\u002BM/eyNAahsuLVEsNIgQz7HHZPSC2Zq2DTv/M="],"CachedAssets":{},"CachedCopyCandidates":{}}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"GlobalPropertiesHash":"tz7A8kmttSN9+SL3/NuLsoDvPr4WMTbab6KAU6dljeo=","FingerprintPatternsHash":"gq3WsqcKBUGTSNle7RKKyXRIwh7M8ccEqOqYvIzoM04=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["dodu8R7\u002BM/eyNAahsuLVEsNIgQz7HHZPSC2Zq2DTv/M="],"CachedAssets":{},"CachedCopyCandidates":{}}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"Version":1,"ManifestType":"Build","Endpoints":[]}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"Version":1,"Hash":"IHnFtYJ/J9qzhSAqAkp0ew1KxHR3UkhEc5mdDZjqe2A=","Source":"RemoteTriggerEndpoint","BasePath":"/","Mode":"Root","ManifestType":"Build","ReferencedProjectsConfiguration":[],"DiscoveryPatterns":[],"Assets":[],"Endpoints":[]}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
IHnFtYJ/J9qzhSAqAkp0ew1KxHR3UkhEc5mdDZjqe2A=
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
{
"format": 1,
"restore": {
"C:\\Users\\tvxma\\Desktop\\projekty\\RemoteBackup-reposytoryArch\\RemoteTriggerEndpoint\\RemoteTriggerEndpoint.csproj": {}
},
"projects": {
"C:\\Users\\tvxma\\Desktop\\projekty\\RemoteBackup-reposytoryArch\\RemoteTriggerEndpoint\\RemoteTriggerEndpoint.csproj": {
"version": "1.0.0",
"restore": {
"projectUniqueName": "C:\\Users\\tvxma\\Desktop\\projekty\\RemoteBackup-reposytoryArch\\RemoteTriggerEndpoint\\RemoteTriggerEndpoint.csproj",
"projectName": "RemoteTriggerEndpoint",
"projectPath": "C:\\Users\\tvxma\\Desktop\\projekty\\RemoteBackup-reposytoryArch\\RemoteTriggerEndpoint\\RemoteTriggerEndpoint.csproj",
"packagesPath": "C:\\Users\\tvxma\\.nuget\\packages\\",
"outputPath": "C:\\Users\\tvxma\\Desktop\\projekty\\RemoteBackup-reposytoryArch\\RemoteTriggerEndpoint\\obj\\",
"projectStyle": "PackageReference",
"fallbackFolders": [
"C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages"
],
"configFilePaths": [
"C:\\Users\\tvxma\\AppData\\Roaming\\NuGet\\NuGet.Config",
"C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.FallbackLocation.config",
"C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.Offline.config"
],
"originalTargetFrameworks": [
"net8.0"
],
"sources": {
"C:\\Program Files (x86)\\Microsoft SDKs\\NuGetPackages\\": {},
"C:\\Program Files\\dotnet\\library-packs": {},
"https://api.nuget.org/v3/index.json": {}
},
"frameworks": {
"net8.0": {
"targetAlias": "net8.0",
"projectReferences": {}
}
},
"warningProperties": {
"warnAsError": [
"NU1605"
]
},
"restoreAuditProperties": {
"enableAudit": "true",
"auditLevel": "low",
"auditMode": "direct"
},
"SdkAnalysisLevel": "10.0.100"
},
"frameworks": {
"net8.0": {
"targetAlias": "net8.0",
"imports": [
"net461",
"net462",
"net47",
"net471",
"net472",
"net48",
"net481"
],
"assetTargetFallback": true,
"warn": true,
"frameworkReferences": {
"Microsoft.AspNetCore.App": {
"privateAssets": "none"
},
"Microsoft.NETCore.App": {
"privateAssets": "all"
}
},
"runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\10.0.103/PortableRuntimeIdentifierGraph.json"
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
<RestoreSuccess Condition=" '$(RestoreSuccess)' == '' ">True</RestoreSuccess>
<RestoreTool Condition=" '$(RestoreTool)' == '' ">NuGet</RestoreTool>
<ProjectAssetsFile Condition=" '$(ProjectAssetsFile)' == '' ">$(MSBuildThisFileDirectory)project.assets.json</ProjectAssetsFile>
<NuGetPackageRoot Condition=" '$(NuGetPackageRoot)' == '' ">$(UserProfile)\.nuget\packages\</NuGetPackageRoot>
<NuGetPackageFolders Condition=" '$(NuGetPackageFolders)' == '' ">C:\Users\tvxma\.nuget\packages\;C:\Program Files (x86)\Microsoft Visual Studio\Shared\NuGetPackages</NuGetPackageFolders>
<NuGetProjectStyle Condition=" '$(NuGetProjectStyle)' == '' ">PackageReference</NuGetProjectStyle>
<NuGetToolVersion Condition=" '$(NuGetToolVersion)' == '' ">7.0.0</NuGetToolVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
<SourceRoot Include="C:\Users\tvxma\.nuget\packages\" />
<SourceRoot Include="C:\Program Files (x86)\Microsoft Visual Studio\Shared\NuGetPackages\" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" />
Loading