diff --git a/Source/LibationSearchEngine/SearchEngine.cs b/Source/LibationSearchEngine/SearchEngine.cs index 173e0406..43e55b8f 100644 --- a/Source/LibationSearchEngine/SearchEngine.cs +++ b/Source/LibationSearchEngine/SearchEngine.cs @@ -81,10 +81,12 @@ public class SearchEngine public void CreateNewIndex(IEnumerable library, bool overwrite = true) { const int maxRetries = 5; - const int retryDelayMs = 400; + const int baseDelayMs = 400; var libraryList = library.ToList(); - for (var attempt = 0; attempt < maxRetries; attempt++) + // Exponential backoff retry: 400 ms, 800 ms, 1600 ms, etc + // Total wait time before giving up: 12.4 sec + for (var attempt = 0; attempt < maxRetries; attempt++) { try { @@ -93,15 +95,17 @@ public class SearchEngine } catch (IOException ex) when (attempt < maxRetries - 1) { + var delayMs = baseDelayMs * (1 << attempt); // write.lock can be held by another process (e.g. second Libation instance, antivirus) or a prior writer that did not release. Retry after delay. - Serilog.Log.Logger.Warning(ex, "Search index lock conflict (attempt {Attempt}/{Max}), retrying in {Delay}ms", attempt + 1, maxRetries, retryDelayMs); - Thread.Sleep(retryDelayMs); + Serilog.Log.Logger.Warning(ex, "Search index lock conflict (attempt {Attempt}/{Max}), retrying in {Delay}ms", attempt + 1, maxRetries, delayMs); + Thread.Sleep(delayMs); } catch (UnauthorizedAccessException ex) when (attempt < maxRetries - 1) { + var delayMs = baseDelayMs * (1 << attempt); // Windows may report "file in use" as UnauthorizedAccessException - Serilog.Log.Logger.Warning(ex, "Search index lock conflict (attempt {Attempt}/{Max}), retrying in {Delay}ms", attempt + 1, maxRetries, retryDelayMs); - Thread.Sleep(retryDelayMs); + Serilog.Log.Logger.Warning(ex, "Search index lock conflict (attempt {Attempt}/{Max}), retrying in {Delay}ms", attempt + 1, maxRetries, delayMs); + Thread.Sleep(delayMs); } } }