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; } }
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); } } }
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; } }
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)); }
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); }
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); }
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)); }