Contact-Sync: schnellerer Retry (3min statt 30min) nach fehlgeschlagenem Sync, z.B. bei abgelaufener Session
This commit is contained in:
parent
3500d75b42
commit
e4cbec50f4
1 changed files with 28 additions and 8 deletions
|
|
@ -10,6 +10,13 @@ namespace Anrufmonitor.Contacts;
|
|||
/// Der eigentliche Anruf-Lookup (<see cref="ContactLookupService"/>) liest danach
|
||||
/// nur noch aus dem Cache und ruft nie live gegen Office365/Google waehrend eines
|
||||
/// eingehenden Anrufs.
|
||||
///
|
||||
/// Adaptives Intervall: nach einem erfolgreichen Durchlauf wird das normale, lange
|
||||
/// <see cref="ContactsOptions.SyncInterval"/> gewartet. Ist mindestens ein Provider
|
||||
/// fehlgeschlagen (z. B. weil ein Tenant eine kurze Session-Lifetime erzwingt und ein
|
||||
/// neuer interaktiver Login noetig ist, der Device-Code aber noch nicht eingegeben wurde),
|
||||
/// wird stattdessen zeitnah erneut versucht - sonst muesste man bis zu 30 Minuten auf den
|
||||
/// naechsten (rechtzeitig ablaufenden) Login-Code warten.
|
||||
/// </summary>
|
||||
public sealed class ContactSyncService(
|
||||
ContactCache cache,
|
||||
|
|
@ -18,6 +25,8 @@ public sealed class ContactSyncService(
|
|||
ILogger<ContactSyncService> logger)
|
||||
: BackgroundService
|
||||
{
|
||||
private static readonly TimeSpan RetryIntervalAfterFailure = TimeSpan.FromMinutes(3);
|
||||
|
||||
private readonly ContactsOptions _options = options.Value;
|
||||
|
||||
public event EventHandler? SyncCompleted;
|
||||
|
|
@ -26,19 +35,28 @@ public sealed class ContactSyncService(
|
|||
{
|
||||
await cache.EnsureCreatedAsync(stoppingToken);
|
||||
|
||||
using var timer = new PeriodicTimer(_options.SyncInterval);
|
||||
|
||||
// Erster Sync sofort beim Start, danach im konfigurierten Intervall.
|
||||
do
|
||||
while (!stoppingToken.IsCancellationRequested)
|
||||
{
|
||||
await SyncOnceAsync(stoppingToken);
|
||||
var allSucceeded = await SyncOnceAsync(stoppingToken);
|
||||
|
||||
var delay = allSucceeded ? _options.SyncInterval : RetryIntervalAfterFailure;
|
||||
|
||||
try
|
||||
{
|
||||
await Task.Delay(delay, stoppingToken);
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (!stoppingToken.IsCancellationRequested
|
||||
&& await timer.WaitForNextTickAsync(stoppingToken));
|
||||
}
|
||||
|
||||
public async Task SyncOnceAsync(CancellationToken cancellationToken)
|
||||
/// <summary>Gibt zurueck, ob ALLE aktivierten Provider erfolgreich synchronisiert wurden.</summary>
|
||||
public async Task<bool> SyncOnceAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
var allSucceeded = true;
|
||||
|
||||
foreach (var provider in providers.Where(p => p.IsEnabled))
|
||||
{
|
||||
try
|
||||
|
|
@ -48,10 +66,12 @@ public sealed class ContactSyncService(
|
|||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
allSucceeded = false;
|
||||
logger.LogError(ex, "Sync fuer {Source} fehlgeschlagen", provider.Source);
|
||||
}
|
||||
}
|
||||
|
||||
SyncCompleted?.Invoke(this, EventArgs.Empty);
|
||||
return allSucceeded;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue