Skip to content
Merged
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 15 additions & 16 deletions src/ConfigurationClientManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ const SECRET_KEY_NAME = "Secret";
const TRUSTED_DOMAIN_LABELS = [".azconfig.", ".appconfig."];
const FALLBACK_CLIENT_REFRESH_EXPIRE_INTERVAL = 60 * 60 * 1000; // 1 hour in milliseconds
const MINIMAL_CLIENT_REFRESH_INTERVAL = 30 * 1000; // 30 seconds in milliseconds
const SRV_QUERY_TIMEOUT = 30 * 1000; // 30 seconds in milliseconds
const DNS_RESOLVER_TIMEOUT = 1_000; // 1 second in milliseconds
const DNS_RESOLVER_TRIES = 2;
const MAX_RESOLVESRV_TIMES = 15;

export class ConfigurationClientManager {
#isFailoverable: boolean;
Expand Down Expand Up @@ -85,10 +87,11 @@ export class ConfigurationClientManager {
this.#isFailoverable = false;
return;
}
if (this.#dns) {
if (this.#dns) { // dns module is already loaded
return;
}

// We can only know whether dns module is available during runtime.
try {
this.#dns = await import("dns/promises");
} catch (error) {
Expand Down Expand Up @@ -142,20 +145,16 @@ export class ConfigurationClientManager {
}

async #discoverFallbackClients(host: string) {
let result;
let timeout;
let result: string[];
try {
result = await Promise.race([
new Promise((_, reject) => timeout = setTimeout(() => reject(new Error("SRV record query timed out.")), SRV_QUERY_TIMEOUT)),
this.#querySrvTargetHost(host)
]);
result = await this.#querySrvTargetHost(host);
} catch (error) {
throw new Error(`Failed to build fallback clients, ${error.message}`);
} finally {
clearTimeout(timeout);
console.warn(`Failed to build fallback clients, ${error.message}`);
this.#lastFallbackClientRefreshTime = Date.now();
return; // swallow the error when srv query fails
}

const srvTargetHosts = shuffleList(result) as string[];
const srvTargetHosts = shuffleList(result);
const newDynamicClients: ConfigurationClientWrapper[] = [];
for (const host of srvTargetHosts) {
if (isValidEndpoint(host, this.#validDomain)) {
Expand All @@ -182,8 +181,9 @@ export class ConfigurationClientManager {
const results: string[] = [];

try {
const resolver = new this.#dns.Resolver({timeout: DNS_RESOLVER_TIMEOUT, tries: DNS_RESOLVER_TRIES});
// Look up SRV records for the origin host
const originRecords = await this.#dns.resolveSrv(`${TCP_ORIGIN_KEY_NAME}.${host}`);
const originRecords = await resolver.resolveSrv(`${TCP_ORIGIN_KEY_NAME}.${host}`);
if (originRecords.length === 0) {
return results;
}
Expand All @@ -194,10 +194,9 @@ export class ConfigurationClientManager {

// Look up SRV records for alternate hosts
let index = 0;
// eslint-disable-next-line no-constant-condition
while (true) {
while (index < MAX_RESOLVESRV_TIMES) {
const currentAlt = `${ALT_KEY_NAME}${index}`;
const altRecords = await this.#dns.resolveSrv(`${currentAlt}.${TCP_KEY_NAME}.${originHost}`);
const altRecords = await resolver.resolveSrv(`${currentAlt}.${TCP_KEY_NAME}.${originHost}`);
if (altRecords.length === 0) {
break; // No more alternate records, exit loop
}
Expand Down
Loading