sync: migrate sync devices from fs to mongodb
This commit is contained in:
@@ -1,65 +1,41 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using MongoDB.Driver;
|
||||
using Notesnook.API.Interfaces;
|
||||
using Notesnook.API.Models;
|
||||
using Notesnook.API.Services;
|
||||
using Quartz;
|
||||
|
||||
namespace Notesnook.API.Jobs
|
||||
{
|
||||
public class DeviceCleanupJob : IJob
|
||||
public class DeviceCleanupJob(ISyncItemsRepositoryAccessor repositories) : IJob
|
||||
{
|
||||
public Task Execute(IJobExecutionContext context)
|
||||
public async Task Execute(IJobExecutionContext context)
|
||||
{
|
||||
ParallelOptions parallelOptions = new()
|
||||
var cutoffDate = DateTimeOffset.UtcNow.AddMonths(-1).ToUnixTimeMilliseconds();
|
||||
var deviceFilter = Builders<SyncDevice>.Filter.Lt(x => x.LastAccessTime, cutoffDate);
|
||||
|
||||
using var cursor = await repositories.SyncDevices.Collection.Find(deviceFilter, new FindOptions { BatchSize = 1000 })
|
||||
.Project(x => x.DeviceId)
|
||||
.ToCursorAsync();
|
||||
|
||||
var deleteModels = new List<WriteModel<DeviceIdsChunk>>();
|
||||
while (await cursor.MoveNextAsync())
|
||||
{
|
||||
MaxDegreeOfParallelism = 100,
|
||||
CancellationToken = context.CancellationToken,
|
||||
};
|
||||
Parallel.ForEach(Directory.EnumerateDirectories("sync"), parallelOptions, (userDir, ct) =>
|
||||
if (!cursor.Current.Any()) continue;
|
||||
deleteModels.Add(new DeleteManyModel<DeviceIdsChunk>(Builders<DeviceIdsChunk>.Filter.In(x => x.DeviceId, cursor.Current)));
|
||||
}
|
||||
|
||||
if (deleteModels.Count > 0)
|
||||
{
|
||||
foreach (var device in Directory.EnumerateDirectories(userDir))
|
||||
{
|
||||
string lastAccessFile = Path.Combine(device, "LastAccessTime");
|
||||
var bulkOptions = new BulkWriteOptions { IsOrdered = false };
|
||||
await repositories.DeviceIdsChunks.Collection.BulkWriteAsync(deleteModels, bulkOptions);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (!File.Exists(lastAccessFile))
|
||||
{
|
||||
Directory.Delete(device, true);
|
||||
continue;
|
||||
}
|
||||
|
||||
string content = File.ReadAllText(lastAccessFile);
|
||||
if (!long.TryParse(content, out long lastAccessTime) || lastAccessTime <= 0)
|
||||
{
|
||||
Directory.Delete(device, true);
|
||||
continue;
|
||||
}
|
||||
|
||||
DateTimeOffset accessTime;
|
||||
try
|
||||
{
|
||||
accessTime = DateTimeOffset.FromUnixTimeMilliseconds(lastAccessTime);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
Directory.Delete(device, true);
|
||||
continue;
|
||||
}
|
||||
|
||||
// If the device hasn't been accessed for more than one month, delete it.
|
||||
if (accessTime.AddMonths(1) < DateTimeOffset.UtcNow)
|
||||
{
|
||||
Directory.Delete(device, true);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Log the error and continue processing other directories.
|
||||
Console.Error.WriteLine($"Error processing device '{device}': {ex.Message}");
|
||||
}
|
||||
}
|
||||
});
|
||||
return Task.CompletedTask;
|
||||
await repositories.SyncDevices.Collection.DeleteManyAsync(deviceFilter);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user