Beispiel #1
0
        /// <summary>Gets a detailed grain report from a specified silo</summary>
        /// <param name="grainFactory">The grain factory.</param>
        /// <param name="grainId">The grain id we are requesting information from</param>
        /// <param name="siloHandle">The target silo that should provide this information from it's cache</param>
        internal static Task <DetailedGrainReport> GetDetailedGrainReport(IInternalGrainFactory grainFactory, GrainId grainId, SiloHandle siloHandle)
        {
            var siloControl = grainFactory.GetSystemTarget <ISiloControl>(Constants.SiloControlId, siloHandle.ProxyAddress);

            return(siloControl.GetDetailedGrainReport(grainId));
        }
 private IClusterTypeManager GetTypeManager(SiloAddress destination, IInternalGrainFactory grainFactory)
 {
     return(grainFactory.GetSystemTarget <IClusterTypeManager>(Constants.TypeManagerId, destination));
 }
        private async Task <bool> UpdateManifest(ClusterMembershipSnapshot clusterMembership)
        {
            var existingManifest = _current;
            var builder          = existingManifest.Silos.ToBuilder();
            var modified         = false;

            // First, remove defunct entries.
            foreach (var entry in existingManifest.Silos)
            {
                var address = entry.Key;
                var status  = clusterMembership.GetSiloStatus(address);

                if (address.Equals(_localSiloAddress))
                {
                    // The local silo is always present in the manifest.
                    continue;
                }

                if (status == SiloStatus.None || status == SiloStatus.Dead)
                {
                    builder.Remove(address);
                    modified = true;
                }
            }

            // Next, fill missing entries.
            var tasks = new List <Task <(SiloAddress Key, SiloManifest Value, Exception Exception)> >();

            foreach (var entry in clusterMembership.Members)
            {
                var member = entry.Value;

                if (member.SiloAddress.Equals(_localSiloAddress))
                {
                    // The local silo is always present in the manifest.
                    continue;
                }

                if (existingManifest.Silos.ContainsKey(member.SiloAddress))
                {
                    // Manifest has already been retrieved for the cluster member.
                    continue;
                }

                if (member.Status != SiloStatus.Active)
                {
                    // If the member is not yet active, it may not be ready to process requests.
                    continue;
                }

                tasks.Add(GetManifest(member.SiloAddress));

                async Task <(SiloAddress, SiloManifest, Exception)> GetManifest(SiloAddress siloAddress)
                {
                    try
                    {
                        // Get the manifest from the remote silo.
                        var remoteManifestProvider = _grainFactory.GetSystemTarget <ISiloManifestSystemTarget>(Constants.ManifestProviderType, member.SiloAddress);
                        var manifest = await remoteManifestProvider.GetSiloManifest();

                        return(siloAddress, manifest, null);
                    }
                    catch (Exception exception)
                    {
                        return(siloAddress, null, exception);
                    }
                }
            }

            var fetchSuccess = true;
            await Task.WhenAll(tasks);

            foreach (var task in tasks)
            {
                var result = await task;
                if (result.Exception is Exception exception)
                {
                    fetchSuccess = false;
                    _logger.LogWarning(exception, "Error retrieving silo manifest for silo {SiloAddress}", result.Key);
                }
                else
                {
                    modified            = true;
                    builder[result.Key] = result.Value;
                }
            }

            // Regardless of success or failure, update the manifest if it has been modified.
            var version = new MajorMinorVersion(clusterMembership.Version.Value, existingManifest.Version.Minor + 1);

            if (modified)
            {
                return(_updates.TryPublish(new ClusterManifest(version, builder.ToImmutable())) && fetchSuccess);
            }

            return(fetchSuccess);
        }