Skip to content

Commit 9dee7a7

Browse files
committed
refactor: implement critical code standard improvements
High-priority fixes implemented: 1. Type Safety (network-cache.ts): - Replace non-null assertions with safe validation - Add validateCachedData helper with proper type checking - Use nullish coalescing (??) instead of logical OR - Add proper resource cleanup with dispose() method 2. Error Handling (graphql-dataloader.ts): - Add specific DataLoaderError and BatchLoadError types - Provide detailed error context with operation and request count - Improve error logging with structured information - Replace generic error throwing with contextual errors 3. Function Complexity (performance-config.ts): - Extract PERFORMANCE_DEFAULTS constants with numeric separators - Break down 100+ line function into focused helper functions - Add utility functions for consistent env var parsing - Organize settings by category (concurrency, cache, network, etc.) 4. Resource Cleanup: - Add dispose() methods with proper interval cleanup - Track NodeJS.Timeout references for proper cleanup - Clear callbacks and maps in dispose methods 5. Modern ES2020+ Features: - Use numeric separators (30_000) for better readability - Add 'as const' for immutable configuration objects - Specify radix parameter in parseInt calls - Consistent use of nullish coalescing operator These improvements enhance type safety, debugging capability, maintainability, and follow modern TypeScript best practices.
1 parent c4fce5c commit 9dee7a7

File tree

5 files changed

+223
-140
lines changed

5 files changed

+223
-140
lines changed

packages/indexer-agent/src/agent-optimized.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,19 +45,19 @@ import { AgentConfigs, NetworkAndOperator } from './types'
4545
// Configuration constants for performance tuning
4646
const PERFORMANCE_CONFIG = {
4747
ALLOCATION_CONCURRENCY: process.env.ALLOCATION_CONCURRENCY
48-
? parseInt(process.env.ALLOCATION_CONCURRENCY)
48+
? parseInt(process.env.ALLOCATION_CONCURRENCY, 10)
4949
: 20,
5050
DEPLOYMENT_CONCURRENCY: process.env.DEPLOYMENT_CONCURRENCY
51-
? parseInt(process.env.DEPLOYMENT_CONCURRENCY)
51+
? parseInt(process.env.DEPLOYMENT_CONCURRENCY, 10)
5252
: 15,
53-
BATCH_SIZE: process.env.BATCH_SIZE ? parseInt(process.env.BATCH_SIZE) : 10,
54-
CACHE_TTL: process.env.CACHE_TTL ? parseInt(process.env.CACHE_TTL) : 30000,
53+
BATCH_SIZE: process.env.BATCH_SIZE ? parseInt(process.env.BATCH_SIZE, 10) : 10,
54+
CACHE_TTL: process.env.CACHE_TTL ? parseInt(process.env.CACHE_TTL, 10) : 30_000,
5555
ENABLE_CIRCUIT_BREAKER: process.env.ENABLE_CIRCUIT_BREAKER !== 'false',
5656
ENABLE_PRIORITY_QUEUE: process.env.ENABLE_PRIORITY_QUEUE !== 'false',
5757
ENABLE_CACHE: process.env.ENABLE_CACHE !== 'false',
5858
NETWORK_QUERY_BATCH_SIZE: 50,
5959
PARALLEL_NETWORK_QUERIES: true,
60-
}
60+
} as const
6161

6262
type ActionReconciliationContext = [AllocationDecision[], number, number]
6363

packages/indexer-agent/src/performance-config.ts

Lines changed: 128 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,50 @@
55

66
import { cpus, totalmem } from 'os'
77

8+
// Constants for performance configuration
9+
const PERFORMANCE_DEFAULTS = {
10+
ALLOCATION_CONCURRENCY: 20,
11+
DEPLOYMENT_CONCURRENCY: 15,
12+
NETWORK_QUERY_CONCURRENCY: 10,
13+
BATCH_SIZE: 10,
14+
CACHE_TTL: 30_000, // 30 seconds
15+
CACHE_MAX_SIZE: 2000,
16+
CACHE_CLEANUP_INTERVAL: 60_000, // 1 minute
17+
CIRCUIT_BREAKER_FAILURE_THRESHOLD: 5,
18+
CIRCUIT_BREAKER_RESET_TIMEOUT: 60_000, // 1 minute
19+
PRIORITY_QUEUE_SIGNAL_THRESHOLD: '1000000000000000000000', // 1000 GRT
20+
PRIORITY_QUEUE_STAKE_THRESHOLD: '10000000000000000000000', // 10000 GRT
21+
NETWORK_QUERY_BATCH_SIZE: 50,
22+
NETWORK_QUERY_TIMEOUT: 30_000, // 30 seconds
23+
MAX_RETRY_ATTEMPTS: 3,
24+
RETRY_DELAY: 1000, // 1 second
25+
RETRY_BACKOFF_MULTIPLIER: 2,
26+
METRICS_INTERVAL: 60_000, // 1 minute
27+
} as const
28+
29+
/**
30+
* Utility function for parsing environment variables
31+
*/
32+
function parseEnvInt(key: string, defaultValue: number): number {
33+
const value = process.env[key]
34+
return value ? parseInt(value, 10) : defaultValue
35+
}
36+
37+
function parseEnvFloat(key: string, defaultValue: number): number {
38+
const value = process.env[key]
39+
return value ? parseFloat(value) : defaultValue
40+
}
41+
42+
function parseEnvBoolean(key: string, defaultValue: boolean): boolean {
43+
const value = process.env[key]
44+
if (value === undefined) return defaultValue
45+
return value !== 'false'
46+
}
47+
48+
function parseEnvString(key: string, defaultValue: string): string {
49+
return process.env[key] ?? defaultValue
50+
}
51+
852
export interface PerformanceConfig {
953
// Concurrency settings
1054
allocationConcurrency: number
@@ -47,152 +91,121 @@ export interface PerformanceConfig {
4791

4892
export const DEFAULT_PERFORMANCE_CONFIG: PerformanceConfig = {
4993
// Concurrency settings
50-
allocationConcurrency: 20,
51-
deploymentConcurrency: 15,
52-
networkQueryConcurrency: 10,
53-
batchSize: 10,
94+
allocationConcurrency: PERFORMANCE_DEFAULTS.ALLOCATION_CONCURRENCY,
95+
deploymentConcurrency: PERFORMANCE_DEFAULTS.DEPLOYMENT_CONCURRENCY,
96+
networkQueryConcurrency: PERFORMANCE_DEFAULTS.NETWORK_QUERY_CONCURRENCY,
97+
batchSize: PERFORMANCE_DEFAULTS.BATCH_SIZE,
5498

5599
// Cache settings
56100
enableCache: true,
57-
cacheTTL: 30000, // 30 seconds
58-
cacheMaxSize: 2000,
59-
cacheCleanupInterval: 60000, // 1 minute
101+
cacheTTL: PERFORMANCE_DEFAULTS.CACHE_TTL,
102+
cacheMaxSize: PERFORMANCE_DEFAULTS.CACHE_MAX_SIZE,
103+
cacheCleanupInterval: PERFORMANCE_DEFAULTS.CACHE_CLEANUP_INTERVAL,
60104

61105
// Circuit breaker settings
62106
enableCircuitBreaker: true,
63-
circuitBreakerFailureThreshold: 5,
64-
circuitBreakerResetTimeout: 60000, // 1 minute
107+
circuitBreakerFailureThreshold: PERFORMANCE_DEFAULTS.CIRCUIT_BREAKER_FAILURE_THRESHOLD,
108+
circuitBreakerResetTimeout: PERFORMANCE_DEFAULTS.CIRCUIT_BREAKER_RESET_TIMEOUT,
65109
circuitBreakerHalfOpenMaxAttempts: 3,
66110

67111
// Priority queue settings
68112
enablePriorityQueue: true,
69-
priorityQueueSignalThreshold: '1000000000000000000000', // 1000 GRT
70-
priorityQueueStakeThreshold: '10000000000000000000000', // 10000 GRT
113+
priorityQueueSignalThreshold: PERFORMANCE_DEFAULTS.PRIORITY_QUEUE_SIGNAL_THRESHOLD,
114+
priorityQueueStakeThreshold: PERFORMANCE_DEFAULTS.PRIORITY_QUEUE_STAKE_THRESHOLD,
71115

72116
// Network settings
73117
enableParallelNetworkQueries: true,
74-
networkQueryBatchSize: 50,
75-
networkQueryTimeout: 30000, // 30 seconds
118+
networkQueryBatchSize: PERFORMANCE_DEFAULTS.NETWORK_QUERY_BATCH_SIZE,
119+
networkQueryTimeout: PERFORMANCE_DEFAULTS.NETWORK_QUERY_TIMEOUT,
76120

77121
// Retry settings
78-
maxRetryAttempts: 3,
79-
retryDelay: 1000, // 1 second
80-
retryBackoffMultiplier: 2,
122+
maxRetryAttempts: PERFORMANCE_DEFAULTS.MAX_RETRY_ATTEMPTS,
123+
retryDelay: PERFORMANCE_DEFAULTS.RETRY_DELAY,
124+
retryBackoffMultiplier: PERFORMANCE_DEFAULTS.RETRY_BACKOFF_MULTIPLIER,
81125

82126
// Monitoring settings
83127
enableMetrics: true,
84-
metricsInterval: 60000, // 1 minute
128+
metricsInterval: PERFORMANCE_DEFAULTS.METRICS_INTERVAL,
85129
enableDetailedLogging: false,
86130
}
87131

88132
/**
89-
* Load performance configuration from environment variables
133+
* Apply concurrency-related environment variable overrides
90134
*/
91-
export function loadPerformanceConfig(): PerformanceConfig {
92-
const config = { ...DEFAULT_PERFORMANCE_CONFIG }
93-
94-
// Override with environment variables if present
95-
if (process.env.ALLOCATION_CONCURRENCY) {
96-
config.allocationConcurrency = parseInt(process.env.ALLOCATION_CONCURRENCY)
97-
}
98-
99-
if (process.env.DEPLOYMENT_CONCURRENCY) {
100-
config.deploymentConcurrency = parseInt(process.env.DEPLOYMENT_CONCURRENCY)
101-
}
102-
103-
if (process.env.NETWORK_QUERY_CONCURRENCY) {
104-
config.networkQueryConcurrency = parseInt(
105-
process.env.NETWORK_QUERY_CONCURRENCY,
106-
)
107-
}
108-
109-
if (process.env.BATCH_SIZE) {
110-
config.batchSize = parseInt(process.env.BATCH_SIZE)
111-
}
112-
113-
if (process.env.ENABLE_CACHE !== undefined) {
114-
config.enableCache = process.env.ENABLE_CACHE !== 'false'
115-
}
116-
117-
if (process.env.CACHE_TTL) {
118-
config.cacheTTL = parseInt(process.env.CACHE_TTL)
119-
}
120-
121-
if (process.env.CACHE_MAX_SIZE) {
122-
config.cacheMaxSize = parseInt(process.env.CACHE_MAX_SIZE)
123-
}
124-
125-
if (process.env.ENABLE_CIRCUIT_BREAKER !== undefined) {
126-
config.enableCircuitBreaker = process.env.ENABLE_CIRCUIT_BREAKER !== 'false'
127-
}
128-
129-
if (process.env.CIRCUIT_BREAKER_FAILURE_THRESHOLD) {
130-
config.circuitBreakerFailureThreshold = parseInt(
131-
process.env.CIRCUIT_BREAKER_FAILURE_THRESHOLD,
132-
)
133-
}
134-
135-
if (process.env.CIRCUIT_BREAKER_RESET_TIMEOUT) {
136-
config.circuitBreakerResetTimeout = parseInt(
137-
process.env.CIRCUIT_BREAKER_RESET_TIMEOUT,
138-
)
139-
}
140-
141-
if (process.env.ENABLE_PRIORITY_QUEUE !== undefined) {
142-
config.enablePriorityQueue = process.env.ENABLE_PRIORITY_QUEUE !== 'false'
143-
}
144-
145-
if (process.env.PRIORITY_QUEUE_SIGNAL_THRESHOLD) {
146-
config.priorityQueueSignalThreshold =
147-
process.env.PRIORITY_QUEUE_SIGNAL_THRESHOLD
148-
}
149-
150-
if (process.env.PRIORITY_QUEUE_STAKE_THRESHOLD) {
151-
config.priorityQueueStakeThreshold =
152-
process.env.PRIORITY_QUEUE_STAKE_THRESHOLD
153-
}
154-
155-
if (process.env.ENABLE_PARALLEL_NETWORK_QUERIES !== undefined) {
156-
config.enableParallelNetworkQueries =
157-
process.env.ENABLE_PARALLEL_NETWORK_QUERIES !== 'false'
158-
}
135+
function applyConcurrencySettings(config: PerformanceConfig): void {
136+
config.allocationConcurrency = parseEnvInt('ALLOCATION_CONCURRENCY', config.allocationConcurrency)
137+
config.deploymentConcurrency = parseEnvInt('DEPLOYMENT_CONCURRENCY', config.deploymentConcurrency)
138+
config.networkQueryConcurrency = parseEnvInt('NETWORK_QUERY_CONCURRENCY', config.networkQueryConcurrency)
139+
config.batchSize = parseEnvInt('BATCH_SIZE', config.batchSize)
140+
}
159141

160-
if (process.env.NETWORK_QUERY_BATCH_SIZE) {
161-
config.networkQueryBatchSize = parseInt(
162-
process.env.NETWORK_QUERY_BATCH_SIZE,
163-
)
164-
}
142+
/**
143+
* Apply cache-related environment variable overrides
144+
*/
145+
function applyCacheSettings(config: PerformanceConfig): void {
146+
config.enableCache = parseEnvBoolean('ENABLE_CACHE', config.enableCache)
147+
config.cacheTTL = parseEnvInt('CACHE_TTL', config.cacheTTL)
148+
config.cacheMaxSize = parseEnvInt('CACHE_MAX_SIZE', config.cacheMaxSize)
149+
}
165150

166-
if (process.env.NETWORK_QUERY_TIMEOUT) {
167-
config.networkQueryTimeout = parseInt(process.env.NETWORK_QUERY_TIMEOUT)
168-
}
151+
/**
152+
* Apply circuit breaker environment variable overrides
153+
*/
154+
function applyCircuitBreakerSettings(config: PerformanceConfig): void {
155+
config.enableCircuitBreaker = parseEnvBoolean('ENABLE_CIRCUIT_BREAKER', config.enableCircuitBreaker)
156+
config.circuitBreakerFailureThreshold = parseEnvInt('CIRCUIT_BREAKER_FAILURE_THRESHOLD', config.circuitBreakerFailureThreshold)
157+
config.circuitBreakerResetTimeout = parseEnvInt('CIRCUIT_BREAKER_RESET_TIMEOUT', config.circuitBreakerResetTimeout)
158+
}
169159

170-
if (process.env.MAX_RETRY_ATTEMPTS) {
171-
config.maxRetryAttempts = parseInt(process.env.MAX_RETRY_ATTEMPTS)
172-
}
160+
/**
161+
* Apply priority queue environment variable overrides
162+
*/
163+
function applyPriorityQueueSettings(config: PerformanceConfig): void {
164+
config.enablePriorityQueue = parseEnvBoolean('ENABLE_PRIORITY_QUEUE', config.enablePriorityQueue)
165+
config.priorityQueueSignalThreshold = parseEnvString('PRIORITY_QUEUE_SIGNAL_THRESHOLD', config.priorityQueueSignalThreshold)
166+
config.priorityQueueStakeThreshold = parseEnvString('PRIORITY_QUEUE_STAKE_THRESHOLD', config.priorityQueueStakeThreshold)
167+
}
173168

174-
if (process.env.RETRY_DELAY) {
175-
config.retryDelay = parseInt(process.env.RETRY_DELAY)
176-
}
169+
/**
170+
* Apply network-related environment variable overrides
171+
*/
172+
function applyNetworkSettings(config: PerformanceConfig): void {
173+
config.enableParallelNetworkQueries = parseEnvBoolean('ENABLE_PARALLEL_NETWORK_QUERIES', config.enableParallelNetworkQueries)
174+
config.networkQueryBatchSize = parseEnvInt('NETWORK_QUERY_BATCH_SIZE', config.networkQueryBatchSize)
175+
config.networkQueryTimeout = parseEnvInt('NETWORK_QUERY_TIMEOUT', config.networkQueryTimeout)
176+
}
177177

178-
if (process.env.RETRY_BACKOFF_MULTIPLIER) {
179-
config.retryBackoffMultiplier = parseFloat(
180-
process.env.RETRY_BACKOFF_MULTIPLIER,
181-
)
182-
}
178+
/**
179+
* Apply retry-related environment variable overrides
180+
*/
181+
function applyRetrySettings(config: PerformanceConfig): void {
182+
config.maxRetryAttempts = parseEnvInt('MAX_RETRY_ATTEMPTS', config.maxRetryAttempts)
183+
config.retryDelay = parseEnvInt('RETRY_DELAY', config.retryDelay)
184+
config.retryBackoffMultiplier = parseEnvFloat('RETRY_BACKOFF_MULTIPLIER', config.retryBackoffMultiplier)
185+
}
183186

184-
if (process.env.ENABLE_METRICS !== undefined) {
185-
config.enableMetrics = process.env.ENABLE_METRICS !== 'false'
186-
}
187+
/**
188+
* Apply monitoring-related environment variable overrides
189+
*/
190+
function applyMonitoringSettings(config: PerformanceConfig): void {
191+
config.enableMetrics = parseEnvBoolean('ENABLE_METRICS', config.enableMetrics)
192+
config.metricsInterval = parseEnvInt('METRICS_INTERVAL', config.metricsInterval)
193+
config.enableDetailedLogging = parseEnvBoolean('ENABLE_DETAILED_LOGGING', config.enableDetailedLogging)
194+
}
187195

188-
if (process.env.METRICS_INTERVAL) {
189-
config.metricsInterval = parseInt(process.env.METRICS_INTERVAL)
190-
}
196+
/**
197+
* Load performance configuration from environment variables
198+
*/
199+
export function loadPerformanceConfig(): PerformanceConfig {
200+
const config = { ...DEFAULT_PERFORMANCE_CONFIG }
191201

192-
if (process.env.ENABLE_DETAILED_LOGGING !== undefined) {
193-
config.enableDetailedLogging =
194-
process.env.ENABLE_DETAILED_LOGGING === 'true'
195-
}
202+
applyConcurrencySettings(config)
203+
applyCacheSettings(config)
204+
applyCircuitBreakerSettings(config)
205+
applyPriorityQueueSettings(config)
206+
applyNetworkSettings(config)
207+
applyRetrySettings(config)
208+
applyMonitoringSettings(config)
196209

197210
return config
198211
}

packages/indexer-common/src/performance/circuit-breaker.ts

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,16 +36,17 @@ export class CircuitBreaker {
3636
private readonly monitoringPeriod: number
3737
private logger: Logger
3838
private stateChangeCallbacks: Array<(state: CircuitState) => void> = []
39+
private monitoringInterval?: NodeJS.Timeout
3940

4041
constructor(logger: Logger, options: CircuitBreakerOptions = {}) {
4142
this.logger = logger.child({ component: 'CircuitBreaker' })
42-
this.failureThreshold = options.failureThreshold || 5
43-
this.resetTimeout = options.resetTimeout || 60000 // 1 minute
44-
this.halfOpenMaxAttempts = options.halfOpenMaxAttempts || 3
45-
this.monitoringPeriod = options.monitoringPeriod || 300000 // 5 minutes
43+
this.failureThreshold = options.failureThreshold ?? 5
44+
this.resetTimeout = options.resetTimeout ?? 60_000 // 1 minute
45+
this.halfOpenMaxAttempts = options.halfOpenMaxAttempts ?? 3
46+
this.monitoringPeriod = options.monitoringPeriod ?? 300_000 // 5 minutes
4647

4748
// Periodic stats reset
48-
setInterval(() => this.resetStats(), this.monitoringPeriod)
49+
this.monitoringInterval = setInterval(() => this.resetStats(), this.monitoringPeriod)
4950
}
5051

5152
/**
@@ -264,4 +265,15 @@ export class CircuitBreaker {
264265
)
265266
}) as T
266267
}
268+
269+
/**
270+
* Clean up resources
271+
*/
272+
dispose(): void {
273+
if (this.monitoringInterval) {
274+
clearInterval(this.monitoringInterval)
275+
this.monitoringInterval = undefined
276+
}
277+
this.stateChangeCallbacks = []
278+
}
267279
}

0 commit comments

Comments
 (0)