From bb7de7f9d197b9a83f2a0954d6ec3486e3830ceb Mon Sep 17 00:00:00 2001
From: cocoa-dev004 <66989461+cocoa-dev004@users.noreply.github.com>
Date: Mon, 11 Jul 2022 16:17:12 +0900
Subject: [PATCH 1/2] Rotate event logs
---
.../Covid19Radar.Android.csproj | 1 +
.../Covid19Radar.Android/MainApplication.cs | 14 ++
.../DataMaintainanceBackgroundService.cs | 107 ++++++++++
.../Migration/MigrationProcessService.cs | 5 +
.../Services/Migration/WorkManagerMigrator.cs | 5 +
Covid19Radar/Covid19Radar.iOS/AppDelegate.cs | 14 ++
.../Covid19Radar.iOS/Covid19Radar.iOS.csproj | 1 +
Covid19Radar/Covid19Radar.iOS/Info.plist | 1 +
.../DataMaintainanceBackgroundService.cs | 112 ++++++++++
.../EventLogSubmissionBackgroundService.cs | 7 +
Covid19Radar/Covid19Radar/App.xaml.cs | 14 +-
.../Covid19Radar/Common/AppConstants.cs | 5 +
.../Repository/EventLogRepository.cs | 90 ++++++--
.../AbsDataMaintainanceBackgroundService.cs | 44 ++++
.../ViewModels/Settings/DebugPageViewModel.cs | 5 +
.../Views/Settings/DebugPage.xaml | 4 +
.../Repository/EventLogRepositoryTests.cs | 198 ++++++++++++++++++
17 files changed, 612 insertions(+), 15 deletions(-)
create mode 100644 Covid19Radar/Covid19Radar.Android/Services/DataMaintainanceBackgroundService.cs
create mode 100644 Covid19Radar/Covid19Radar.iOS/Services/DataMaintainanceBackgroundService.cs
create mode 100644 Covid19Radar/Covid19Radar/Services/AbsDataMaintainanceBackgroundService.cs
create mode 100644 Covid19Radar/Tests/Covid19Radar.UnitTests/Repository/EventLogRepositoryTests.cs
diff --git a/Covid19Radar/Covid19Radar.Android/Covid19Radar.Android.csproj b/Covid19Radar/Covid19Radar.Android/Covid19Radar.Android.csproj
index ad99d5244..70ff8a800 100644
--- a/Covid19Radar/Covid19Radar.Android/Covid19Radar.Android.csproj
+++ b/Covid19Radar/Covid19Radar.Android/Covid19Radar.Android.csproj
@@ -193,6 +193,7 @@
+
diff --git a/Covid19Radar/Covid19Radar.Android/MainApplication.cs b/Covid19Radar/Covid19Radar.Android/MainApplication.cs
index b2d213f2b..4a26647bb 100644
--- a/Covid19Radar/Covid19Radar.Android/MainApplication.cs
+++ b/Covid19Radar/Covid19Radar.Android/MainApplication.cs
@@ -49,6 +49,9 @@ private Lazy _exposureDetectionBackground
private readonly Lazy _eventLogSubmissionBackgroundService
= new Lazy(() => ContainerLocator.Current.Resolve());
+ private Lazy _dataMaintainanceService
+ = new Lazy(() => ContainerLocator.Current.Resolve());
+
private Lazy _loggerService
= new Lazy(() => ContainerLocator.Current.Resolve());
@@ -98,6 +101,7 @@ private void ScheduleBackgroundTasks()
{
_loggerService.Value.Exception("Failed to schedule ExposureDetectionBackgroundService", exception);
}
+
try
{
_eventLogSubmissionBackgroundService.Value.Schedule();
@@ -106,6 +110,15 @@ private void ScheduleBackgroundTasks()
{
_loggerService.Value.Exception("Failed to schedule EventLogSubmissionBackgroundService", exception);
}
+
+ try
+ {
+ _dataMaintainanceService.Value.Schedule();
+ }
+ catch (Exception exception)
+ {
+ _loggerService.Value.Exception("Failed to schedule DataMaintainanceBackgroundService", exception);
+ }
}
private void SetupENClient(ExposureNotificationClient client)
@@ -141,6 +154,7 @@ private void RegisterPlatformTypes(IContainer container)
container.Register(Reuse.Singleton);
container.Register(Reuse.Singleton);
container.Register(Reuse.Singleton);
+ container.Register(Reuse.Singleton);
}
public Task GetExposureConfigurationAsync()
diff --git a/Covid19Radar/Covid19Radar.Android/Services/DataMaintainanceBackgroundService.cs b/Covid19Radar/Covid19Radar.Android/Services/DataMaintainanceBackgroundService.cs
new file mode 100644
index 000000000..33788b0f1
--- /dev/null
+++ b/Covid19Radar/Covid19Radar.Android/Services/DataMaintainanceBackgroundService.cs
@@ -0,0 +1,107 @@
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at https://mozilla.org/MPL/2.0/.
+
+using System;
+using Android.Content;
+using Android.Runtime;
+using AndroidX.Work;
+using Covid19Radar.Repository;
+using Covid19Radar.Services;
+using Covid19Radar.Services.Logs;
+using Java.Util.Concurrent;
+using Prism.Ioc;
+using Xamarin.Essentials;
+
+namespace Covid19Radar.Droid.Services
+{
+ public class DataMaintainanceBackgroundService : AbsDataMaintainanceBackgroundService
+ {
+ private const string CURRENT_WORK_NAME = "data_maintainance_worker_20220628";
+
+ private const long INTERVAL_IN_HOURS = 24;
+ private const long BACKOFF_DELAY_IN_MINUTES = 60;
+
+ public DataMaintainanceBackgroundService(
+ ILoggerService loggerService,
+ IEventLogRepository eventLogRepository
+ ) : base(loggerService, eventLogRepository)
+ {
+ // do nothing
+ }
+
+ public override void Schedule()
+ {
+ LoggerService.StartMethod();
+
+ WorkManager workManager = WorkManager.GetInstance(Platform.AppContext);
+
+ PeriodicWorkRequest periodicWorkRequest = CreatePeriodicWorkRequest();
+ workManager.EnqueueUniquePeriodicWork(
+ CURRENT_WORK_NAME,
+ ExistingPeriodicWorkPolicy.Keep,
+ periodicWorkRequest
+ );
+
+ LoggerService.EndMethod();
+ }
+
+ private PeriodicWorkRequest CreatePeriodicWorkRequest()
+ {
+ var workRequestBuilder = new PeriodicWorkRequest.Builder(
+ typeof(DataMaintainanceBackgroundWorker),
+ INTERVAL_IN_HOURS, TimeUnit.Hours
+ )
+ .SetConstraints(new Constraints.Builder()
+ .SetRequiresBatteryNotLow(true)
+ .Build())
+ .SetBackoffCriteria(BackoffPolicy.Linear, BACKOFF_DELAY_IN_MINUTES, TimeUnit.Minutes);
+ return workRequestBuilder.Build();
+ }
+ }
+
+ [Preserve]
+ public class DataMaintainanceBackgroundWorker : Worker
+ {
+ private Lazy _dataMaintainanceBackgroundService
+ => new Lazy(() => ContainerLocator.Current.Resolve());
+ private Lazy _loggerService => new Lazy(() => ContainerLocator.Current.Resolve());
+
+ public DataMaintainanceBackgroundWorker(Context context, WorkerParameters workerParameters)
+ : base(context, workerParameters)
+ {
+ // do nothing
+ }
+
+ public override Result DoWork()
+ {
+ var dataMaintainanceBackgroundService = _dataMaintainanceBackgroundService.Value;
+ var loggerService = _loggerService.Value;
+
+ loggerService.StartMethod();
+
+ try
+ {
+ dataMaintainanceBackgroundService.ExecuteAsync().GetAwaiter().GetResult();
+ return Result.InvokeSuccess();
+ }
+ catch (Exception exception)
+ {
+ loggerService.Exception("Exception", exception);
+ return Result.InvokeFailure();
+ }
+ finally
+ {
+ loggerService.EndMethod();
+ }
+ }
+
+ public override void OnStopped()
+ {
+ base.OnStopped();
+
+ _loggerService.Value.Warning("OnStopped");
+ }
+ }
+}
+
diff --git a/Covid19Radar/Covid19Radar.Android/Services/Migration/MigrationProcessService.cs b/Covid19Radar/Covid19Radar.Android/Services/Migration/MigrationProcessService.cs
index 9ee3dbbbb..a9209cafe 100644
--- a/Covid19Radar/Covid19Radar.Android/Services/Migration/MigrationProcessService.cs
+++ b/Covid19Radar/Covid19Radar.Android/Services/Migration/MigrationProcessService.cs
@@ -69,14 +69,18 @@ public override Result DoWork()
public class MigrationProccessService : IMigrationProcessService
{
private readonly AbsExposureDetectionBackgroundService _exposureDetectionBackgroundService;
+ private readonly AbsDataMaintainanceBackgroundService _dataMaintainanceBackgroundService;
+
private readonly ILoggerService _loggerService;
public MigrationProccessService(
AbsExposureDetectionBackgroundService exposureDetectionBackgroundService,
+ AbsDataMaintainanceBackgroundService dataMaintainanceBackgroundService,
ILoggerService loggerService
)
{
_exposureDetectionBackgroundService = exposureDetectionBackgroundService;
+ _dataMaintainanceBackgroundService = dataMaintainanceBackgroundService;
_loggerService = loggerService;
}
@@ -86,6 +90,7 @@ public async Task SetupAsync()
await new WorkManagerMigrator(
_exposureDetectionBackgroundService,
+ _dataMaintainanceBackgroundService,
_loggerService
).ExecuteAsync();
diff --git a/Covid19Radar/Covid19Radar.Android/Services/Migration/WorkManagerMigrator.cs b/Covid19Radar/Covid19Radar.Android/Services/Migration/WorkManagerMigrator.cs
index c0e02ee8a..5fc117812 100644
--- a/Covid19Radar/Covid19Radar.Android/Services/Migration/WorkManagerMigrator.cs
+++ b/Covid19Radar/Covid19Radar.Android/Services/Migration/WorkManagerMigrator.cs
@@ -19,14 +19,18 @@ internal class WorkManagerMigrator
};
private readonly AbsExposureDetectionBackgroundService _exposureDetectionBackgroundService;
+ private readonly AbsDataMaintainanceBackgroundService _dataMaintainanceBackgroundService;
+
private readonly ILoggerService _loggerService;
public WorkManagerMigrator(
AbsExposureDetectionBackgroundService exposureDetectionBackgroundService,
+ AbsDataMaintainanceBackgroundService dataMaintainanceBackgroundService,
ILoggerService loggerService
)
{
_exposureDetectionBackgroundService = exposureDetectionBackgroundService;
+ _dataMaintainanceBackgroundService = dataMaintainanceBackgroundService;
_loggerService = loggerService;
}
@@ -38,6 +42,7 @@ internal Task ExecuteAsync()
CancelOldWorks(workManager, OldWorkNames, _loggerService);
_exposureDetectionBackgroundService.Schedule();
+ _dataMaintainanceBackgroundService.Schedule();
_loggerService.EndMethod();
diff --git a/Covid19Radar/Covid19Radar.iOS/AppDelegate.cs b/Covid19Radar/Covid19Radar.iOS/AppDelegate.cs
index 6c491c375..3ebfa7aff 100644
--- a/Covid19Radar/Covid19Radar.iOS/AppDelegate.cs
+++ b/Covid19Radar/Covid19Radar.iOS/AppDelegate.cs
@@ -44,6 +44,9 @@ private Lazy _exposureDetectionBackground
private readonly Lazy _eventLogSubmissionBackgroundService
= new Lazy(() => ContainerLocator.Current.Resolve());
+ private Lazy _dataMaintainanceBackgroundService
+ = new Lazy(() => ContainerLocator.Current.Resolve());
+
private Lazy _exposureDetectionService
= new Lazy(() => ContainerLocator.Current.Resolve());
@@ -127,6 +130,7 @@ private void ScheduleBackgroundTask()
{
_loggerService.Value.Exception("Failed to schedule ExposureDetectionBackgroundService", exception);
}
+
try
{
_eventLogSubmissionBackgroundService.Value.Schedule();
@@ -135,6 +139,15 @@ private void ScheduleBackgroundTask()
{
_loggerService.Value.Exception("Failed to schedule EventLogSubmissionBackgroundService", exception);
}
+
+ try
+ {
+ _dataMaintainanceBackgroundService.Value.Schedule();
+ }
+ catch (Exception exception)
+ {
+ _loggerService.Value.Exception("Failed to schedule DataMaintainanceBackgroundService", exception);
+ }
}
private bool IsUniversalLinks(NSDictionary launchOptions)
@@ -274,6 +287,7 @@ private void RegisterPlatformTypes(IContainer container)
#endif
container.Register(Reuse.Singleton);
container.Register(Reuse.Singleton);
+ container.Register(Reuse.Singleton);
}
public Task GetExposureConfigurationAsync()
diff --git a/Covid19Radar/Covid19Radar.iOS/Covid19Radar.iOS.csproj b/Covid19Radar/Covid19Radar.iOS/Covid19Radar.iOS.csproj
index e423d9e96..b4e913796 100644
--- a/Covid19Radar/Covid19Radar.iOS/Covid19Radar.iOS.csproj
+++ b/Covid19Radar/Covid19Radar.iOS/Covid19Radar.iOS.csproj
@@ -272,6 +272,7 @@
+
diff --git a/Covid19Radar/Covid19Radar.iOS/Info.plist b/Covid19Radar/Covid19Radar.iOS/Info.plist
index 751350d06..ebe15152b 100644
--- a/Covid19Radar/Covid19Radar.iOS/Info.plist
+++ b/Covid19Radar/Covid19Radar.iOS/Info.plist
@@ -56,6 +56,7 @@
APP_PACKAGE_NAME.exposure-notification
APP_PACKAGE_NAME.delete-old-logs
APP_PACKAGE_NAME.eventlog-submission
+ APP_PACKAGE_NAME.data-maintainance
UIAppFonts
diff --git a/Covid19Radar/Covid19Radar.iOS/Services/DataMaintainanceBackgroundService.cs b/Covid19Radar/Covid19Radar.iOS/Services/DataMaintainanceBackgroundService.cs
new file mode 100644
index 000000000..3df569f1a
--- /dev/null
+++ b/Covid19Radar/Covid19Radar.iOS/Services/DataMaintainanceBackgroundService.cs
@@ -0,0 +1,112 @@
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at https://mozilla.org/MPL/2.0/.
+
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+using BackgroundTasks;
+using Covid19Radar.Common;
+using Covid19Radar.Repository;
+using Covid19Radar.Services;
+using Covid19Radar.Services.Logs;
+using Foundation;
+using Xamarin.Essentials;
+
+namespace Covid19Radar.iOS.Services
+{
+ public class DataMaintainanceBackgroundService : AbsDataMaintainanceBackgroundService
+ {
+ private const int TASK_INTERVAL_IN_DAYS = 1;
+ private static readonly string BGTASK_IDENTIFIER = AppInfo.PackageName + ".data-maintainance";
+
+ private readonly IDateTimeUtility _dateTimeUtility;
+
+ public DataMaintainanceBackgroundService(
+ ILoggerService loggerService,
+ IEventLogRepository eventLogRepository,
+ IDateTimeUtility dateTimeUtility
+ ) : base(loggerService, eventLogRepository)
+ {
+ _dateTimeUtility = dateTimeUtility;
+ }
+
+ public override void Schedule()
+ {
+ LoggerService.StartMethod();
+
+ var result = BGTaskScheduler.Shared.Register(BGTASK_IDENTIFIER, null, task =>
+ {
+ LoggerService.Info("Background task has been started.");
+
+ DateTime nextDateTime = _dateTimeUtility.UtcNow.Date.AddDays(TASK_INTERVAL_IN_DAYS);
+ ScheduleBgTask(nextDateTime);
+
+ var cancellationTokenSource = new CancellationTokenSource();
+ task.ExpirationHandler = cancellationTokenSource.Cancel;
+
+ _ = Task.Run(async () =>
+ {
+ try
+ {
+ await ExecuteAsync();
+ task.SetTaskCompleted(true);
+ }
+ catch (OperationCanceledException exception)
+ {
+ LoggerService.Exception($"Background task canceled.", exception);
+ task.SetTaskCompleted(false);
+ }
+ catch (Exception exception)
+ {
+ LoggerService.Exception($"Exception", exception);
+ task.SetTaskCompleted(false);
+ }
+ finally
+ {
+ cancellationTokenSource.Dispose();
+ }
+ }, cancellationTokenSource.Token);
+ });
+
+ if (result)
+ {
+ LoggerService.Debug("BGTaskScheduler.Shared.Register succeeded.");
+ }
+ else
+ {
+ LoggerService.Info("BGTaskScheduler.Shared.Register failed.");
+ }
+
+ ScheduleBgTask(_dateTimeUtility.UtcNow);
+
+ LoggerService.EndMethod();
+ }
+
+ private void ScheduleBgTask(DateTime nextDateTime)
+ {
+ LoggerService.StartMethod();
+
+ try
+ {
+ BGProcessingTaskRequest bgTaskRequest = new BGProcessingTaskRequest(BGTASK_IDENTIFIER)
+ {
+ EarliestBeginDate = NSDate.FromTimeIntervalSince1970(nextDateTime.ToUnixEpoch())
+ };
+
+ BGTaskScheduler.Shared.Submit(bgTaskRequest, out var error);
+ if (error != null)
+ {
+ NSErrorException exception = new NSErrorException(error);
+ LoggerService.Exception("BGTaskScheduler submit failed.", exception);
+ throw exception;
+ }
+ }
+ finally
+ {
+ LoggerService.EndMethod();
+ }
+ }
+ }
+}
+
diff --git a/Covid19Radar/Covid19Radar.iOS/Services/EventLogSubmissionBackgroundService.cs b/Covid19Radar/Covid19Radar.iOS/Services/EventLogSubmissionBackgroundService.cs
index eb6b65720..34736ba7b 100644
--- a/Covid19Radar/Covid19Radar.iOS/Services/EventLogSubmissionBackgroundService.cs
+++ b/Covid19Radar/Covid19Radar.iOS/Services/EventLogSubmissionBackgroundService.cs
@@ -7,6 +7,7 @@
using System.Threading.Tasks;
using BackgroundTasks;
using Covid19Radar.Common;
+using Covid19Radar.Repository;
using Covid19Radar.Services;
using Covid19Radar.Services.Logs;
using Foundation;
@@ -21,14 +22,17 @@ public class EventLogSubmissionBackgroundService : AbsEventLogSubmissionBackgrou
private const double ONE_DAY_IN_SECONDS = 1 * 24 * 60 * 60;
private readonly IEventLogService _eventLogService;
+ private readonly IEventLogRepository _eventLogRepository;
private readonly ILoggerService _loggerService;
public EventLogSubmissionBackgroundService(
IEventLogService eventLogService,
+ IEventLogRepository eventLogRepository,
ILoggerService loggerService
) : base()
{
_eventLogService = eventLogService;
+ _eventLogRepository = eventLogRepository;
_loggerService = loggerService;
}
@@ -60,6 +64,9 @@ private void HandleSendLogAsync(BGAppRefreshTask task)
_loggerService.Info("HandleSendLogAsync() Task.Run() start");
try
{
+ await _eventLogRepository.RotateAsync(
+ AppConstants.EventLogFileExpiredSeconds);
+
await _eventLogService.SendAllAsync(
AppConstants.EventLogMaxRequestSizeInBytes,
AppConstants.EventLogMaxRetry);
diff --git a/Covid19Radar/Covid19Radar/App.xaml.cs b/Covid19Radar/Covid19Radar/App.xaml.cs
index cbcb98b91..af62e702d 100644
--- a/Covid19Radar/Covid19Radar/App.xaml.cs
+++ b/Covid19Radar/Covid19Radar/App.xaml.cs
@@ -37,6 +37,8 @@ public partial class App : PrismApplication
private ILoggerService LoggerService;
private ILogFileService LogFileService;
+ private IEventLogRepository EventLogRepository { get; set; }
+
/*
* The Xamarin Forms XAML Previewer in Visual Studio uses System.Activator.CreateInstance.
* This imposes a limitation in which the App class must have a default constructor.
@@ -55,6 +57,8 @@ protected override void OnInitialized()
LogFileService = Container.Resolve();
LogFileService.SetSkipBackupAttributeToLogDir();
+ EventLogRepository = Container.Resolve();
+
LogUnobservedTaskExceptions();
FirstLoad = false;
@@ -234,19 +238,25 @@ private static void RegisterCommonTypes(IContainer container)
container.Register(Reuse.Singleton);
}
- protected override void OnStart()
+ protected override async void OnStart()
{
// Initialize periodic log delete service
var logPeriodicDeleteService = Container.Resolve();
logPeriodicDeleteService.Init();
LogFileService.Rotate();
+
+ await EventLogRepository.RotateAsync(
+ AppConstants.EventLogFileExpiredSeconds);
}
- protected override void OnResume()
+ protected override async void OnResume()
{
base.OnResume();
LogFileService.Rotate();
+
+ await EventLogRepository.RotateAsync(
+ AppConstants.EventLogFileExpiredSeconds);
}
protected override void OnSleep()
diff --git a/Covid19Radar/Covid19Radar/Common/AppConstants.cs b/Covid19Radar/Covid19Radar/Common/AppConstants.cs
index c240e0e66..c3736c348 100644
--- a/Covid19Radar/Covid19Radar/Common/AppConstants.cs
+++ b/Covid19Radar/Covid19Radar/Common/AppConstants.cs
@@ -91,6 +91,11 @@ public static readonly DateTime COCOA_FIRST_RELEASE_DATE
///
public const int EventLogMaxRetry = 3;
+ ///
+ /// Event log file expiration date. (seconds)
+ ///
+ public const int EventLogFileExpiredSeconds = 14 * 24 * 60 * 60; // 14 days
+
#region Other Private Methods
private static TimeZoneInfo JstTimeZoneInfo()
diff --git a/Covid19Radar/Covid19Radar/Repository/EventLogRepository.cs b/Covid19Radar/Covid19Radar/Repository/EventLogRepository.cs
index ec133b539..4b424c87e 100644
--- a/Covid19Radar/Covid19Radar/Repository/EventLogRepository.cs
+++ b/Covid19Radar/Covid19Radar/Repository/EventLogRepository.cs
@@ -20,19 +20,12 @@ namespace Covid19Radar.Repository
{
public interface IEventLogRepository
{
- public Task> GetLogsAsync(
- long maxSize = AppConstants.EventLogMaxRequestSizeInBytes
- );
-
- public Task RemoveAsync(EventLog eventLog);
-
- public Task RemoveAllAsync();
-
- public Task AddEventNotifiedAsync(
- long maxSize = AppConstants.EventLogMaxRequestSizeInBytes
- );
-
- public Task IsExist();
+ Task> GetLogsAsync(long maxSize = AppConstants.EventLogMaxRequestSizeInBytes);
+ Task RemoveAsync(EventLog eventLog);
+ Task RemoveAllAsync();
+ Task AddEventNotifiedAsync(long maxSize = AppConstants.EventLogMaxRequestSizeInBytes);
+ Task IsExist();
+ Task RotateAsync(long seconds);
}
public class EventLogRepository : IEventLogRepository
@@ -350,6 +343,77 @@ private bool IsExistInternal()
_loggerService.EndMethod();
}
}
+
+ public async Task RotateAsync(long seconds)
+ {
+ _loggerService.StartMethod();
+
+ await _semaphore.WaitAsync();
+
+ try
+ {
+ await RotateAsyncInternal(seconds);
+ }
+ finally
+ {
+ _semaphore.Release();
+
+ _loggerService.EndMethod();
+ }
+ }
+
+ private async Task RotateAsyncInternal(long seconds)
+ {
+ _loggerService.StartMethod();
+ _loggerService.Info($"seconds: {seconds}");
+
+ try
+ {
+ if (!Directory.Exists(_basePath))
+ {
+ return;
+ }
+
+ long utcNowEpoch = DateTime.UtcNow.ToUnixEpoch();
+ _loggerService.Info($"utcNowEpoch: {utcNowEpoch}");
+
+ string[] filesInDirectory = Directory.GetFiles(_basePath);
+ foreach (var file in filesInDirectory)
+ {
+ _loggerService.Info($"file: {file}");
+
+ long eventLogEpoch;
+ try
+ {
+ string content = await File.ReadAllTextAsync(file);
+ EventLog eventLog = JsonConvert.DeserializeObject(content);
+ eventLogEpoch = eventLog.Epoch;
+ }
+ catch (Exception ex)
+ {
+ _loggerService.Exception("Failed read of event log content.", ex);
+ File.Delete(file);
+ continue;
+ }
+
+ _loggerService.Info($"eventLogEpoch: {eventLogEpoch}");
+
+ if (eventLogEpoch < utcNowEpoch - seconds)
+ {
+ _loggerService.Info("Delete");
+ File.Delete(file);
+ }
+ else
+ {
+ _loggerService.Info("Keep");
+ }
+ }
+ }
+ finally
+ {
+ _loggerService.EndMethod();
+ }
+ }
}
public class EventContentExposureNotified
diff --git a/Covid19Radar/Covid19Radar/Services/AbsDataMaintainanceBackgroundService.cs b/Covid19Radar/Covid19Radar/Services/AbsDataMaintainanceBackgroundService.cs
new file mode 100644
index 000000000..0a034e26e
--- /dev/null
+++ b/Covid19Radar/Covid19Radar/Services/AbsDataMaintainanceBackgroundService.cs
@@ -0,0 +1,44 @@
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at https://mozilla.org/MPL/2.0/.
+
+using System.Threading.Tasks;
+using Covid19Radar.Common;
+using Covid19Radar.Repository;
+using Covid19Radar.Services.Logs;
+
+namespace Covid19Radar.Services
+{
+ public abstract class AbsDataMaintainanceBackgroundService : IBackgroundService
+ {
+ protected ILoggerService LoggerService { get; private set; }
+
+ private readonly IEventLogRepository _eventLogRepository;
+
+ public AbsDataMaintainanceBackgroundService(
+ ILoggerService loggerService,
+ IEventLogRepository eventLogRepository)
+ {
+ LoggerService = loggerService;
+ _eventLogRepository = eventLogRepository;
+ }
+
+ public abstract void Schedule();
+
+ public async Task ExecuteAsync()
+ {
+ LoggerService.StartMethod();
+
+ try
+ {
+ await _eventLogRepository.RotateAsync(
+ AppConstants.EventLogFileExpiredSeconds);
+ }
+ finally
+ {
+ LoggerService.EndMethod();
+ }
+ }
+ }
+}
+
diff --git a/Covid19Radar/Covid19Radar/ViewModels/Settings/DebugPageViewModel.cs b/Covid19Radar/Covid19Radar/ViewModels/Settings/DebugPageViewModel.cs
index 1c0b85529..b955f90b3 100644
--- a/Covid19Radar/Covid19Radar/ViewModels/Settings/DebugPageViewModel.cs
+++ b/Covid19Radar/Covid19Radar/ViewModels/Settings/DebugPageViewModel.cs
@@ -329,6 +329,11 @@ private string ConvertSha256(string text)
await _eventLogRepository.AddEventNotifiedAsync();
});
+ public IAsyncCommand OnClickRotateEventLogs => new AsyncCommand(async () =>
+ {
+ await _eventLogRepository.RotateAsync(AppConstants.EventLogFileExpiredSeconds);
+ });
+
public Command OnClickQuit => new Command(() =>
{
Application.Current.Quit();
diff --git a/Covid19Radar/Covid19Radar/Views/Settings/DebugPage.xaml b/Covid19Radar/Covid19Radar/Views/Settings/DebugPage.xaml
index a85b7bfd5..fc10e7dc0 100644
--- a/Covid19Radar/Covid19Radar/Views/Settings/DebugPage.xaml
+++ b/Covid19Radar/Covid19Radar/Views/Settings/DebugPage.xaml
@@ -116,6 +116,10 @@
Command="{Binding Path=OnClickAddEventNotifiedForce}"
Style="{StaticResource DefaultButton}"
Text="AddEventNotified(Force)" />
+