|  |  |  | @ -32,7 +32,6 @@ namespace ZeroLevel.Network | 
			
		
	
		
			
				
					|  |  |  |  |     internal sealed class Exchange : | 
			
		
	
		
			
				
					|  |  |  |  |         IExchange | 
			
		
	
		
			
				
					|  |  |  |  |     { | 
			
		
	
		
			
				
					|  |  |  |  |         private IDiscoveryClient _discoveryClient = null; // Feature расширить до нескольких discovery         | 
			
		
	
		
			
				
					|  |  |  |  |         private readonly ServiceRouteStorage _aliases = new ServiceRouteStorage(); | 
			
		
	
		
			
				
					|  |  |  |  |         private readonly ExClientServerCachee _cachee = new ExClientServerCachee(); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
	
		
			
				
					|  |  |  | @ -44,8 +43,8 @@ namespace ZeroLevel.Network | 
			
		
	
		
			
				
					|  |  |  |  |         public Exchange(IZeroService owner) | 
			
		
	
		
			
				
					|  |  |  |  |         { | 
			
		
	
		
			
				
					|  |  |  |  |             _owner = owner; | 
			
		
	
		
			
				
					|  |  |  |  |             _cachee.OnBrokenConnection += _cachee_OnBrokenConnection; | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         #endregion Ctor | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         #region IMultiClient       | 
			
		
	
	
		
			
				
					|  |  |  | @ -458,37 +457,43 @@ namespace ZeroLevel.Network | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         public void UseDiscovery() | 
			
		
	
		
			
				
					|  |  |  |  |         { | 
			
		
	
		
			
				
					|  |  |  |  |             if (_discoveryClient != null) | 
			
		
	
		
			
				
					|  |  |  |  |             try | 
			
		
	
		
			
				
					|  |  |  |  |             { | 
			
		
	
		
			
				
					|  |  |  |  |                 _discoveryClient.Dispose(); | 
			
		
	
		
			
				
					|  |  |  |  |                 _discoveryClient = null; | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  |             var discovery = Configuration.Default.First("discovery"); | 
			
		
	
		
			
				
					|  |  |  |  |             _discoveryClient = new DiscoveryClient(_cachee.GetClient(NetUtils.CreateIPEndPoint(discovery), false, BaseSocket.NullRouter)); | 
			
		
	
		
			
				
					|  |  |  |  |                 var discoveryEndpoint = Configuration.Default.First("discovery"); | 
			
		
	
		
			
				
					|  |  |  |  |                 _aliases.Set(BaseSocket.DISCOVERY_ALIAS, NetUtils.CreateIPEndPoint(discoveryEndpoint)); | 
			
		
	
		
			
				
					|  |  |  |  |                 RestartDiscoveryTasks(); | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  |             catch (Exception ex) | 
			
		
	
		
			
				
					|  |  |  |  |             { | 
			
		
	
		
			
				
					|  |  |  |  |                 Log.Error(ex, "[Exchange.UseDiscovery]"); | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         public void UseDiscovery(string endpoint) | 
			
		
	
		
			
				
					|  |  |  |  |         public void UseDiscovery(string discoveryEndpoint) | 
			
		
	
		
			
				
					|  |  |  |  |         { | 
			
		
	
		
			
				
					|  |  |  |  |             try | 
			
		
	
		
			
				
					|  |  |  |  |             { | 
			
		
	
		
			
				
					|  |  |  |  |             if (_discoveryClient != null) | 
			
		
	
		
			
				
					|  |  |  |  |                 _aliases.Set(BaseSocket.DISCOVERY_ALIAS, NetUtils.CreateIPEndPoint(discoveryEndpoint)); | 
			
		
	
		
			
				
					|  |  |  |  |                 RestartDiscoveryTasks(); | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  |             catch (Exception ex) | 
			
		
	
		
			
				
					|  |  |  |  |             { | 
			
		
	
		
			
				
					|  |  |  |  |                 _discoveryClient.Dispose(); | 
			
		
	
		
			
				
					|  |  |  |  |                 _discoveryClient = null; | 
			
		
	
		
			
				
					|  |  |  |  |                 Log.Error(ex, "[Exchange.UseDiscovery]"); | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  |             _discoveryClient = new DiscoveryClient(_cachee.GetClient(NetUtils.CreateIPEndPoint(endpoint), false, BaseSocket.NullRouter)); | 
			
		
	
		
			
				
					|  |  |  |  |             RestartDiscoveryTasks(); | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         public void UseDiscovery(IPEndPoint endpoint) | 
			
		
	
		
			
				
					|  |  |  |  |         public void UseDiscovery(IPEndPoint discoveryEndpoint) | 
			
		
	
		
			
				
					|  |  |  |  |         { | 
			
		
	
		
			
				
					|  |  |  |  |             if (_discoveryClient != null) | 
			
		
	
		
			
				
					|  |  |  |  |             try | 
			
		
	
		
			
				
					|  |  |  |  |             { | 
			
		
	
		
			
				
					|  |  |  |  |                 _discoveryClient.Dispose(); | 
			
		
	
		
			
				
					|  |  |  |  |                 _discoveryClient = null; | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  |             _discoveryClient = new DiscoveryClient(_cachee.GetClient(endpoint, false, BaseSocket.NullRouter)); | 
			
		
	
		
			
				
					|  |  |  |  |                 _aliases.Set(BaseSocket.DISCOVERY_ALIAS, discoveryEndpoint); | 
			
		
	
		
			
				
					|  |  |  |  |                 RestartDiscoveryTasks(); | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  |             catch (Exception ex) | 
			
		
	
		
			
				
					|  |  |  |  |             { | 
			
		
	
		
			
				
					|  |  |  |  |                 Log.Error(ex, "[Exchange.UseDiscovery]"); | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         private void RestartDiscoveryTasks() | 
			
		
	
		
			
				
					|  |  |  |  |         { | 
			
		
	
	
		
			
				
					|  |  |  | @ -500,13 +505,16 @@ namespace ZeroLevel.Network | 
			
		
	
		
			
				
					|  |  |  |  |             { | 
			
		
	
		
			
				
					|  |  |  |  |                 Sheduller.Remove(_register_in_discovery_table_task); | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  |             RegisterServicesInDiscovery(); | 
			
		
	
		
			
				
					|  |  |  |  |             _update_discovery_table_task = Sheduller.RemindEvery(_update_discovery_table_period, RegisterServicesInDiscovery); | 
			
		
	
		
			
				
					|  |  |  |  |             _register_in_discovery_table_task = Sheduller.RemindEvery(_register_in_discovery_table_period, UpdateServiceListFromDiscovery); | 
			
		
	
		
			
				
					|  |  |  |  |             _register_in_discovery_table_task = Sheduller.RemindEvery(TimeSpan.FromMilliseconds(500), _update_discovery_table_period, RegisterServicesInDiscovery); | 
			
		
	
		
			
				
					|  |  |  |  |             _update_discovery_table_task = Sheduller.RemindEvery(TimeSpan.FromMilliseconds(750), _register_in_discovery_table_period, UpdateServiceListFromDiscovery); | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         private void RegisterServicesInDiscovery() | 
			
		
	
		
			
				
					|  |  |  |  |         { | 
			
		
	
		
			
				
					|  |  |  |  |             var discovery_endpoint = _aliases.Get(BaseSocket.DISCOVERY_ALIAS); | 
			
		
	
		
			
				
					|  |  |  |  |             if (discovery_endpoint.Success) | 
			
		
	
		
			
				
					|  |  |  |  |             { | 
			
		
	
		
			
				
					|  |  |  |  |                 var discoveryClient = _cachee.GetClient(discovery_endpoint.Value, true); | 
			
		
	
		
			
				
					|  |  |  |  |                 var services = _cachee.ServerList. | 
			
		
	
		
			
				
					|  |  |  |  |                     Select(s => | 
			
		
	
		
			
				
					|  |  |  |  |                     { | 
			
		
	
	
		
			
				
					|  |  |  | @ -517,13 +525,68 @@ namespace ZeroLevel.Network | 
			
		
	
		
			
				
					|  |  |  |  |                     ToList(); | 
			
		
	
		
			
				
					|  |  |  |  |                 foreach (var service in services) | 
			
		
	
		
			
				
					|  |  |  |  |                 { | 
			
		
	
		
			
				
					|  |  |  |  |                 _discoveryClient.Register(service); | 
			
		
	
		
			
				
					|  |  |  |  |                     var request = discoveryClient.Request<ZeroServiceInfo, InvokeResult>("register", service, r => | 
			
		
	
		
			
				
					|  |  |  |  |                     { | 
			
		
	
		
			
				
					|  |  |  |  |                         if (!r.Success) | 
			
		
	
		
			
				
					|  |  |  |  |                         { | 
			
		
	
		
			
				
					|  |  |  |  |                             Log.SystemWarning($"[Exchange.RegisterServicesInDiscovery] Register canceled. {r.Comment}"); | 
			
		
	
		
			
				
					|  |  |  |  |                         } | 
			
		
	
		
			
				
					|  |  |  |  |                     }); | 
			
		
	
		
			
				
					|  |  |  |  |                     if (request.Success == false) | 
			
		
	
		
			
				
					|  |  |  |  |                     { | 
			
		
	
		
			
				
					|  |  |  |  |                         Log.SystemWarning($"[Exchange.RegisterServicesInDiscovery] Register canceled.{request.Comment}"); | 
			
		
	
		
			
				
					|  |  |  |  |                     } | 
			
		
	
		
			
				
					|  |  |  |  |                 } | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         private void UpdateServiceListFromDiscovery() | 
			
		
	
		
			
				
					|  |  |  |  |         { | 
			
		
	
		
			
				
					|  |  |  |  |              | 
			
		
	
		
			
				
					|  |  |  |  |             var discovery_endpoint = _aliases.Get(BaseSocket.DISCOVERY_ALIAS); | 
			
		
	
		
			
				
					|  |  |  |  |             if (discovery_endpoint.Success) | 
			
		
	
		
			
				
					|  |  |  |  |             { | 
			
		
	
		
			
				
					|  |  |  |  |                 var discoveryClient = _cachee.GetClient(discovery_endpoint.Value, true); | 
			
		
	
		
			
				
					|  |  |  |  |                 try | 
			
		
	
		
			
				
					|  |  |  |  |                 { | 
			
		
	
		
			
				
					|  |  |  |  |                     var ir = discoveryClient.Request<IEnumerable<ServiceEndpointsInfo>>("services", records => | 
			
		
	
		
			
				
					|  |  |  |  |                     { | 
			
		
	
		
			
				
					|  |  |  |  |                         if (records == null) | 
			
		
	
		
			
				
					|  |  |  |  |                         { | 
			
		
	
		
			
				
					|  |  |  |  |                             Log.SystemWarning("[Exchange.UpdateServiceListFromDiscovery] UpdateServiceListInfo. Discrovery response is empty"); | 
			
		
	
		
			
				
					|  |  |  |  |                             return; | 
			
		
	
		
			
				
					|  |  |  |  |                         } | 
			
		
	
		
			
				
					|  |  |  |  |                         var endpoints = new HashSet<IPEndPoint>(); | 
			
		
	
		
			
				
					|  |  |  |  |                         foreach (var service in records) | 
			
		
	
		
			
				
					|  |  |  |  |                         { | 
			
		
	
		
			
				
					|  |  |  |  |                             endpoints.Clear(); | 
			
		
	
		
			
				
					|  |  |  |  |                             foreach (var ep in service.Endpoints) | 
			
		
	
		
			
				
					|  |  |  |  |                             { | 
			
		
	
		
			
				
					|  |  |  |  |                                 try | 
			
		
	
		
			
				
					|  |  |  |  |                                 { | 
			
		
	
		
			
				
					|  |  |  |  |                                     var endpoint = NetUtils.CreateIPEndPoint(ep); | 
			
		
	
		
			
				
					|  |  |  |  |                                     endpoints.Add(endpoint); | 
			
		
	
		
			
				
					|  |  |  |  |                                 } | 
			
		
	
		
			
				
					|  |  |  |  |                                 catch | 
			
		
	
		
			
				
					|  |  |  |  |                                 { | 
			
		
	
		
			
				
					|  |  |  |  |                                     Log.SystemWarning($"[Exchange.UpdateServiceListFromDiscovery] Can't parse address {ep} as IPEndPoint"); | 
			
		
	
		
			
				
					|  |  |  |  |                                 } | 
			
		
	
		
			
				
					|  |  |  |  |                             } | 
			
		
	
		
			
				
					|  |  |  |  |                             _aliases.Set(service.ServiceKey, | 
			
		
	
		
			
				
					|  |  |  |  |                                 service.ServiceType, | 
			
		
	
		
			
				
					|  |  |  |  |                                 service.ServiceGroup, | 
			
		
	
		
			
				
					|  |  |  |  |                                 endpoints); | 
			
		
	
		
			
				
					|  |  |  |  |                         } | 
			
		
	
		
			
				
					|  |  |  |  |                     }); | 
			
		
	
		
			
				
					|  |  |  |  |                     if (!ir.Success) | 
			
		
	
		
			
				
					|  |  |  |  |                     { | 
			
		
	
		
			
				
					|  |  |  |  |                         Log.SystemWarning($"[Exchange.UpdateServiceListFromDiscovery] Error request to inbox 'services'. {ir.Comment}"); | 
			
		
	
		
			
				
					|  |  |  |  |                     } | 
			
		
	
		
			
				
					|  |  |  |  |                 } | 
			
		
	
		
			
				
					|  |  |  |  |                 catch (Exception ex) | 
			
		
	
		
			
				
					|  |  |  |  |                 { | 
			
		
	
		
			
				
					|  |  |  |  |                     Log.SystemError(ex, "[Exchange.UpdateServiceListFromDiscovery] Discovery service response is absent"); | 
			
		
	
		
			
				
					|  |  |  |  |                 } | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |         #endregion | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
	
		
			
				
					|  |  |  | @ -541,7 +604,7 @@ namespace ZeroLevel.Network | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  |             catch (Exception ex) | 
			
		
	
		
			
				
					|  |  |  |  |             { | 
			
		
	
		
			
				
					|  |  |  |  |                 Log.Error(ex, "[Exchange.GetConnection]"); | 
			
		
	
		
			
				
					|  |  |  |  |                 Log.SystemError(ex, "[Exchange.GetConnection]"); | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  |             return null; | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
	
		
			
				
					|  |  |  | @ -554,7 +617,7 @@ namespace ZeroLevel.Network | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  |             catch (Exception ex) | 
			
		
	
		
			
				
					|  |  |  |  |             { | 
			
		
	
		
			
				
					|  |  |  |  |                 Log.Error(ex, "[Exchange.GetConnection]"); | 
			
		
	
		
			
				
					|  |  |  |  |                 Log.SystemError(ex, "[Exchange.GetConnection]"); | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  |             return null; | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
	
		
			
				
					|  |  |  | @ -734,21 +797,6 @@ namespace ZeroLevel.Network | 
			
		
	
		
			
				
					|  |  |  |  |             return success; | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         private InvokeResult CallServiceDirect(string endpoint, Func<ExClient, InvokeResult> callHandler) | 
			
		
	
		
			
				
					|  |  |  |  |         { | 
			
		
	
		
			
				
					|  |  |  |  |             ExClient transport; | 
			
		
	
		
			
				
					|  |  |  |  |             try | 
			
		
	
		
			
				
					|  |  |  |  |             { | 
			
		
	
		
			
				
					|  |  |  |  |                 transport = _cachee.GetClient(NetUtils.CreateIPEndPoint(endpoint), true); | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  |             catch (Exception ex) | 
			
		
	
		
			
				
					|  |  |  |  |             { | 
			
		
	
		
			
				
					|  |  |  |  |                 Log.SystemError(ex, $"[Exchange.CallServiceDirect] Can't get transport for endpoint '{endpoint}'"); | 
			
		
	
		
			
				
					|  |  |  |  |                 return InvokeResult.Fault(ex.Message); | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  |             return callHandler(transport); | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         private IEnumerable<Tresp> _RequestBroadcast<Treq, Tresp>(List<ExClient> clients, string inbox, Treq data) | 
			
		
	
		
			
				
					|  |  |  |  |         { | 
			
		
	
		
			
				
					|  |  |  |  |             var response = new List<Tresp>(); | 
			
		
	
	
		
			
				
					|  |  |  | @ -804,6 +852,11 @@ namespace ZeroLevel.Network | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  |             return response; | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         private void _cachee_OnBrokenConnection(IPEndPoint endpoint) | 
			
		
	
		
			
				
					|  |  |  |  |         { | 
			
		
	
		
			
				
					|  |  |  |  |             //_aliases.Remove(endpoint); ??? no need | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |         #endregion | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         public void Dispose() | 
			
		
	
	
		
			
				
					|  |  |  | 
 |