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/** configs/**/data/**
*.bak
**/node_modules **/node_modules
**/.DS_Store **/.DS_Store
logs/ logs/

View file

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

View file

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

View file

@ -42,6 +42,8 @@ public class BackgroundWorkerSeedDto
public string WorkerType { get; set; } public string WorkerType { get; set; }
public bool IsActive { get; set; } public bool IsActive { get; set; }
public string DataSourceCode { get; set; } public string DataSourceCode { get; set; }
public string BeforeSp { get; set; }
public string AfterSp { get; set; }
} }
public class NotificationRuleSeedDto public class NotificationRuleSeedDto
@ -435,7 +437,9 @@ public class HostDataSeeder : IDataSeedContributor, ITransientDependency
Cron = item.Cron, Cron = item.Cron,
WorkerType = Enum.Parse<WorkerTypeEnum>(item.WorkerType), WorkerType = Enum.Parse<WorkerTypeEnum>(item.WorkerType),
IsActive = item.IsActive, 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 Volo.Abp.Users;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using System.IO; using System.IO;
using Volo.Abp.Uow;
namespace Sozsoft.Platform.BackgroundWorkers; namespace Sozsoft.Platform.BackgroundWorkers;
@ -56,6 +57,8 @@ public class PlatformBackgroundWorker : PlatformDomainService, IPlatformBackgrou
public async Task StartAsync(Guid WorkerId, CancellationToken cancellationToken = default) 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 Worker = await Repository.GetAsync(a => a.Id == WorkerId);
var LogPrefix = $"{Clock.Now:s}_{Worker.Name}: {{0}}"; 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ı // Backup Worker için yedeklerin saklanacağı klasörün oluşturulması
if (Worker.WorkerType == WorkerTypeEnum.BackupWorker) if (Worker.WorkerType == WorkerTypeEnum.BackupWorker)
{ {
backupPath = Path.Combine(Configuration["App:CdnPath"], "host", "backup"); backupPath = Configuration["App:BackupPath"];
if (!Directory.Exists(backupPath)) if (!Directory.Exists(backupPath))
{ {
Directory.CreateDirectory(backupPath); Directory.CreateDirectory(backupPath);

View file

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

View file

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

View file

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

View file

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

View file

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