<commit_before>using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.ServiceModel.Discovery;
using System.Threading;

namespace Nvents.Services.Network
{
	public class MultiEventServiceClient : IEventService, IDisposable
	{
		ChannelFactory<IEventService> factory;
		Dictionary<EndpointAddress, IEventService> servers = new Dictionary<EndpointAddress, IEventService>();
		ReaderWriterLockSlim locker = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion);
		DateTime lastDiscoveryLookup = DateTime.Now.AddDays(-1);

		public MultiEventServiceClient(string encryptionKey)
		{
			var binding = new NetTcpBinding(SecurityMode.None);
			binding.Security.Transport.ClientCredentialType = TcpClientCredentialType.None;
			binding.ReliableSession.Enabled = true;
			factory = new ChannelFactory<IEventService>(binding);
			factory.Endpoint.Contract.Operations[0].Behaviors.Add(new EncryptionBehavior { EncryptionKey = encryptionKey });
		}

		public void Publish(IEvent @event)
		{
			foreach (var server in GetServers())
			{
				ThreadPool.QueueUserWorkItem(state =>
				{
					var s = state as IEventService;
					s.Publish(@event);
				}, server);
			}
		}

		private IEnumerable<IEventService> GetServers()
		{
			locker.EnterUpgradeableReadLock();
			foreach (var server in servers.Values.ToArray())
			{
				yield return server;
			}

			locker.EnterWriteLock();
			foreach (var address in GetAddresses())
			{
				if (servers.ContainsKey(address))
					continue;

				var server = factory.CreateChannel(address);
				var connection = server as ICommunicationObject;
				connection.Faulted += connection_FaultedOrClosing;
				connection.Closing += connection_FaultedOrClosing;
				try
				{
					connection.Open();
				}
				catch (Exception ex)
				{
					continue;
				}
				servers[address] = server;
				yield return server;
			}
			locker.ExitWriteLock();
			locker.ExitUpgradeableReadLock();
		}

		private void connection_FaultedOrClosing(object sender, EventArgs e)
		{
			locker.EnterWriteLock();
			var server = sender as IEventService;
			if (servers.ContainsValue(server))
			{
				var address = servers.Single(x => x.Value == server).Key;
				servers.Remove(address);
			}
			locker.ExitWriteLock();
		}

		private IEnumerable<EndpointAddress> GetAddresses()
		{
			var now = DateTime.Now;
			if (now - lastDiscoveryLookup < TimeSpan.FromSeconds(1))<commit_msg>Catching timeout exception when trying to publish to a disconnected client and removes that client from the list. Closes #1<commit_after>using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.ServiceModel.Discovery;
using System.Threading;

namespace Nvents.Services.Network
{
	public class MultiEventServiceClient : IEventService, IDisposable
	{
		ChannelFactory<IEventService> factory;
		Dictionary<EndpointAddress, IEventService> servers = new Dictionary<EndpointAddress, IEventService>();
		ReaderWriterLockSlim locker = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion);
		DateTime lastDiscoveryLookup = DateTime.Now.AddDays(-1);

		public MultiEventServiceClient(string encryptionKey)
		{
			var binding = new NetTcpBinding(SecurityMode.None);
			binding.Security.Transport.ClientCredentialType = TcpClientCredentialType.None;
			binding.ReliableSession.Enabled = true;
			factory = new ChannelFactory<IEventService>(binding);
			factory.Endpoint.Contract.Operations[0].Behaviors.Add(new EncryptionBehavior { EncryptionKey = encryptionKey });
		}

		public void Publish(IEvent @event)
		{
			foreach (var server in GetServers())
			{
				ThreadPool.QueueUserWorkItem(state =>
				{
					var s = state as IEventService;
					try
					{
						s.Publish(@event);
					}
					catch (TimeoutException)
					{
						RemoveServer(s);
					}
				}, server);
			}
		}

		private IEnumerable<IEventService> GetServers()
		{
			locker.EnterUpgradeableReadLock();
			foreach (var server in servers.Values.ToArray())
			{
				yield return server;
			}

			locker.EnterWriteLock();
			foreach (var address in GetAddresses())
			{
				if (servers.ContainsKey(address))
					continue;

				var server = factory.CreateChannel(address);
				var connection = server as ICommunicationObject;
				connection.Faulted += connection_FaultedOrClosing;
				connection.Closing += connection_FaultedOrClosing;
				try
				{
					connection.Open();
				}
				catch (EndpointNotFoundException)
				{
					continue;
				}
				servers[address] = server;
				yield return server;
			}
			locker.ExitWriteLock();
			locker.ExitUpgradeableReadLock();
		}

		private void connection_FaultedOrClosing(object sender, EventArgs e)
		{
			var server = sender as IEventService;
			RemoveServer(server);
		}

		private void RemoveServer(IEventService server)
		{
			locker.EnterWriteLock();
			if (servers.ContainsValue(server))
			{
				var address = servers.Single(x => x.Value == server).Key;
				servers.Remove(address);
			}
			locker.ExitWriteLock();
		}

		private IEnumerable<EndpointAddress> GetAddresses()
		{
			var now = DateTime.Now;
			if (now - lastDiscoveryLookup < TimeSpan.FromSeconds(1))
{'fraction_non_alphanumeric': 0.09547738693467336, 'fraction_numerical': 0.001352918438345574, 'mean_word_length': 4.083497053045186, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3135138', 'n_tokens_mistral': 1862, 'n_tokens_neox': 1514, 'n_words': 318}