sql backup

This commit is contained in:
Sedat ÖZTÜRK 2026-04-30 11:54:24 +03:00
parent 2037cfd6d7
commit 054a23bc9d
11 changed files with 40 additions and 24 deletions

2
.gitignore vendored
View file

@ -1,5 +1,5 @@
configs/**/data/**
*.bak
**/node_modules
**/.DS_Store
logs/

View file

@ -59,12 +59,12 @@ public class BackgroundWorkerAppService : PlatformAppService
foreach (var worker in workers)
{
var w = LazyServiceProvider.GetRequiredService<PlatformBackgroundWorker>();
var workerId = worker.Id;
RecurringJob.AddOrUpdate(
RecurringJob.AddOrUpdate<IPlatformBackgroundWorker>(
$"{worker.WorkerType}:{worker.Name}",
"platform",
() => w.StartAsync(worker.Id, default),
(w) => w.StartAsync(workerId, default),
worker.Cron,
new RecurringJobOptions
{

View file

@ -35,6 +35,7 @@ public class FileManagementAppService : ApplicationService, IFileManagementAppSe
// BlobContainerNames.Import,
// BlobContainerNames.Note,
// BlobContainerNames.Intranet
// BlobContainerNames.Backup
};
public FileManagementAppService(

View file

@ -42,6 +42,8 @@ public class BackgroundWorkerSeedDto
public string WorkerType { get; set; }
public bool IsActive { get; set; }
public string DataSourceCode { get; set; }
public string BeforeSp { get; set; }
public string AfterSp { get; set; }
}
public class NotificationRuleSeedDto
@ -435,7 +437,9 @@ public class HostDataSeeder : IDataSeedContributor, ITransientDependency
Cron = item.Cron,
WorkerType = Enum.Parse<WorkerTypeEnum>(item.WorkerType),
IsActive = item.IsActive,
DataSourceCode = item.DataSourceCode
DataSourceCode = item.DataSourceCode,
BeforeSp = item.BeforeSp,
AfterSp = item.AfterSp
});
}
}

View file

@ -20,6 +20,7 @@ using Volo.Abp.Settings;
using Volo.Abp.Users;
using Microsoft.Extensions.Configuration;
using System.IO;
using Volo.Abp.Uow;
namespace Sozsoft.Platform.BackgroundWorkers;
@ -56,6 +57,8 @@ public class PlatformBackgroundWorker : PlatformDomainService, IPlatformBackgrou
public async Task StartAsync(Guid WorkerId, CancellationToken cancellationToken = default)
{
using var uow = LazyServiceProvider.LazyGetRequiredService<IUnitOfWorkManager>().Begin(requiresNew: true, isTransactional: false);
var Worker = await Repository.GetAsync(a => a.Id == WorkerId);
var LogPrefix = $"{Clock.Now:s}_{Worker.Name}: {{0}}";
@ -80,7 +83,7 @@ public class PlatformBackgroundWorker : PlatformDomainService, IPlatformBackgrou
// Backup Worker için yedeklerin saklanacağı klasörün oluşturulması
if (Worker.WorkerType == WorkerTypeEnum.BackupWorker)
{
backupPath = Path.Combine(Configuration["App:CdnPath"], "host", "backup");
backupPath = Configuration["App:BackupPath"];
if (!Directory.Exists(backupPath))
{
Directory.CreateDirectory(backupPath);

View file

@ -6,4 +6,5 @@ public static class BlobContainerNames
public const string Avatar = "avatar";
public const string Import = "import";
public const string Note = "note";
public const string Backup = "backup";
}

View file

@ -7,6 +7,7 @@
"AttachmentsPath": "/etc/api/mail-queue/attachments",
"CdnPath": "/etc/api/cdn",
"BaseDomain": "sozsoft.com",
"BackupPath": "/var/opt/mssql/backup",
"BackupDeleteAfterDays": 3
},
"ConnectionStrings": {

View file

@ -8,6 +8,9 @@ networks:
volumes:
cdn:
api-keys:
sql-backups:
external: true
name: sozsoft-platform-data_sql-backups
services:
migrator:
@ -31,6 +34,7 @@ services:
- 8080:8080
volumes:
- cdn:/etc/api/cdn
- sql-backups:/etc/api/cdn/host/backup
- api-keys:/root/.aspnet/DataProtection-Keys
networks:
- db
@ -53,7 +57,8 @@ services:
profiles: ["ui"]
working_dir: /srv/http-server
volumes:
- cdn:/public:ro
- cdn:/public
- sql-backups:/public/host/backup
command: "/public -c10 --cors"
ports:
- 8081:8080

View file

@ -9,6 +9,7 @@ networks:
volumes:
pg:
mssql:
sql-backups:
services:
redis:
@ -46,5 +47,6 @@ services:
- 1433:1433
volumes:
- mssql:/var/opt/mssql
- sql-backups:/var/opt/mssql/backup
networks:
- db

View file

@ -46,4 +46,4 @@ services:
- 1433:1433
volumes:
- mssql:/var/opt/mssql
- /etc/api/cdn/host/backup:/var/opt/mssql/backup
- ./data/cdn/host/backup:/var/opt/mssql/backup

View file

@ -39,6 +39,8 @@ import type {
import classNames from 'classnames'
import { APP_NAME } from '@/constants/app.constant'
const { VITE_CDN_URL } = import.meta.env
// Select options for sorting
const FileManager = () => {
@ -134,7 +136,7 @@ const FileManager = () => {
const items = response.data.items || []
// Manual protection for system folders
const protectedItems = items.map((item) => {
const isSystemFolder = ['avatar', 'import', 'note'].includes(item.name.toLowerCase())
const isSystemFolder = ['intranet', 'avatar', 'import', 'note', 'backup'].includes(item.name.toLowerCase())
return {
...item,
isReadOnly: item.isReadOnly || isSystemFolder,
@ -373,21 +375,18 @@ const FileManager = () => {
}
}
const handleDownload = async (item: FileItemType) => {
try {
const blob = await fileManagementService.downloadFile(item.id, selectedTenant?.id)
const url = URL.createObjectURL(blob)
const handleDownload = (item: FileItemType) => {
const tenantSegment = selectedTenant?.id ? `tenants/${selectedTenant.id}` : 'host'
const filePath = item.id.replace(/\|/g, '/')
const url = `${VITE_CDN_URL}/${tenantSegment}/${filePath}`
const a = document.createElement('a')
a.href = url
a.download = item.name
a.target = '_blank'
a.rel = 'noopener noreferrer'
document.body.appendChild(a)
a.click()
document.body.removeChild(a)
URL.revokeObjectURL(url)
} catch (error) {
console.error('Download failed:', error)
toast.push(<Notification type="danger">Failed to download file</Notification>)
}
}
// Action handlers