Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 | 1x 1x 1x 1x 1x 1x 1x | // SPDX-License-Identifier: Apache-2.0
import net from 'net';
import { IService } from './IService';
import { LoggerService } from './LoggerService';
import { ServiceLocator } from './ServiceLocator';
import { CLIService } from './CLIService';
import { Errors } from '../Errors/LocalNodeErrors';
import debounce from '../utils/debounce';
/**
* ConnectionService is a service class that handles network connections.
* It implements the IService interface.
* It uses the 'net' module to create connections and check their status.
*
* @class
* @public
*/
export class ConnectionService implements IService{
/**
* The logger service used for logging.
* @private
*/
private logger: LoggerService;
/**
* The name of the service.
* @private
*/
private serviceName: string;
/**
* The CLI service used for command line interface operations.
* @private
*/
private cliService: CLIService;
// Debounced function to print error message at most once every N seconds
private readonly debouncedErrorLog;
/**
* Constructs a new instance of the ConnectionService.
* Initializes the logger and CLI service, and logs the initialization of the connection service.
*/
constructor() {
this.serviceName = ConnectionService.name;
this.logger = ServiceLocator.Current.get<LoggerService>(LoggerService.name);
this.cliService = ServiceLocator.Current.get<CLIService>(CLIService.name);
this.logger.trace('Connection Service Initialized!', this.serviceName);
this.debouncedErrorLog = debounce((message: string) => {
this.logger.info(message, this.serviceName);
}, 5000);
}
/**
* Waits for the local node to fire up by continuously trying to establish a connection.
* If the connection is not ready after 100 retries, it throws a CONNECTION_ERROR.
*
* @param {number} port - The port to connect to.
* @throws CONNECTION_ERROR if the port is not ready after a certain number of retries.
* @returns {Promise<void>} A promise that resolves when the port is ready for connection.
* @public
*/
public async waitForFiringUp(port: number, serviceName: string): Promise<void> {
const { host } = this.cliService.getCurrentArgv();
let isReady = false;
// this means that we wait around 100 seconds, normal consensus node startup takes around 60 seconds
let retries = parseInt(process.env.FIRING_UP_RETRY_ATTEMPTS ?? '100');
while (!isReady) {
net
.createConnection(port, host)
.on('data', () => {
isReady = true;
})
.on('error', (err: any) => {
if (err.code === 'ECONNREFUSED') {
this.debouncedErrorLog(`${serviceName} not yet available at: ${host}:${port}. Retrying...`);
}
else {
this.logger.error(err.message, this.serviceName);
}
});
retries--;
await new Promise((r) => setTimeout(r, 100));
Iif (retries < 0) {
throw Errors.CONNECTION_ERROR(port);
}
}
}
/**
* Checks the connection to the local node.
* If the connection is not established within a timeout of 3000ms, it rejects the promise with 'timeout'.
* If the connection is established, it resolves the promise and ends the socket.
* If there is an error during the connection, it rejects the promise with the error.
*
* @param {number} port - The port to connect to.
* @public
* @returns {Promise<void>} - A promise that resolves when the connection is established, and rejects when there is an error or timeout.
*/
public checkConnection(port: number): Promise<void> {
const { host } = this.cliService.getCurrentArgv();
return new Promise<void>((resolve, reject) => {
const timeout = 3000;
const timer = setTimeout(() => {
reject('timeout');
socket.end();
}, timeout);
let socket = net.createConnection(port, host, () => {
clearTimeout(timer);
resolve();
socket.end();
});
socket.on('error', (err) => {
clearTimeout(timer);
reject(err);
});
});
}
}
|