Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve https and tee clusters helpers #191

Closed
wants to merge 1 commit into from
Closed
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
3 changes: 2 additions & 1 deletion src/helpers/http.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ import axios, { AxiosInstance } from "axios"
export class HttpClient {
client: AxiosInstance

constructor(baseURL: string) {
constructor(baseURL: string, timeout?: number) {
this.client = axios.create({
baseURL,
...(timeout && { timeout })
})
}

Expand Down
41 changes: 21 additions & 20 deletions src/helpers/tee.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import {
TeeReconciliationType,
NFTListType,
} from "./types"
import { ensureHttps, removeURLSlash, retryPost } from "./utils"
import { ensureHttps, removeURLSlash, retryPost, timeoutTrigger } from "./utils"

import { getClusterData, getEnclaveData, getNextClusterIdAvailable } from "../tee"
import { Errors, chainQuery, txPallets } from "../constants"
Expand Down Expand Up @@ -92,11 +92,11 @@ export const combineKeyShares = (shares: string[]): string => {
* @param clusterId The TEE Cluster id.
* @returns An array of JSONs containing each enclave information (status, date, description, addresses)
*/
export const getEnclaveHealthStatus = async (clusterId = 0) => {
export const getEnclaveHealthStatus = async (clusterId = 0, timeout = 10000) => {
const teeEnclaves = await getTeeEnclavesBaseUrl(clusterId)
const clusterHealthCheck = await Promise.all(
teeEnclaves.map(async (enclaveUrl, idx) => {
const http = new HttpClient(ensureHttps(enclaveUrl))
const http = new HttpClient(ensureHttps(enclaveUrl), timeout)
const enclaveData: EnclaveHealthType = await http.getRaw(TEE_HEALTH_ENDPOINT)
const isError = enclaveData.status !== 200
if (isError || !enclaveData.sync_state.length || enclaveData.sync_state == "setup")
Expand Down Expand Up @@ -142,12 +142,12 @@ export const populateEnclavesData = async (clusterId = 0) => {
* @param clusterId The TEE Cluster id.
* @returns An array of JSONs containing each enclave data populated with its health information.
*/
export const getEnclaveDataAndHealth = async (clusterId = 0): Promise<EnclaveDataAndHealthType[]> => {
export const getEnclaveDataAndHealth = async (clusterId = 0, timeout = 10000): Promise<EnclaveDataAndHealthType[]> => {
const teeEnclaves = await populateEnclavesData(clusterId)
const enclaveData:EnclaveDataAndHealthType[] = await Promise.all(
const enclaveData: EnclaveDataAndHealthType[] = await Promise.all(
teeEnclaves.map(async (e, idx) => {
try {
const http = new HttpClient(ensureHttps(e.enclaveUrl))
const http = new HttpClient(ensureHttps(e.enclaveUrl), timeout)
const enclaveHealthData: EnclaveHealthType = await http.getRaw(TEE_HEALTH_ENDPOINT)
const { block_number, sync_state, version, description, status } = enclaveHealthData
return { ...e, status, blockNumber: block_number, syncState: sync_state, description, version }
Expand Down Expand Up @@ -218,27 +218,28 @@ export const getPublicsClusters = async () => {

/**
* @name getFirstPublicClusterAvailable
* @summary Provides the id of the first available public cluster.
* @summary Provides the id of the first available healthy public cluster.
* @returns A clusterId as a number.
*/
export const getFirstPublicClusterAvailable = async () => {
const nextClusterId = await getNextClusterIdAvailable()
for (let i = 0; i < nextClusterId; i++) {
export const getFirstPublicClusterAvailable = async (timeout = 10000) => {
const publicClusters = await getPublicsClusters()
if (publicClusters.length === 0) return undefined;

for (const cluster of publicClusters) {
try {
const data = await query(txPallets.tee, chainQuery.clusterData, [i])
const result = data.toJSON() as ClusterDataType
if (result) {
const { enclaves, clusterType } = result
// CHECK PUBLIC CLUSTER WITH THE 5 ENCLAVES WORKING
if (enclaves.length === ENCLAVES_IN_CLUSTER && clusterType === "Public") {
return i
}
const healthData = await timeoutTrigger<EnclaveDataAndHealthType[]>(() =>
getEnclaveDataAndHealth(cluster, timeout),
timeout + 1000
)
const filteredData = healthData.filter((c) => c.status === 200)
if (filteredData.length === ENCLAVES_IN_CLUSTER) {
return cluster
}
} catch (error) {
// DO NOT THROW AN ERROR - WE WANT TO PROVIDE THE NEXT ID.
// console.log(`CLUSTER_${i}_UNAVAILABLE - ${error instanceof Error ? error.message : JSON.stringify(error)}`)
// DO NOT THROW AN ERROR - CONTINUE TO THE NEXT CLUSTER.
}
}
return undefined
}

/**
Expand Down
18 changes: 18 additions & 0 deletions src/helpers/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,3 +70,21 @@ export const ensureHttps = (url: string) => {
else if (url.indexOf("http://") === 0) return url.replace("http://", "https://")
else return "https://" + url
}

export const timeoutTrigger = <T>(fn: () => Promise<T>, duration = 10000): Promise<T> => {
return new Promise((resolve, reject) => {
const timer = setTimeout(() => {
reject(new Error('Error: Function timed out'));
}, duration);

try {
const data = fn();
clearTimeout(timer);
resolve(data);
} catch (error) {
clearTimeout(timer);
reject(error);
}
});
}

Loading