Exemplo n.º 1
0
 public void SetWatch(long watchId, Watch watch)
 => _watches.TryAdd(watchId, watch);
        public Watch CreateWatch(
            bool ads,
            DiscoveryRequest request,
            ISet <string>?knownResourceNames,
            Action <Response> responseCallback)
        {
            var group = _hash(request.Node);

            // even though we're modifying, we take a readLock to allow multiple watches to be created in parallel since it
            // doesn't conflict
            _rwLock.EnterReadLock();
            try
            {
                var status = _statuses.GetOrAdd(group, g => new CacheStatusInfo <T>(group));

                status.SetLastWatchRequestTime(DateTimeOffset.UtcNow.Ticks);

                _snapshots.TryGetValue(group, out Snapshot? snapshot);
                var version = snapshot == null
                    ? string.Empty
                    : snapshot.GetVersion(request.TypeUrl, request.ResourceNames);

                var watch = new Watch(ads, request, responseCallback);

                if (snapshot != null)
                {
                    var requestedResources = ImmutableHashSet.CreateRange(request.ResourceNames);
                    var newResourceHints   = requestedResources.Except(knownResourceNames);

                    // If the request is asking for resources we haven't sent to the proxy yet, see if we have additional resources.
                    if (newResourceHints.Any())
                    {
                        // If any of the newly requested resources are in the snapshot respond immediately. If not we'll fall back to
                        // version comparisons.
                        if (snapshot.GetResources(request.TypeUrl).Keys.Any(newResourceHints.Contains))
                        {
                            this.Respond(watch, snapshot, group);
                            return(watch);
                        }
                    }
                }

                // If the requested version is up-to-date or missing a response, leave an open watch.
                if (snapshot == null || request.VersionInfo.Equals(version))
                {
                    long watchId = Interlocked.Increment(ref _watchCount);

                    Logger.LogDebug("open watch {0} for {1}[{2}] from node {3} for version {4}",
                                    watchId,
                                    request.TypeUrl,
                                    string.Join(", ", request.ResourceNames),
                                    group,
                                    request.VersionInfo);

                    status.SetWatch(watchId, watch);

                    watch.SetStop(() => status.RemoveWatch(watchId));

                    return(watch);
                }

                // Otherwise, the watch may be responded immediately
                var responded = this.Respond(watch, snapshot, group);

                if (!responded)
                {
                    long watchId = Interlocked.Increment(ref _watchCount);


                    Logger.LogDebug("did not respond immediately, leaving open watch {0} for {1}[{2}] from node {3} for version {4}",
                                    watchId,
                                    request.TypeUrl,
                                    string.Join(", ", request.ResourceNames),
                                    group,
                                    request.VersionInfo);

                    status.SetWatch(watchId, watch);
                    watch.SetStop(() => status.RemoveWatch(watchId));
                }

                return(watch);
            }
            finally
            {
                _rwLock.ExitReadLock();
            }
        }