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);
                }
            }
        }
示例#2
0
        /// <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);
            }
        }