public async Task <Boolean> UpdateRow(MembershipEntry entry, String etag, TableVersion tableVersion)
        {
            //Update Silo Liveness
            try
            {
                var siloRegistration = ConsulSiloRegistrationAssembler.FromMembershipEntry(this.clusterId, entry, etag);
                var updateKV         = ConsulSiloRegistrationAssembler.ToKVPair(siloRegistration, this.kvRootFolder);

                //If the KV.CAS() call returns false then the update failed
                var tryUpdate = await _consulClient.KV.CAS(updateKV);

                if (!tryUpdate.Response)
                {
                    _logger.Debug("ConsulMembershipProvider failed the CAS check when updating the registration for silo {0}.", entry.SiloAddress);
                    return(false);
                }

                return(true);
            }
            catch (Exception ex)
            {
                _logger.Info("ConsulMembershipProvider failed to update the registration for silo {0}: {1}.", entry.SiloAddress, ex);
                throw;
            }
        }
Beispiel #2
0
        public async Task CleanupDefunctSiloEntries(DateTimeOffset beforeDate)
        {
            var allKVs = await _consulClient.KV.List(ConsulSiloRegistrationAssembler.FormatDeploymentKVPrefix(this.clusterId, this.kvRootFolder));

            if (allKVs.Response == null)
            {
                _logger.Debug("Could not find any silo registrations for deployment {0}.", this.clusterId);
                return;
            }

            var allRegistrations =
                allKVs.Response
                .Where(siloKV => !siloKV.Key.EndsWith(ConsulSiloRegistrationAssembler.SiloIAmAliveSuffix, StringComparison.OrdinalIgnoreCase) &&
                       !siloKV.Key.EndsWith(ConsulSiloRegistrationAssembler.VersionSuffix, StringComparison.OrdinalIgnoreCase))
                .Select(siloKV =>
            {
                var iAmAliveKV = allKVs.Response.Where(kv => kv.Key.Equals(ConsulSiloRegistrationAssembler.FormatSiloIAmAliveKey(siloKV.Key), StringComparison.OrdinalIgnoreCase)).SingleOrDefault();
                return(new
                {
                    RegistrationKey = siloKV.Key,
                    Registration = ConsulSiloRegistrationAssembler.FromKVPairs(clusterId, siloKV, iAmAliveKV)
                });
            }).ToArray();

            foreach (var entry in allRegistrations)
            {
                if (entry.Registration.IAmAliveTime < beforeDate)
                {
                    await _consulClient.KV.DeleteTree(entry.RegistrationKey);
                }
            }
        }
Beispiel #3
0
        public async Task <bool> InsertRow(MembershipEntry entry, TableVersion tableVersion)
        {
            try
            {
                //Use "0" as the eTag then Consul KV CAS will treat the operation as an insert and return false if the KV already exiats.
                var siloRegistration = ConsulSiloRegistrationAssembler.FromMembershipEntry(this.clusterId, entry, "0");
                var insertKV         = ConsulSiloRegistrationAssembler.ToKVPair(siloRegistration, this.kvRootFolder);
                var rowInsert        = new KVTxnOp(insertKV.Key, KVTxnVerb.CAS)
                {
                    Index = siloRegistration.LastIndex, Value = insertKV.Value
                };
                var versionUpdate = this.GetVersionRowUpdate(tableVersion);

                var responses = await _consulClient.KV.Txn(new List <KVTxnOp> {
                    rowInsert, versionUpdate
                });

                if (!responses.Response.Success)
                {
                    _logger.Debug("ConsulMembershipProvider failed to insert the row {0}.", entry.SiloAddress);
                    return(false);
                }

                return(true);
            }
            catch (Exception ex)
            {
                _logger.Info("ConsulMembershipProvider failed to insert registration for silo {0}; {1}.", entry.SiloAddress, ex);
                throw;
            }
        }
Beispiel #4
0
        public async Task <bool> UpdateRow(MembershipEntry entry, string etag, TableVersion tableVersion)
        {
            //Update Silo Liveness
            try
            {
                var siloRegistration = ConsulSiloRegistrationAssembler.FromMembershipEntry(this.clusterId, entry, etag);
                var updateKV         = ConsulSiloRegistrationAssembler.ToKVPair(siloRegistration, this.kvRootFolder);

                var rowUpdate = new KVTxnOp(updateKV.Key, KVTxnVerb.CAS)
                {
                    Index = siloRegistration.LastIndex, Value = updateKV.Value
                };
                var versionUpdate = this.GetVersionRowUpdate(tableVersion);

                var responses = await _consulClient.KV.Txn(new List <KVTxnOp> {
                    rowUpdate, versionUpdate
                });

                if (!responses.Response.Success)
                {
                    _logger.Debug("ConsulMembershipProvider failed the CAS check when updating the registration for silo {0}.", entry.SiloAddress);
                    return(false);
                }

                return(true);
            }
            catch (Exception ex)
            {
                _logger.Info("ConsulMembershipProvider failed to update the registration for silo {0}: {1}.", entry.SiloAddress, ex);
                throw;
            }
        }
        private static MembershipTableData AssembleMembershipTableData(params ConsulSiloRegistration[] silos)
        {
            var membershipEntries = silos
                                    .Where(silo => silo != null)
                                    .Select(silo => ConsulSiloRegistrationAssembler.ToMembershipEntry(silo))
                                    .ToList();

            return(new MembershipTableData(membershipEntries, _tableVersion));
        }
Beispiel #6
0
 public ConsulBasedMembershipTable(
     ILogger <ConsulBasedMembershipTable> logger,
     IOptions <ConsulClusteringOptions> membershipTableOptions,
     IOptions <ClusterOptions> clusterOptions)
 {
     this.clusterId    = clusterOptions.Value.ClusterId;
     this.kvRootFolder = membershipTableOptions.Value.KvRootFolder;
     this._logger      = logger;
     this.clusteringSiloTableOptions = membershipTableOptions.Value;
     this._consulClient = this.clusteringSiloTableOptions.CreateClient();
     versionKey         = ConsulSiloRegistrationAssembler.FormatVersionKey(clusterId, kvRootFolder);
 }
        private async Task <ConsulSiloRegistration> GetConsulSiloRegistration(SiloAddress siloAddress)
        {
            var siloKey     = ConsulSiloRegistrationAssembler.ParseDeploymentSiloKey(this.clusterId, this.kvRootFolder, siloAddress);
            var siloKVEntry = await _consulClient.KV.List(siloKey);

            if (siloKVEntry.Response == null)
            {
                return(null);
            }

            var siloKV     = siloKVEntry.Response.Single(KV => KV.Key.Equals(siloKey, StringComparison.OrdinalIgnoreCase));
            var iAmAliveKV = siloKVEntry.Response.SingleOrDefault(KV => KV.Key.Equals(ConsulSiloRegistrationAssembler.ParseSiloIAmAliveKey(siloKey), StringComparison.OrdinalIgnoreCase));

            var siloRegistration = ConsulSiloRegistrationAssembler.FromKVPairs(this.clusterId, siloKV, iAmAliveKV);

            return(siloRegistration);
        }
Beispiel #8
0
 public ConsulBasedMembershipTable(
     ILogger <ConsulBasedMembershipTable> logger,
     IOptions <ConsulClusteringSiloOptions> membershipTableOptions,
     IOptions <ClusterOptions> clusterOptions)
 {
     this.clusterId    = clusterOptions.Value.ClusterId;
     this.kvRootFolder = membershipTableOptions.Value.KvRootFolder;
     this._logger      = logger;
     this.clusteringSiloTableOptions = membershipTableOptions.Value;
     _consulClient =
         new ConsulClient(config =>
     {
         config.Address = this.clusteringSiloTableOptions.Address;
         config.Token   = this.clusteringSiloTableOptions.AclClientToken;
     });
     versionKey = ConsulSiloRegistrationAssembler.FormatVersionKey(clusterId, kvRootFolder);
 }
Beispiel #9
0
        private async Task <(ConsulSiloRegistration, TableVersion)> GetConsulSiloRegistration(SiloAddress siloAddress)
        {
            var deploymentKey = ConsulSiloRegistrationAssembler.FormatDeploymentKVPrefix(this.clusterId, this.kvRootFolder);
            var siloKey       = ConsulSiloRegistrationAssembler.FormatDeploymentSiloKey(this.clusterId, this.kvRootFolder, siloAddress);
            var entries       = await _consulClient.KV.List(deploymentKey);

            if (entries.Response == null)
            {
                return(null, NotFoundTableVersion);
            }

            var siloKV       = entries.Response.Single(KV => KV.Key.Equals(siloKey, StringComparison.OrdinalIgnoreCase));
            var iAmAliveKV   = entries.Response.SingleOrDefault(KV => KV.Key.Equals(ConsulSiloRegistrationAssembler.FormatSiloIAmAliveKey(siloKey), StringComparison.OrdinalIgnoreCase));
            var tableVersion = GetTableVersion(versionKey: versionKey, entries: entries);

            var siloRegistration = ConsulSiloRegistrationAssembler.FromKVPairs(this.clusterId, siloKV, iAmAliveKV);

            return(siloRegistration, tableVersion);
        }
        public static async Task <MembershipTableData> ReadAll(ConsulClient consulClient, string clusterId, string kvRootFolder, ILogger logger)
        {
            var deploymentKVAddresses = await consulClient.KV.List(ConsulSiloRegistrationAssembler.ParseDeploymentKVPrefix(clusterId, kvRootFolder));

            if (deploymentKVAddresses.Response == null)
            {
                logger.Debug("Could not find any silo registrations for deployment {0}.", clusterId);
                return(new MembershipTableData(_tableVersion));
            }

            var allSiloRegistrations =
                deploymentKVAddresses.Response
                .Where(siloKV => !siloKV.Key.EndsWith(ConsulSiloRegistrationAssembler.SiloIAmAliveSuffix, StringComparison.OrdinalIgnoreCase))
                .Select(siloKV =>
            {
                var iAmAliveKV = deploymentKVAddresses.Response.Where(kv => kv.Key.Equals(ConsulSiloRegistrationAssembler.ParseSiloIAmAliveKey(siloKV.Key), StringComparison.OrdinalIgnoreCase)).SingleOrDefault();
                return(ConsulSiloRegistrationAssembler.FromKVPairs(clusterId, siloKV, iAmAliveKV));
            }).ToArray();

            return(AssembleMembershipTableData(allSiloRegistrations));
        }
        public async Task <Boolean> InsertRow(MembershipEntry entry, TableVersion tableVersion)
        {
            try
            {
                //Use "0" as the eTag then Consul KV CAS will treat the operation as an insert and return false if the KV already exiats.
                var consulSiloRegistration = ConsulSiloRegistrationAssembler.FromMembershipEntry(this.clusterId, entry, "0");
                var insertKV = ConsulSiloRegistrationAssembler.ToKVPair(consulSiloRegistration, this.kvRootFolder);

                var tryUpdate = await _consulClient.KV.CAS(insertKV);

                if (!tryUpdate.Response)
                {
                    _logger.Debug("ConsulMembershipProvider failed to insert the row because a registration already exists for silo {0}.", entry.SiloAddress);
                    return(false);
                }

                return(true);
            }
            catch (Exception ex)
            {
                _logger.Info("ConsulMembershipProvider failed to insert registration for silo {0}; {1}.", entry.SiloAddress, ex);
                throw;
            }
        }
 public async Task DeleteMembershipTableEntries(String clusterId)
 {
     await _consulClient.KV.DeleteTree(ConsulSiloRegistrationAssembler.ParseDeploymentKVPrefix(this.clusterId, this.kvRootFolder));
 }
 public async Task UpdateIAmAlive(MembershipEntry entry)
 {
     var iAmAliveKV = ConsulSiloRegistrationAssembler.ToIAmAliveKVPair(this.clusterId, this.kvRootFolder, entry.SiloAddress, entry.IAmAliveTime);
     await _consulClient.KV.Put(iAmAliveKV);
 }
 public async Task DeleteMembershipTableEntries(String deploymentId)
 {
     await _consulClient.KV.DeleteTree(ConsulSiloRegistrationAssembler.ParseDeploymentKVPrefix(this.deploymentId));
 }