protected EventStoreClientBase(EventStoreClientSettings?settings, IDictionary <string, Func <RpcException, Exception> > exceptionMap) { Settings = settings ?? new EventStoreClientSettings(); _httpHandler = Settings.CreateHttpMessageHandler?.Invoke() ?? new HttpClientHandler(); var connectionName = Settings.ConnectionName ?? $"ES-{Guid.NewGuid()}"; Action <Exception>?exceptionNotificationHook = null; if (Settings.ConnectivitySettings.GossipSeeds.Length > 0) { _httpHandler = ClusterAwareHttpHandler.Create(Settings, _httpHandler); } _channel = GrpcChannel.ForAddress(Settings.ConnectivitySettings.Address, new GrpcChannelOptions { HttpClient = new HttpClient(_httpHandler) { Timeout = Timeout.InfiniteTimeSpan, DefaultRequestVersion = new Version(2, 0), }, LoggerFactory = Settings.LoggerFactory }); CallInvoker = (Settings.Interceptors ?? Array.Empty <Interceptor>()).Aggregate( _channel.CreateCallInvoker() .Intercept(new TypedExceptionInterceptor(exceptionMap, exceptionNotificationHook)) .Intercept(new ConnectionNameInterceptor(connectionName)), (invoker, interceptor) => invoker.Intercept(interceptor)); }
protected EventStoreClientBase(EventStoreClientSettings?settings, IDictionary <string, Func <RpcException, Exception> > exceptionMap) { Settings = settings ?? new EventStoreClientSettings(); var connectionName = Settings.ConnectionName ?? $"ES-{Guid.NewGuid()}"; if (Settings.ConnectivitySettings.Address.Scheme == Uri.UriSchemeHttp || !Settings.ConnectivitySettings.GossipOverHttps) { //this must be switched on before creation of the HttpMessageHandler AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true); } #if NETCOREAPP3_1 _innerHttpHandler = Settings.CreateHttpMessageHandler?.Invoke() ?? new SocketsHttpHandler(); #elif NETSTANDARD2_1 _innerHttpHandler = Settings.CreateHttpMessageHandler?.Invoke() ?? new HttpClientHandler(); #endif _httpHandler = Settings.ConnectivitySettings.IsSingleNode ? (HttpMessageHandler) new SingleNodeHttpHandler(Settings) { InnerHandler = _innerHttpHandler } : ClusterAwareHttpHandler.Create(Settings, _innerHttpHandler); #if NETSTANDARD2_1 _httpHandler = new DefaultRequestVersionHandler(_httpHandler); #endif _channel = GrpcChannel.ForAddress(new UriBuilder(Settings.ConnectivitySettings.Address) { Scheme = Uri.UriSchemeHttps }.Uri, new GrpcChannelOptions { HttpClient = new HttpClient(_httpHandler) { Timeout = Timeout.InfiniteTimeSpan, #if NETCOREAPP3_1 DefaultRequestVersion = new Version(2, 0), #endif }, LoggerFactory = Settings.LoggerFactory, Credentials = Settings.ChannelCredentials }); Action <Exception>?exceptionNotificationHook = _httpHandler is ClusterAwareHttpHandler h ? h.ExceptionOccurred : new Action <Exception>(ex => { }); CallInvoker = (Settings.Interceptors ?? Array.Empty <Interceptor>()).Aggregate( _channel.CreateCallInvoker() .Intercept(new TypedExceptionInterceptor(exceptionMap, exceptionNotificationHook)) .Intercept(new ConnectionNameInterceptor(connectionName)), (invoker, interceptor) => invoker.Intercept(interceptor)); }
public EventStoreClient(EventStoreClientSettings settings = null) { _settings = settings ?? new EventStoreClientSettings(); var connectionName = _settings.ConnectionName ?? $"ES-{Guid.NewGuid()}"; Action <Exception> exceptionNotificationHook = null; var httpHandler = _settings.CreateHttpMessageHandler?.Invoke() ?? new HttpClientHandler(); if (_settings.ConnectivitySettings.GossipSeeds.Length > 0) { ConfigureClusterAwareHandler(); } _channel = GrpcChannel.ForAddress(_settings.ConnectivitySettings.Address, new GrpcChannelOptions { HttpClient = new HttpClient(httpHandler) { Timeout = Timeout.InfiniteTimeSpan, DefaultRequestVersion = new Version(2, 0), }, LoggerFactory = _settings.LoggerFactory }); var callInvoker = (_settings.Interceptors ?? Array.Empty <Interceptor>()).Aggregate( _channel.CreateCallInvoker() .Intercept(new TypedExceptionInterceptor(exceptionNotificationHook)) .Intercept(new ConnectionNameInterceptor(connectionName)), (invoker, interceptor) => invoker.Intercept(interceptor)); _client = new Streams.Streams.StreamsClient(callInvoker); PersistentSubscriptions = new EventStorePersistentSubscriptionsClient(callInvoker, _settings); ProjectionsManager = new EventStoreProjectionManagerClient(callInvoker); UsersManager = new EventStoreUserManagerClient(callInvoker); _log = _settings.LoggerFactory?.CreateLogger <EventStoreClient>() ?? new NullLogger <EventStoreClient>(); void ConfigureClusterAwareHandler() { var clusterAwareHttpHandler = new ClusterAwareHttpHandler( _settings.ConnectivitySettings.NodePreference == NodePreference.Leader, new ClusterEndpointDiscoverer( _settings.ConnectivitySettings.MaxDiscoverAttempts, _settings.ConnectivitySettings.GossipSeeds, _settings.ConnectivitySettings.GossipTimeout, _settings.ConnectivitySettings.DiscoveryInterval, _settings.ConnectivitySettings.NodePreference, httpHandler)) { InnerHandler = httpHandler }; exceptionNotificationHook = clusterAwareHttpHandler.ExceptionOccurred; httpHandler = clusterAwareHttpHandler; } }
public async Task should_set_requires_leader_header(bool requiresLeader) { var sut = new ClusterAwareHttpHandler( requiresLeader, new FakeEndpointDiscoverer(() => new IPEndPoint(IPAddress.Parse("0.0.0.0"), 2113))) { InnerHandler = new TestMessageHandler() }; var client = new HttpClient(sut); var request = new HttpRequestMessage(HttpMethod.Get, new UriBuilder().Uri); await client.SendAsync(request); Assert.True(request.Headers.TryGetValues("requires-leader", out var value)); Assert.True(bool.Parse(value.First()) == requiresLeader); }
public async Task should_set_endpoint_to_leader_endpoint_on_exception(bool useHttps, EndPoint endpoint) { var sut = new ClusterAwareHttpHandler( useHttps, true, new FakeEndpointDiscoverer(() => new IPEndPoint(IPAddress.Parse("0.0.0.0"), 2113))) { InnerHandler = new TestMessageHandler() }; var client = new HttpClient(sut); var request = new HttpRequestMessage(HttpMethod.Get, new UriBuilder().Uri); sut.ExceptionOccurred(new NotLeaderException(endpoint.GetHost(), endpoint.GetPort())); await client.SendAsync(request); Assert.Equal(endpoint.GetHost(), request.RequestUri.Host); Assert.Equal(endpoint.GetPort(), request.RequestUri.Port); }
public async Task should_issue_request_to_discovered_endpoint() { var discoveredEndpoint = new IPEndPoint(IPAddress.Parse("0.0.0.0"), 2113); var sut = new ClusterAwareHttpHandler( true, new FakeEndpointDiscoverer(() => discoveredEndpoint)) { InnerHandler = new TestMessageHandler() }; var client = new HttpClient(sut); await client.SendAsync(new HttpRequestMessage(HttpMethod.Get, new UriBuilder().Uri)); var request = new HttpRequestMessage(HttpMethod.Get, new UriBuilder().Uri); await client.SendAsync(request); Assert.Equal(discoveredEndpoint.Address.ToString(), request.RequestUri.Host); Assert.Equal(discoveredEndpoint.Port, request.RequestUri.Port); }
public async Task should_attempt_endpoint_discovery_on_next_request_when_request_fails() { int discoveryAttempts = 0; var sut = new ClusterAwareHttpHandler( true, new FakeEndpointDiscoverer(() => { discoveryAttempts++; throw new Exception(); })) { InnerHandler = new TestMessageHandler() }; var client = new HttpClient(sut); await Assert.ThrowsAsync <Exception>(() => client.SendAsync(new HttpRequestMessage(HttpMethod.Get, new UriBuilder().Uri))); await Assert.ThrowsAsync <Exception>(() => client.SendAsync(new HttpRequestMessage(HttpMethod.Get, new UriBuilder().Uri))); Assert.Equal(2, discoveryAttempts); }