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);
            }
        }
Ejemplo n.º 2
0
        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);
            }
        }
Ejemplo n.º 4
0
        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"));
        }