예제 #1
0
        private SiloEntity ConvertToEntity(MembershipEntry membershipEntry)
        {
            var tableEntry = new SiloEntity
            {
                Metadata = new V1ObjectMeta {
                    Name = ConstructSiloEntityId(membershipEntry.SiloAddress)
                },
                ClusterId    = this._clusterOptions.ClusterId,
                Address      = membershipEntry.SiloAddress.Endpoint.Address.ToString(),
                Port         = membershipEntry.SiloAddress.Endpoint.Port,
                Generation   = membershipEntry.SiloAddress.Generation,
                Hostname     = membershipEntry.HostName,
                Status       = membershipEntry.Status,
                ProxyPort    = membershipEntry.ProxyPort,
                SiloName     = membershipEntry.SiloName,
                StartTime    = membershipEntry.StartTime,
                IAmAliveTime = membershipEntry.IAmAliveTime,
                Kind         = SiloEntity.KIND,
                ApiVersion   = $"{Constants.ORLEANS_GROUP}/{Constants.PROVIDER_MODEL_VERSION}",
            };

            if (membershipEntry.SuspectTimes != null)
            {
                foreach (var tuple in membershipEntry.SuspectTimes)
                {
                    tableEntry.SuspectingSilos.Add(tuple.Item1.ToParsableString());
                    tableEntry.SuspectingTimes.Add(LogFormatter.PrintDate(tuple.Item2));
                }
            }

            return(tableEntry);
        }
예제 #2
0
        private static SiloEntity ConvertToEntity(MembershipEntry memEntry, string clusterId)
        {
            var tableEntry = new SiloEntity
            {
                Id           = ConstructSiloEntityId(memEntry.SiloAddress),
                ClusterId    = clusterId,
                Address      = memEntry.SiloAddress.Endpoint.Address.ToString(),
                Port         = memEntry.SiloAddress.Endpoint.Port,
                Generation   = memEntry.SiloAddress.Generation,
                Hostname     = memEntry.HostName,
                Status       = memEntry.Status,
                ProxyPort    = memEntry.ProxyPort,
                SiloName     = memEntry.SiloName,
                StartTime    = memEntry.StartTime,
                IAmAliveTime = memEntry.IAmAliveTime
            };

            if (memEntry.SuspectTimes != null)
            {
                foreach (var tuple in memEntry.SuspectTimes)
                {
                    tableEntry.SuspectingSilos.Add(tuple.Item1.ToParsableString());
                    tableEntry.SuspectingTimes.Add(LogFormatter.PrintDate(tuple.Item2));
                }
            }

            return(tableEntry);
        }
예제 #3
0
        public async Task <MembershipTableData> ReadRow(SiloAddress key)
        {
            var name = ConstructSiloEntityId(key);

            try
            {
                var versionEntity = await this.GetClusterVersion();

                SiloEntity entity = default;

                try
                {
                    entity = ((JObject)await this._kubeClient.GetNamespacedCustomObjectAsync(
                                  Constants.ORLEANS_GROUP,
                                  Constants.PROVIDER_MODEL_VERSION,
                                  this._namespace,
                                  SiloEntity.PLURAL,
                                  name
                                  ))?.ToObject <SiloEntity>();
                }
                catch (HttpOperationException ex)
                {
                    if (ex.Response.StatusCode != HttpStatusCode.NotFound)
                    {
                        throw;
                    }
                }

                var version = default(TableVersion);

                if (versionEntity != null)
                {
                    version = new TableVersion(versionEntity.ClusterVersion, versionEntity.Metadata.ResourceVersion);
                }
                else
                {
                    this._logger?.LogError("Initial ClusterVersionEntity entity doesn't exist.");
                }

                var memEntries = new List <Tuple <MembershipEntry, string> >();

                if (entity != null)
                {
                    var membershipEntry = ParseEntity(entity);

                    memEntries.Add(new Tuple <MembershipEntry, string>(membershipEntry, entity.Metadata.ResourceVersion));
                }

                var data = new MembershipTableData(memEntries, version);

                return(data);
            }
            catch (Exception exc)
            {
                this._logger?.LogError(exc, "Failure reading silo entry {name} for cluster id {clusterId}.", name, this._clusterOptions.ClusterId);

                throw;
            }
        }
예제 #4
0
        private static MembershipEntry ParseEntity(SiloEntity entity)
        {
            var entry = new MembershipEntry
            {
                HostName = entity.Hostname,
                Status   = entity.Status
            };

            if (entity.ProxyPort.HasValue)
            {
                entry.ProxyPort = entity.ProxyPort.Value;
            }

            entry.SiloAddress = SiloAddress.New(new IPEndPoint(IPAddress.Parse(entity.Address), entity.Port), entity.Generation);

            entry.SiloName = entity.SiloName;

            entry.StartTime = entity.StartTime.UtcDateTime;

            entry.IAmAliveTime = entity.IAmAliveTime.UtcDateTime;

            var suspectingSilos = new List <SiloAddress>();
            var suspectingTimes = new List <DateTime>();

            foreach (var silo in entity.SuspectingSilos)
            {
                suspectingSilos.Add(SiloAddress.FromParsableString(silo));
            }

            foreach (var time in entity.SuspectingTimes)
            {
                suspectingTimes.Add(LogFormatter.ParseDate(time));
            }

            if (suspectingSilos.Count != suspectingTimes.Count)
            {
                throw new OrleansException($"SuspectingSilos.Length of {suspectingSilos.Count} as read from Kubernetes is not equal to SuspectingTimes.Length of {suspectingTimes.Count}");
            }

            for (int i = 0; i < suspectingSilos.Count; i++)
            {
                entry.AddSuspector(suspectingSilos[i], suspectingTimes[i]);
            }

            return(entry);
        }
예제 #5
0
        public async Task UpdateIAmAlive(MembershipEntry entry)
        {
            var name = ConstructSiloEntityId(entry.SiloAddress);

            try
            {
                SiloEntity siloEntity = default;

                try
                {
                    siloEntity = ((JObject)await this._kubeClient.GetNamespacedCustomObjectAsync(
                                      Constants.ORLEANS_GROUP,
                                      Constants.PROVIDER_MODEL_VERSION,
                                      this._namespace,
                                      SiloEntity.PLURAL,
                                      name
                                      ))?.ToObject <SiloEntity>();
                }
                catch (HttpOperationException ex)
                {
                    if (ex.Response.StatusCode == HttpStatusCode.NotFound)
                    {
                        throw new InvalidOperationException($"Unable to find silo entry {name}.");
                    }

                    throw;
                }

                siloEntity.IAmAliveTime = entry.IAmAliveTime;

                await this._kubeClient.ReplaceNamespacedCustomObjectAsync(
                    siloEntity,
                    Constants.ORLEANS_GROUP,
                    Constants.PROVIDER_MODEL_VERSION,
                    this._namespace,
                    SiloEntity.PLURAL,
                    siloEntity.Metadata.Name
                    );
            }
            catch (Exception exc)
            {
                this._logger?.LogError(exc, "Unable to update Silo Entry {name}.", name);

                throw;
            }
        }
예제 #6
0
        public async Task <bool> InsertRow(MembershipEntry entry, TableVersion tableVersion)
        {
            try
            {
                var siloEntity    = this.ConvertToEntity(entry);
                var versionEntity = this.BuildVersionEntity(tableVersion);

                SiloEntity existentSiloEntry = default;

                try
                {
                    existentSiloEntry = ((JObject)await this._kubeClient.GetNamespacedCustomObjectAsync(
                                             Constants.ORLEANS_GROUP,
                                             Constants.PROVIDER_MODEL_VERSION,
                                             this._namespace,
                                             SiloEntity.PLURAL,
                                             siloEntity.Metadata.Name
                                             ))?.ToObject <SiloEntity>();
                }
                catch (HttpOperationException ex)
                {
                    if (ex.Response.StatusCode != HttpStatusCode.NotFound)
                    {
                        throw;
                    }
                }

                if (existentSiloEntry != null)
                {
                    return(false);
                }

                var currentVersionEntity = await this.GetClusterVersion();

                if (currentVersionEntity == null ||
                    currentVersionEntity.ClusterVersion == versionEntity.ClusterVersion)
                {
                    return(false);
                }

                var updatedVersionEntity = await this._kubeClient.ReplaceNamespacedCustomObjectAsync(
                    versionEntity,
                    Constants.ORLEANS_GROUP,
                    Constants.PROVIDER_MODEL_VERSION,
                    this._namespace,
                    ClusterVersionEntity.PLURAL,
                    versionEntity.Metadata.Name
                    );

                if (updatedVersionEntity == null)
                {
                    return(false);
                }

                var createdSiloEntity = await this._kubeClient.CreateNamespacedCustomObjectAsync(
                    siloEntity,
                    Constants.ORLEANS_GROUP,
                    Constants.PROVIDER_MODEL_VERSION,
                    this._namespace,
                    SiloEntity.PLURAL
                    );

                return(createdSiloEntity != null);
            }
            catch (InvalidOperationException)
            {
                return(false);
            }
            catch (Exception exc)
            {
                this._logger?.LogError(exc, "Unable to insert Silo Entry.");

                throw;
            }
        }
        private static Uri ConvertToGatewayUri(SiloEntity gateway)
        {
            SiloAddress address = SiloAddress.New(new IPEndPoint(IPAddress.Parse(gateway.Address), gateway.ProxyPort.Value), gateway.Generation);

            return(address.ToGatewayUri());
        }
예제 #8
0
        private async Task <(ClusterVersionEntity Version, List <SiloEntity> Silos)> ReadRecords(string clusterId)
        {
            var query = this._container
                        .GetItemQueryIterator <dynamic>(
                READ_ALL_QUERY,
                requestOptions: new QueryRequestOptions
            {
                PartitionKey = new PartitionKey(clusterId)
            }
                );

            var silos = new List <SiloEntity>();
            ClusterVersionEntity clusterVersion = null;

            do
            {
                var items = await query.ReadNextAsync();

                var version = items.Where(i => i.EntityType == nameof(ClusterVersionEntity)).SingleOrDefault();
                if (version != null)
                {
                    clusterVersion = ClusterVersionEntity.FromDocument(version);
                }

                silos.AddRange(items.Where(i => i.EntityType == nameof(SiloEntity)).Select(d => (SiloEntity)SiloEntity.FromDocument(d)));
            } while (query.HasMoreResults);

            return(clusterVersion, silos);
        }
예제 #9
0
        public async Task <MembershipTableData> ReadRow(SiloAddress key)
        {
            var id = ConstructSiloEntityId(key);

            try
            {
                var query = this._container
                            .GetItemQueryIterator <dynamic>(
                    new QueryDefinition(READ_ENTRY_QUERY).WithParameter("@siloId", id),
                    requestOptions: new QueryRequestOptions
                {
                    PartitionKey = new PartitionKey(this._clusterOptions.ClusterId)
                }
                    );

                var docs = await query.ReadNextAsync();

                var versionDoc = docs.Where(i => i.EntityType == nameof(ClusterVersionEntity)).SingleOrDefault();
                ClusterVersionEntity clusterVersionEntity = versionDoc != null?ClusterVersionEntity.FromDocument(versionDoc) : default;

                var siloEntities = docs.Where(i => i.EntityType == nameof(SiloEntity)).Select <dynamic, SiloEntity>(d => SiloEntity.FromDocument(d));

                TableVersion version = null;
                if (clusterVersionEntity != null)
                {
                    version = new TableVersion(clusterVersionEntity.ClusterVersion, clusterVersionEntity.ETag);
                }
                else
                {
                    this._logger.LogError("Initial ClusterVersionEntity entity doesn't exist.");
                }

                var memEntries = new List <Tuple <MembershipEntry, string> >();
                foreach (var entity in siloEntities)
                {
                    try
                    {
                        MembershipEntry membershipEntry = ParseEntity(entity);
                        memEntries.Add(new Tuple <MembershipEntry, string>(membershipEntry, entity.ETag));
                    }
                    catch (Exception exc)
                    {
                        this._logger.LogError(exc, "Failure reading membership row.");
                        throw;
                    }
                }

                var data = new MembershipTableData(memEntries, version);
                return(data);
            }
            catch (Exception exc)
            {
                this._logger.LogWarning($"Failure reading silo entry {id} for cluster id {this._clusterOptions.ClusterId}: {exc}");
                throw;
            }
        }