private void FetchServices(Timer obj) { var knownServices = RemoteServerManager.GetAllGroups().SelectMany(g => g.GetAllRemoteServers()).Select(s => s.ID); var joined = registry.Keys.Except(knownServices); var left = knownServices.Except(registry.Keys); foreach (ushort joinedID in joined) { if (joinedID != RemoteServerManager.ServerID) { RegistryEntry service = registry[joinedID]; string group = service.Group; Logger.Trace($"Discovered server {joinedID} from group '{group}'."); HandleServerJoin(joinedID, group, service.Host, service.Port, new Dictionary <string, string>(service.Properties)); } } //TODO consider just a set method instead of/as well as join/leave foreach (ushort leftID in left) { if (leftID != RemoteServerManager.ServerID) { Logger.Trace($"Server {leftID} has left the cluster."); HandleServerLeave(leftID); } } }
/// <summary> /// Pulls the current services from Consul and updates the server with any changes to that list. /// </summary> /// <returns>A task object for the operation.</returns> protected async Task FetchServices() { Logger.Trace($"Refreshing services (I'm server {RemoteServerManager.ServerID})."); // Query Consul for the current list of services // TODO the library we use doesn't seem to allow us to get only services with a passing health check QueryResult <CatalogService[]> result; try { result = await client.Catalog.Service(serviceName); } catch (Exception e) { Logger.Error("Failed to fetch services from Consul as an exception occurred.", e); return; } CatalogService[] services = result.Response; // Map to ushort IDs Dictionary <ushort, CatalogService> parsedServices = services.ToDictionary(s => ushort.Parse(s.ServiceID), s => s); // Get all known sevices // TODO if a server isn't in a group we're connected with then they're not retured here which causes us to perpetually discover them IEnumerable <ushort> knownServices = RemoteServerManager.GetAllGroups().SelectMany(g => g.GetAllRemoteServers()).Select(s => s.ID); // Diff the current services aginst the known services IEnumerable <ushort> joined, left; joined = parsedServices.Keys.Where(k => !knownServices.Contains(k)); left = knownServices.Where(k => !parsedServices.ContainsKey(k)); foreach (ushort joinedID in joined) { CatalogService service = parsedServices[joinedID]; string group = service.ServiceTags.First().Substring(6); HandleServerJoin(joinedID, group, service.Address, (ushort)service.ServicePort, service.ServiceMeta); } //TODO consider just a set method instead of/as well as join/leave foreach (ushort leftID in left) { HandleServerLeave(leftID); } }