@bcoders.gr/virtualpool
Version:
Advanced Ethereum testing framework with provider pooling, load balancing, and comprehensive monitoring
258 lines (196 loc) โข 6.77 kB
Markdown
# @bcoders.gr/virtualpool
Advanced Ethereum testing framework with provider pooling, load balancing, and comprehensive monitoring.
## Features
- ๐ **Provider Pooling**: Manage multiple Anvil instances efficiently
- โ๏ธ **Load Balancing**: Multiple strategies (random, round-robin, least-used, fastest)
- ๐ **Monitoring**: Comprehensive metrics and health checks
- ๐ **Auto-recovery**: Automatic provider restart on failure
- ๐ฏ **Circuit Breaker**: Prevent cascading failures
- ๐งช **Testing Ready**: Built for extensive blockchain testing
## Installation
```bash
npm install @bcoders.gr/virtualpool
```
## Quick Start
```javascript
import AnvilProviderPool from '@bcoders.gr/virtualpool';
// Create a pool with 3 providers on ports 8545-8547
const pool = new AnvilProviderPool(8545, 8547, {
timeout: 30000,
maxRetries: 5,
healthCheckInterval: 30000
});
// Initialize the pool
await pool.initialize();
// Use a provider with automatic management
const blockNumber = await pool.withProvider(async (provider) => {
return await provider.send('eth_blockNumber', []);
});
console.log(`Current block: ${parseInt(blockNumber, 16)}`);
// Shutdown when done
await pool.shutdown();
```
## API Reference
### Constructor
```javascript
new AnvilProviderPool(portStart, portEnd, options)
```
**Parameters:**
- `portStart` (number): Starting port for Anvil instances
- `portEnd` (number): Ending port for Anvil instances
- `options` (object): Configuration options
**Options:**
- `timeout` (number): Provider startup timeout (default: 30000ms)
- `maxRetries` (number): Max retry attempts (default: 5)
- `maxRetriesPerPort` (number): Max retries per port (default: 3)
- `healthCheckInterval` (number): Health check interval (default: 30000ms)
- `anvilPath` (string): Path to anvil binary (default: '/root/.foundry/bin/anvil')
- `maxParallelStarts` (number): Max parallel provider starts (default: 5)
- `waitInterval` (number): Wait interval for provider availability (default: 10ms)
- `gracefulShutdownTimeout` (number): Graceful shutdown timeout (default: 5000ms)
- `logger` (function): Custom logger function
- `providerOptions` (object): Options passed to IPCProvider
### Methods
#### `initialize()`
Initialize all providers in the pool.
```javascript
await pool.initialize();
```
#### `withProvider(fn)`
Execute a function with an automatically managed provider.
```javascript
const result = await pool.withProvider(async (provider) => {
return await provider.send('eth_getBalance', [address, 'latest']);
});
```
#### `withProviderWait(fn, timeoutMs)`
Execute a function with a provider, waiting if none available.
```javascript
const result = await pool.withProviderWait(async (provider) => {
return await provider.send('eth_call', [transaction, 'latest']);
}, 10000);
```
#### `withProviderStrategy(fn, strategy, timeoutMs)`
Execute a function using a specific load balancing strategy.
```javascript
const result = await pool.withProviderStrategy(async (provider) => {
return await provider.send('eth_chainId', []);
}, 'roundRobin');
```
**Strategies:**
- `'random'`: Random provider selection (default)
- `'roundRobin'`: Round-robin selection
- `'leastUsed'`: Select least used provider
- `'fastest'`: Select fastest responding provider
#### `getAvailableProvider()`
Get an available provider manually (for advanced use cases).
```javascript
const providerInfo = pool.getAvailableProvider();
if (providerInfo) {
const { provider, port } = providerInfo;
// Use provider...
pool.releaseProvider(port); // Don't forget to release!
}
```
#### `getStats()`
Get comprehensive pool statistics.
```javascript
const stats = pool.getStats();
console.log(`Available: ${stats.available}/${stats.total}`);
console.log(`Success rate: ${stats.successRate}`);
console.log(`Avg response time: ${stats.averageResponseTime}ms`);
```
#### `shutdown(forceTimeout)`
Gracefully shutdown the pool.
```javascript
await pool.shutdown(10000); // 10 second force timeout
```
## Events
The pool emits various events for monitoring:
```javascript
pool.on('requestCompleted', ({ port, responseTime, success }) => {
console.log(`Request on port ${port}: ${responseTime}ms, success: ${success}`);
});
pool.on('providerFailed', ({ port, error }) => {
console.log(`Provider ${port} failed: ${error}`);
});
pool.on('providerRecovered', ({ port }) => {
console.log(`Provider ${port} recovered`);
});
pool.on('healthCheckCompleted', (stats) => {
console.log(`Health check completed, ${stats.healthy} healthy providers`);
});
```
## Advanced Usage
### Custom Configuration
```javascript
const pool = new AnvilProviderPool(8545, 8549, {
timeout: 60000,
maxRetries: 10,
healthCheckInterval: 60000,
logger: (msg) => console.log(`[POOL] ${msg}`),
providerOptions: {
requestTimeout: 30000,
autoReconnect: true
}
});
```
### Error Handling
```javascript
try {
await pool.initialize();
} catch (error) {
console.error('Failed to initialize pool:', error.message);
// Handle initialization failure
}
try {
const result = await pool.withProvider(async (provider) => {
return await provider.send('eth_getTransactionReceipt', [txHash]);
});
} catch (error) {
console.error('Transaction failed:', error.message);
// Handle request failure
}
```
### Monitoring
```javascript
// Regular stats monitoring
setInterval(() => {
const stats = pool.getStats();
console.log(`Pool utilization: ${stats.utilizationRate}`);
console.log(`Requests/sec: ${stats.requestsPerSecond}`);
}, 10000);
// Event-based monitoring
pool.on('requestCompleted', ({ port, responseTime, success, totalRequests }) => {
if (!success) {
console.warn(`Failed request on port ${port}`);
}
if (totalRequests % 1000 === 0) {
console.log(`Processed ${totalRequests} requests`);
}
});
```
## Testing
The package includes comprehensive tests:
```bash
npm run test:basic # Basic functionality
npm run test:comprehensive # Full test suite
npm run test:getavailable # Provider allocation tests
```
## Requirements
- Node.js >= 16.0.0
- [Foundry](https://getfoundry.sh/) with Anvil installed
- Linux/macOS (Windows support via WSL)
## License
MIT License - see [LICENSE](LICENSE) file for details.
## Contributing
1. Fork the repository
2. Create a feature branch
3. Add tests for new functionality
4. Ensure all tests pass
5. Submit a pull request
## Support
- GitHub Issues: [Report bugs or request features](https://github.com/pagovitsa/virtualpool/issues)
- Documentation: [Full API documentation](https://github.com/pagovitsa/virtualpool/wiki)
---
Built with โค๏ธ by [bcoders.gr](https://bcoders.gr)