Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,14 @@ describe('discoveryNodeSelector', () => {
const selected = await selector.getSelectedEndpoint()
expect(selected).toBe(BEHIND_BLOCKDIFF_NODE)
expect(selector.isBehind).toBe(true)

// Update config and trigger reselection
selector.updateConfig({
allowlist: new Set([HEALTHY_NODE])
})
const selected2 = await selector.getSelectedEndpoint()
expect(selected2).toBe(HEALTHY_NODE)
expect(selector.isBehind).toBe(false)
})

test('respects blocklist', async () => {
Expand All @@ -248,6 +256,14 @@ describe('discoveryNodeSelector', () => {
const selected = await selector.getSelectedEndpoint()
expect(selected).toBe(BEHIND_BLOCKDIFF_NODE)
expect(selector.isBehind).toBe(true)

// Update config and trigger reselection
selector.updateConfig({
blocklist: new Set([BEHIND_BLOCKDIFF_NODE])
})
const selected2 = await selector.getSelectedEndpoint()
expect(selected2).toBe(HEALTHY_NODE)
expect(selector.isBehind).toBe(false)
})

test('uses configured default', async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export class DiscoveryNodeSelector implements DiscoveryNodeSelectorService {
/**
* Configuration passed in by consumer (with defaults)
*/
private readonly config: DiscoveryNodeSelectorServiceConfigInternal
private config: DiscoveryNodeSelectorServiceConfigInternal

/**
* Whether or not we are using a backup, meaning we were
Expand Down Expand Up @@ -113,6 +113,8 @@ export class DiscoveryNodeSelector implements DiscoveryNodeSelectorService {
this.backupServices = {}
this.selectedNode =
this.config.initialSelectedNode &&
(!this.config.allowlist ||
this.config.allowlist?.has(this.config.initialSelectedNode)) &&
!this.config.blocklist?.has(this.config.initialSelectedNode)
? this.config.initialSelectedNode
: null
Expand All @@ -129,6 +131,30 @@ export class DiscoveryNodeSelector implements DiscoveryNodeSelectorService {
)
}

/**
* Updates the config.
* Note that setting the initial node or bootstrap nodes here does nothing as the service is already initialized.
* Will force reselections if health check thresholds change (as that might cause the current node to be considered unhealthy)
* or if the selected node is excluded per allow/blocklists
*/
public updateConfig(
config: Exclude<
DiscoveryNodeSelectorServiceConfig,
'initialSelectedNode' | 'bootstrapServices'
>
) {
this.config = mergeConfigWithDefaults(config, this.config)
if (this.selectedNode) {
if (config.healthCheckThresholds) {
this.selectedNode = null
} else if (config.allowlist && !config.allowlist.has(this.selectedNode)) {
this.selectedNode = null
} else if (config.blocklist?.has(this.selectedNode)) {
this.selectedNode = null
}
}
}

/**
* Returns a middleware that reselects if the current discovery node is behind
* @returns the middleware
Expand Down Expand Up @@ -328,6 +354,7 @@ export class DiscoveryNodeSelector implements DiscoveryNodeSelectorService {
this.info(`Selected discprov ${selectedService}`, decisionTree, {
attemptedServicesCount
})
this.isBehind = false
return selectedService
}

Expand Down
1 change: 0 additions & 1 deletion libs/src/sdk/services/DiscoveryNodeSelector/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ export const defaultDiscoveryNodeSelectorConfig: DiscoveryNodeSelectorServiceCon
requestTimeout: 30000, // 30s
unhealthyTTL: 3600000, // 1 hour
backupsTTL: 120000, // 2 min
cacheTTL: 600000, // 10 min
healthCheckThresholds: {
minVersion: bootstrap.version,
maxSlotDiffPlays: null,
Expand Down
6 changes: 0 additions & 6 deletions libs/src/sdk/services/DiscoveryNodeSelector/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,6 @@ export type DiscoveryNodeSelectorServiceConfigInternal = {
* tried again (re-requested)
*/
backupsTTL: number
/**
* How long the cache should live for selected nodes, in ms.
* If unset, never expires.
* @default 600000 ten minutes
*/
cacheTTL: number | null
/**
* Configuration for determining healthy status
*/
Expand Down
2 changes: 2 additions & 0 deletions libs/src/sdk/utils/deepPartial.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
// Adjusted from Terry: https://stackoverflow.com/questions/61132262/typescript-deep-partial
export type DeepPartial<T> = T extends any[]
? T
: T extends Set<any>
? T
: T extends object
? {
Expand Down