diff --git a/src/BreCalClient/MainWindow.xaml.cs b/src/BreCalClient/MainWindow.xaml.cs index 4d13c6b..f9aaa80 100644 --- a/src/BreCalClient/MainWindow.xaml.cs +++ b/src/BreCalClient/MainWindow.xaml.cs @@ -19,6 +19,10 @@ using static BreCalClient.Extensions; using System.Collections.Concurrent; using Newtonsoft.Json; using System.Security.Principal; +using Polly; +using System.Net.Http; +using System.Net; +using Polly.Retry; namespace BreCalClient { @@ -34,8 +38,7 @@ namespace BreCalClient #region Fields private static Int32 _uiUpdateRunning = 0; - - private Timer? _timer; + private Credentials? _credentials; private readonly ConcurrentDictionary _allShipcallsDict = new(); @@ -73,7 +76,29 @@ namespace BreCalClient { InitializeComponent(); _api = new DefaultApi(Properties.Settings.Default.API_URL); - _api.Configuration.ApiKeyPrefix["Authorization"] = "Bearer"; + _api.Configuration.ApiKeyPrefix["Authorization"] = "Bearer"; + + const int maxDelayInMilliseconds = 32 * 1000; + var jitterer = new Random(); + + var retryPolicy = + Policy.Handle() + .OrResult(resp => resp.StatusCode == HttpStatusCode.Unauthorized) + .WaitAndRetryAsync(3, + retryAttempt => + { + var calculatedDelayInMilliseconds = Math.Pow(2, retryAttempt) * 1000; + var jitterInMilliseconds = jitterer.Next(0, 1000); + + var actualDelay = Math.Min(calculatedDelayInMilliseconds + jitterInMilliseconds, maxDelayInMilliseconds); + return TimeSpan.FromMilliseconds(actualDelay); + }, + onRetry: (resp, timespan, context) => + { + this.RefreshToken(null); + Trace.WriteLine("token refreshed"); + }); + RetryConfiguration.AsyncRetryPolicy = retryPolicy; } #endregion @@ -123,8 +148,7 @@ namespace BreCalClient this.busyIndicator.IsBusy = false; this._api.Configuration.ApiKey["Authorization"] = _loginResult.Token; this.LoadStaticLists(); - this.labelUsername.Text = $"{_loginResult.FirstName} {_loginResult.LastName}"; - _timer = new Timer(RefreshToken, null, 4000000, Timeout.Infinite); + this.labelUsername.Text = $"{_loginResult.FirstName} {_loginResult.LastName}"; } } labelGeneralStatus.Text = $"Connection {ConnectionStatus.SUCCESSFUL}"; @@ -150,8 +174,9 @@ namespace BreCalClient } } - private void RefreshToken(object? state) + private bool RefreshToken(object? state) { + bool result = false; try { _loginResult = _api.LoginPost(_credentials); @@ -159,7 +184,8 @@ namespace BreCalClient { if (_loginResult.Id > 0) { - this._api.Configuration.ApiKey["Authorization"] = _loginResult.Token; + this._api.Configuration.ApiKey["Authorization"] = _loginResult.Token; + result = true; } } else @@ -171,6 +197,7 @@ namespace BreCalClient { _log.ErrorFormat("Error refreshing token: {0}", ex.Message); } + return result; } private void buttonExit_Click(object sender, RoutedEventArgs e) @@ -805,10 +832,13 @@ namespace BreCalClient private void ShowErrorDialog(string message, string caption) { + _log.ErrorFormat("{0} - {1}", caption, message); + /* Dispatcher.Invoke(new Action(() => { MessageBox.Show(message, caption, MessageBoxButton.OK, MessageBoxImage.Error); - })); + })); + */ } private void EnableControlsForParticipant()