2022-03-15 18:00:53 +00:00
// (c) Copyright Ascensio System SIA 2010-2022
//
// This program is a free software product.
// You can redistribute it and/or modify it under the terms
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
// any third-party rights.
//
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
//
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
//
// The interactive user interfaces in modified source and object code versions of the Program must
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
//
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
// trademark law for use of our trademarks.
//
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
2022-02-23 12:33:42 +00:00
namespace ASC.Data.Backup.Services ;
[Singletone]
internal sealed class BackupCleanerService : BackgroundService
{
private readonly ILog _logger ;
private readonly TimeSpan _backupCleanerPeriod ;
private readonly IServiceScopeFactory _scopeFactory ;
public BackupCleanerService (
ConfigurationExtension configuration ,
2022-03-17 10:13:52 +00:00
ILog logger ,
2022-02-23 12:33:42 +00:00
IServiceScopeFactory scopeFactory )
{
_scopeFactory = scopeFactory ;
2022-03-17 10:13:52 +00:00
_logger = logger ;
2022-02-23 12:33:42 +00:00
_backupCleanerPeriod = configuration . GetSetting < BackupSettings > ( "backup" ) . Cleaner . Period ;
}
protected override async Task ExecuteAsync ( CancellationToken stoppingToken )
{
2022-02-24 14:15:39 +00:00
_logger . Debug ( "BackupCleanerService is starting." ) ;
2022-02-23 12:33:42 +00:00
2022-02-24 14:15:39 +00:00
stoppingToken . Register ( ( ) = > _logger . Debug ( "#1 BackupCleanerService background task is stopping." ) ) ;
while ( ! stoppingToken . IsCancellationRequested )
2022-02-23 12:33:42 +00:00
{
2022-02-24 14:15:39 +00:00
_logger . Debug ( "BackupCleanerService background task is doing background work." ) ;
2022-02-23 12:33:42 +00:00
2022-02-24 15:01:32 +00:00
using var serviceScope = _scopeFactory . CreateScope ( ) ;
var registerInstanceService = serviceScope . ServiceProvider . GetService < IRegisterInstanceManager < BackupCleanerService > > ( ) ;
if ( ! await registerInstanceService . IsActive ( RegisterInstanceWorkerService < BackupCleanerService > . InstanceId ) )
{
_logger . Debug ( $"BackupCleanerService background task with instance id {RegisterInstanceWorkerService<BackupCleanerService>.InstanceId} is't active." ) ;
await Task . Delay ( 1000 , stoppingToken ) ;
continue ;
}
ExecuteBackupCleaner ( stoppingToken ) ;
2022-02-23 12:33:42 +00:00
2022-02-24 14:15:39 +00:00
await Task . Delay ( _backupCleanerPeriod , stoppingToken ) ;
}
2022-02-23 12:33:42 +00:00
2022-02-24 14:15:39 +00:00
_logger . Debug ( "BackupCleanerService background task is stopping." ) ;
}
2022-02-23 12:33:42 +00:00
2022-02-24 15:01:32 +00:00
private void ExecuteBackupCleaner ( CancellationToken stoppingToken )
2022-02-24 14:15:39 +00:00
{
using var serviceScope = _scopeFactory . CreateScope ( ) ;
2022-02-23 12:33:42 +00:00
2022-02-24 14:15:39 +00:00
var backupRepository = serviceScope . ServiceProvider . GetRequiredService < BackupRepository > ( ) ;
var backupStorageFactory = serviceScope . ServiceProvider . GetRequiredService < BackupStorageFactory > ( ) ;
2022-02-23 12:33:42 +00:00
2022-02-24 14:15:39 +00:00
_logger . Debug ( "started to clean expired backups" ) ;
2022-02-23 12:33:42 +00:00
2022-02-24 14:15:39 +00:00
var backupsToRemove = backupRepository . GetExpiredBackupRecords ( ) ;
_logger . DebugFormat ( "found {0} backups which are expired" , backupsToRemove . Count ) ;
foreach ( var scheduledBackups in backupRepository . GetScheduledBackupRecords ( ) . GroupBy ( r = > r . TenantId ) )
{
if ( stoppingToken . IsCancellationRequested ) return ;
var schedule = backupRepository . GetBackupSchedule ( scheduledBackups . Key ) ;
if ( schedule ! = null )
{
var scheduledBackupsToRemove = scheduledBackups . OrderByDescending ( r = > r . CreatedOn ) . Skip ( schedule . BackupsStored ) . ToList ( ) ;
if ( scheduledBackupsToRemove . Any ( ) )
2022-02-23 12:33:42 +00:00
{
2022-02-24 14:15:39 +00:00
_logger . DebugFormat ( "only last {0} scheduled backup records are to keep for tenant {1} so {2} records must be removed" , schedule . BackupsStored , schedule . TenantId , scheduledBackupsToRemove . Count ) ;
backupsToRemove . AddRange ( scheduledBackupsToRemove ) ;
2022-02-23 12:33:42 +00:00
}
}
2022-02-24 14:15:39 +00:00
else
2022-02-23 12:33:42 +00:00
{
2022-02-24 14:15:39 +00:00
backupsToRemove . AddRange ( scheduledBackups ) ;
}
}
2022-02-23 12:33:42 +00:00
2022-02-24 14:15:39 +00:00
foreach ( var backupRecord in backupsToRemove )
{
if ( stoppingToken . IsCancellationRequested ) return ;
2022-02-23 12:33:42 +00:00
2022-02-24 14:15:39 +00:00
try
{
var backupStorage = backupStorageFactory . GetBackupStorage ( backupRecord ) ;
if ( backupStorage = = null ) continue ;
2022-02-23 12:33:42 +00:00
2022-02-24 14:15:39 +00:00
backupStorage . Delete ( backupRecord . StoragePath ) ;
2022-02-23 12:33:42 +00:00
2022-02-24 14:15:39 +00:00
backupRepository . DeleteBackupRecord ( backupRecord . Id ) ;
}
catch ( ProviderInfoArgumentException error )
{
_logger . Warn ( "can't remove backup record " + backupRecord . Id , error ) ;
if ( DateTime . UtcNow > backupRecord . CreatedOn . AddMonths ( 6 ) )
2022-02-23 12:33:42 +00:00
{
2022-02-24 14:15:39 +00:00
backupRepository . DeleteBackupRecord ( backupRecord . Id ) ;
2022-02-23 12:33:42 +00:00
}
}
2022-02-24 14:15:39 +00:00
catch ( Exception error )
{
_logger . Warn ( "can't remove backup record: " + backupRecord . Id , error ) ;
}
2022-02-23 12:33:42 +00:00
}
2022-02-24 14:15:39 +00:00
2022-02-23 12:33:42 +00:00
}
}