private void ErrorExtension_ConnectionError( object sender, string e) { // authentication failure if (string.Equals(e, "403::Handshake denied", StringComparison.OrdinalIgnoreCase) || string.Equals(e, "403:denied_by_security_policy:create_denied", StringComparison.OrdinalIgnoreCase) || string.Equals(e, "403::unknown client", StringComparison.OrdinalIgnoreCase)) { _logger.LogWarning("Handled CometD Exception: {message}", e); // 1. Disconnect existing client. Disconnect(); // 2. Invalidate the access token. _tokenResponse.Invalidate(); _logger.LogDebug("Invalidate token for {name} ...", nameof(BayeuxClient)); // 3. Recreate BayeuxClient and populate it with a new transport with new security headers. CreateBayeuxClient(); // 4. Invoke the Reconnect Event Reconnect?.Invoke(this, true); } else { _logger.LogError("{name} failed with the following message: {message}", nameof(ResilientStreamingClient), e); } }
public async Task End2End() { var testInstance = new AsyncExpiringLazy <TokenResponse>(async metadata => { await Task.Delay(1000); return(new ExpirationMetadata <TokenResponse> { Result = new TokenResponse { AccessToken = Guid.NewGuid().ToString() }, ValidUntil = DateTimeOffset.UtcNow.AddSeconds(2) }); }); // 1. check if value is created - shouldn't Assert.False(await testInstance.IsValueCreated()); // 2. fetch lazy expiring value var token = await testInstance.Value(); // 3a. verify it is created now Assert.True(await testInstance.IsValueCreated()); // 3b. verify it is not null Assert.NotNull(token.AccessToken); // 4. fetch the value again. Since it's lifetime is 2 seconds, it should be still the same var token2 = await testInstance.Value(); Assert.Same(token, token2); // 5. sleep for 2 seconds to let the value expire await Task.Delay(2000); // 6a. verify the value expired Assert.False(await testInstance.IsValueCreated()); // 6b. fetch again var token3 = await testInstance.Value(); // 7. verify we now have a new (recreated) value - as the previous one expired Assert.NotSame(token2, token3); // 8. invalidate the value manually before it has a chance to expire await testInstance.Invalidate(); // 9. check if value is created - shouldn't anymore Assert.False(await testInstance.IsValueCreated()); }
protected virtual void ErrorExtension_ConnectionError( object sender, string e) { // authentication failure if (string.Equals(e, "403::Handshake denied", StringComparison.OrdinalIgnoreCase) || string.Equals(e, "403:denied_by_security_policy:create_denied", StringComparison.OrdinalIgnoreCase) || string.Equals(e, "403::unknown client", StringComparison.OrdinalIgnoreCase) || string.Equals(e, "401::Authentication invalid", StringComparison.OrdinalIgnoreCase)) { _logger.LogWarning("Handled CometD Exception: {message}", e); // 1. Disconnect existing client. Disconnect(); // 2. Invalidate the access token. _tokenResponse.Invalidate(); _logger.LogDebug("Invalidate token for {name} ...", nameof(BayeuxClient)); // 3. Recreate BayeuxClient and populate it with a new transport with new security headers. CreateBayeuxClient(); // 4. Invoke the Reconnect Event Reconnect?.Invoke(this, true); } else if (e.Contains("you provided was invalid")) { var start = e.IndexOf('{'); var end = e.IndexOf('}'); var replayIdString = e.Substring(start + 1, end - (start + 1)); if (int.TryParse(replayIdString, out var replayId)) { InvalidReplayIdStrategy(replayId); } } else { _logger.LogError("{name} failed with the following message: {message}", nameof(ResilientStreamingClient), e); } }
private IAsyncPolicy GetAuthenticationRetryPolicy() { return(Policy .Handle <ForceApiException>(x => x.Message.Contains("ErrorCode INVALID_SESSION_ID")) .RetryAsync( retryCount: _options.Retry, onRetry: (ex, count, context) => { var methodName = context[PolicyContextMethod] ?? "MethodNotSpecified"; _logger.LogWarning( "{Method} attempting to re-authenticate Retry {Count} of {Total} for named policy {PolicyKey}, due to {Message}.", methodName, count, _options.Retry, context.PolicyKey, ex.Message); _forceClient.Invalidate(); }) .WithPolicyKey($"{nameof(ResilientForceClient)}RetryAsync")); }