Skip to content

Commit

Permalink
added ability to set a timeout for node-fetch to prevent system halt …
Browse files Browse the repository at this point in the history
…when node is inaccessible
  • Loading branch information
daviddayag committed Jan 26, 2023
1 parent a45445c commit 97ffe41
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 20 deletions.
37 changes: 33 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
"@orbs-network/orbs-ethereum-contracts-v2": "0.0.38",
"lodash": "^4.17.15",
"node-fetch": "^2.6.0",
"abort-controller": "^3.0.0",
"orbs-client-sdk": "^2.3.1",
"orbs-signer-client": "^1.1.0",
"ts-json-decode": "^0.5.1",
Expand Down
6 changes: 3 additions & 3 deletions src/read/guardians-reputations.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as Logger from '../logger';
import {Reputations, State} from '../model/state';
import {getCurrentClockTime} from '../helpers';
import {fetchManagementStatus, ManagementStatusResponse} from "./management";
import {fetchManagementStatusWithTimeout, ManagementStatusResponse} from "./management";

const GUARDIAN_FALLBACK_PORT = "18888";

Expand Down Expand Up @@ -122,7 +122,7 @@ async function fetchMnmgnmtSrvStatusForGuardian(ethAddress: string, config: Repu

try {

response = await fetchManagementStatus(
response = await fetchManagementStatusWithTimeout(
managementServiceEndpoint
);

Expand All @@ -134,7 +134,7 @@ async function fetchMnmgnmtSrvStatusForGuardian(ethAddress: string, config: Repu

managementServiceEndpoint = config.ManagementServiceEndpointSchema.replace(/{{GUARDIAN_IP}}/g, guardian?.Ip + ":" + GUARDIAN_FALLBACK_PORT);

response = await fetchManagementStatus(
response = await fetchManagementStatusWithTimeout(
managementServiceEndpoint
);

Expand Down
72 changes: 59 additions & 13 deletions src/read/management.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,24 @@
import _ from 'lodash';
import * as Logger from '../logger';
import { State } from '../model/state';
import {State} from '../model/state';
import fetch from 'node-fetch';
import { Decoder, decodeString, num, object, record, bool, str, array, maybe } from 'ts-json-decode';
import { getCurrentClockTime } from '../helpers';
import { findEthFromOrbsAddress } from '../model/helpers';
import { getAbiByContractRegistryKey } from '@orbs-network/orbs-ethereum-contracts-v2';
import {array, bool, Decoder, decodeString, maybe, num, object, record, str} from 'ts-json-decode';
import {getCurrentClockTime} from '../helpers';
import {findEthFromOrbsAddress} from '../model/helpers';
import {getAbiByContractRegistryKey} from '@orbs-network/orbs-ethereum-contracts-v2';
import AbortController from "abort-controller";

// update guardianRegistration contract instance and address
export function updateGuardianRegistrationContract(state: State, address:string){
Logger.log(`updateGuardianRegistrationContract: ${address} `);

if(!address) {
Logger.error('guardianRegistrationAddress is not valid')
return
return
}
// addigment
state.guardianRegistrationAddress = address;

const regAbi = getAbiByContractRegistryKey('guardiansRegistration');
if(!regAbi) {
Logger.error(`failed to create regApi`);
Expand All @@ -27,9 +28,9 @@ export function updateGuardianRegistrationContract(state: State, address:string)
Logger.error(`web3 is not initialized`);
return;
}

state.guardianRegistration = new state.web3.eth.Contract(regAbi, state.guardianRegistrationAddress);
if(!state.guardianRegistration)
if(!state.guardianRegistration)
Logger.error(`failed to create state.guardianRegistration web3 instance`);
}
export async function readManagementStatus(endpoint: string, myOrbsAddress: string, state: State) {
Expand All @@ -44,10 +45,10 @@ export async function readManagementStatus(endpoint: string, myOrbsAddress: stri
state.ManagementCurrentTopology = response.Payload.CurrentTopology;
state.ManagementEthToOrbsAddress = _.mapValues(response.Payload.Guardians, (node) => node.OrbsAddress);

if(state.guardianRegistrationAddress !== response.Payload.CurrentContractAddress.guardiansRegistration){
if(state.guardianRegistrationAddress !== response.Payload.CurrentContractAddress.guardiansRegistration){
updateGuardianRegistrationContract(state, response.Payload.CurrentContractAddress.guardiansRegistration);
}

if(!state.myEthGuardianAddress)
state.myEthGuardianAddress = findEthFromOrbsAddress(myOrbsAddress, state);

Expand Down Expand Up @@ -77,6 +78,51 @@ export async function fetchManagementStatus(url: string): Promise<ManagementStat
}
}

/**
* fetch management status with a timeout (used to fetch from other nodes with ability to prevent system halt)
*
* @param url
* @param timeout
*/
export async function fetchManagementStatusWithTimeout(url: string, timeout = 5000) {

let res = null;
let body = null;

const controller = new AbortController();

const timeoutId = setTimeout(() => controller.abort(), timeout);

try {


Logger.log(`** fetching management service status from ${url}`)

res = await fetch(url, {
signal: controller.signal,
});

clearTimeout(timeoutId);

Logger.log(`** DONE fetching management service status from ${url}`)

body = await res.text();

return decodeString(managementStatusResponseDecoder, body);

} catch (err) {

Logger.error(err.message);
throw new Error(`Error fetching Management status from ${url}, response: ${res}, body: ${body}`);

} finally {

clearTimeout(timeoutId);

}

}

export interface ManagementStatusResponse {
Payload: {
CurrentRefTime: number;
Expand Down Expand Up @@ -124,7 +170,7 @@ const managementStatusResponseDecoder: Decoder<ManagementStatusResponse> = objec
CurrentContractAddress: object({
guardiansRegistration: str,
}),

Guardians: record(
object({
OrbsAddress: str,
Expand All @@ -143,5 +189,5 @@ const managementStatusResponseDecoder: Decoder<ManagementStatusResponse> = objec

export async function isGuardianRegistered(state: State): Promise<boolean> {
if (!state.myEthGuardianAddress) return false; // if myEthGuardianAddress is empty it means the node is not registered (not present in matic reader)
return await state.guardianRegistration?.methods.isRegistered(state.myEthGuardianAddress).call();
return await state.guardianRegistration?.methods.isRegistered(state.myEthGuardianAddress).call();
}

0 comments on commit 97ffe41

Please sign in to comment.