fix(jobs): retry directories whose reconciliation batch was dropped
This commit is contained in:
@@ -121,19 +121,23 @@ public sealed class FileSystemCrawlJob : Job {
|
||||
|
||||
if (changed) {
|
||||
dirsProcessed++;
|
||||
await ReconcileDirectory(assetDb, currentPath, files!, uploaderId, token,
|
||||
bool reconciled = await ReconcileDirectory(assetDb, currentPath, files!, uploaderId, token,
|
||||
(added, updated, deleted) => { filesAdded += added; filesUpdated += updated; filesDeleted += deleted; });
|
||||
|
||||
if (existingStates.TryGetValue(currentPath, out var existingState)) {
|
||||
existingState.LastMtime = currentDir.LastWriteTimeUtc;
|
||||
} else {
|
||||
existingStates[currentPath] = new DirectoryScanState {
|
||||
Id = Guid.NewGuid(),
|
||||
FolderId = folderId,
|
||||
Path = currentPath,
|
||||
LastMtime = currentDir.LastWriteTimeUtc
|
||||
};
|
||||
db.DirectoryScanStates.Add(existingStates[currentPath]);
|
||||
// Only record scan state when the reconciliation batch actually committed; a dropped
|
||||
// batch leaves the mtime stale so the directory is retried on the next run.
|
||||
if (reconciled) {
|
||||
if (existingStates.TryGetValue(currentPath, out var existingState)) {
|
||||
existingState.LastMtime = currentDir.LastWriteTimeUtc;
|
||||
} else {
|
||||
existingStates[currentPath] = new DirectoryScanState {
|
||||
Id = Guid.NewGuid(),
|
||||
FolderId = folderId,
|
||||
Path = currentPath,
|
||||
LastMtime = currentDir.LastWriteTimeUtc
|
||||
};
|
||||
db.DirectoryScanStates.Add(existingStates[currentPath]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
dirsSkipped++;
|
||||
@@ -186,7 +190,8 @@ public sealed class FileSystemCrawlJob : Job {
|
||||
/// <param name="uploaderId">The system uploader id to backfill, if any.</param>
|
||||
/// <param name="token">Cancellation token.</param>
|
||||
/// <param name="report">Callback receiving (added, updated, deleted) counts.</param>
|
||||
async Task ReconcileDirectory(LactoseDbContext assetDb, string dirPath, FileInfo[] files, Guid? uploaderId,
|
||||
/// <returns>True when the batch committed; false when it was dropped due to a duplicate-key race.</returns>
|
||||
async Task<bool> ReconcileDirectory(LactoseDbContext assetDb, string dirPath, FileInfo[] files, Guid? uploaderId,
|
||||
CancellationToken token, Action<int, int, int> report) {
|
||||
var prefix = dirPath.TrimEnd(Path.DirectorySeparatorChar) + Path.DirectorySeparatorChar;
|
||||
var lo = prefix;
|
||||
@@ -260,12 +265,15 @@ public sealed class FileSystemCrawlJob : Job {
|
||||
// same new path concurrently). The batch is dropped; the file is found next run.
|
||||
logger.LogDebug(ex, "Dropped {Count} asset change(s) in {Path} due to a duplicate asset path.",
|
||||
added + updated + deleted, dirPath);
|
||||
report(0, 0, 0);
|
||||
return false;
|
||||
} finally {
|
||||
assetDb.ChangeTracker.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
report(added, updated, deleted);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool IsDuplicateKey(DbUpdateException ex) =>
|
||||
|
||||
Reference in New Issue
Block a user