-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Monitoring
: add service URL manager (#3134)
* Support es6 build * Refactor: update events make the error optional and support log with color * - Refactor - sendGetRequest to sendRequest and use fetch instead of axios. - replace serviceUrl and serviceName with getters - add update method that uses URL setter - Make all IServiceBase classes take an optional options on their contractor, add error handling for side effect - Grouped all RMB properties to RMB to RMBProps - Feat: - add stats monitor class that monitors stats service - add activation monitor class that monitor activation service * Feat: Add serviceURLManager it is class managing service URLs with liveness checking <pick the first reachable endpoint for each service> - Define retries and silent mode settings - Implement constructor to handle StackManagerOptions - Add private handleErrorsOnSilentMode method for error handling based on silent mode - Implement getAvailableStack method to find reachable service URL - Implement getAvailableServicesStack method to fetch and store available service URLs for all services * Revert: playground/config.js * Refactor: remove sesstion from RMBOptions it will be handled internally * Refactor: update service monitor example * Refactor: Rename service url manager options * Refactor: make tfchainMonitor consotractor takes an optional param * Example: add serviceURlManager Example * Fix: remove error on getting Url before intialization and make it return undefined or emptystring remove debug lines * Chore: RMB handle error event * Example: add template type to support silent * Chore: - change naming - remove error on get url and return empty string in case the url is not set yet * Chore: - add errror handling in isAlive, will throw in case the service url is not set * chore: export new services * Chore: make tfchain url optional * chore: change stats url to api/summary * chore: add checks to prevent accessing undefined functions in RMB connect and disconnect * chore: validate rmb connectivity though gridproxy health endpoint * chore: add error handling to isAlive * chore: support timeout, and log errors using events * chore: support timeout * refactor: support increasing timeout * fix: return status object instade of throwing error * refactor: - rename constractor param - use replace instade of split * Refactor: use /health endpoint in tfchain monitor * refactor: remove logs line * feat: isAlive can take new url * Feat: ping url in parallel * Docs: update example * Refactor: retry logic moved to all stacks, to avoid delay * refactor: enahnce logs * docs: update urls in example * Chore: remove disconnect logic * chore: Remove IDisconnectHandler interface * Chore: update monitoring example * chore: Update the service url on success * Refactor: remove update function and replace it with setter * Refactor: add ServiceBase class * chore: predefine the timeout error
- Loading branch information
Showing
20 changed files
with
427 additions
and
161 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import { | ||
GraphQLMonitor, | ||
GridProxyMonitor, | ||
RMBMonitor, | ||
ServiceUrlManager, | ||
TFChainMonitor, | ||
URLManagerOptions, | ||
} from "../src"; | ||
|
||
const gridproxy = ["https://gridproxy.dev.grid.tf/"]; | ||
const rmb = ["https://graphql.dev.grid.tf", "wss://relay.dev.grid.tf", "wss://relay.02.dev.grid.tf"]; | ||
const graphql = ["https://graphql.dev.grid.tf/graphql"]; | ||
const tfChain = ["wss://tfchain.dev.grid.tf/ws"]; | ||
|
||
async function checkStacksAvailability<N extends boolean>(services: URLManagerOptions<N>) { | ||
try { | ||
const pickedUrls = await new ServiceUrlManager(services).getAvailableServicesStack(); | ||
console.log(pickedUrls); | ||
process.exit(0); | ||
} catch (err) { | ||
console.log(err); | ||
} | ||
} | ||
|
||
checkStacksAvailability({ | ||
retries: 3, | ||
silent: true, | ||
services: [ | ||
{ service: new GridProxyMonitor(), URLs: gridproxy }, | ||
{ service: new GraphQLMonitor(), URLs: graphql }, | ||
{ | ||
service: new RMBMonitor(), | ||
URLs: rmb, | ||
}, | ||
{ service: new TFChainMonitor(), URLs: tfChain }, | ||
], | ||
timeout: 2, | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,2 @@ | ||
export * from "./serviceMonitor/index"; | ||
export * from "./types"; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import { resolveServiceStatus, sendRequest } from "../helpers/utils"; | ||
import { ILivenessChecker, ServiceStatus } from "../types"; | ||
import { ServiceBase } from "./serviceBase"; | ||
|
||
export class ActivationMonitor extends ServiceBase implements ILivenessChecker { | ||
constructor(ServiceUrl?: string) { | ||
super("Activation"); | ||
if (ServiceUrl) this.url = ServiceUrl; | ||
} | ||
async isAlive(url = this.url): Promise<ServiceStatus> { | ||
if (!url) throw new Error("Can't access before initialization"); | ||
return resolveServiceStatus(sendRequest(url, { method: "Get" })); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,20 +1,22 @@ | ||
import { resolveServiceStatus, sendGetRequest } from "../helpers/utils"; | ||
import { resolveServiceStatus, sendRequest } from "../helpers/utils"; | ||
import { ILivenessChecker, ServiceStatus } from "../types"; | ||
import { ServiceBase } from "./serviceBase"; | ||
|
||
export class GraphQLMonitor implements ILivenessChecker { | ||
private readonly name = "GraphQl"; | ||
private readonly url: string; | ||
constructor(graphQlUrl: string) { | ||
this.url = graphQlUrl; | ||
export class GraphQLMonitor extends ServiceBase implements ILivenessChecker { | ||
constructor(ServiceUrl?: string) { | ||
super("GraphQl"); | ||
if (ServiceUrl) this.url = ServiceUrl; | ||
} | ||
serviceName() { | ||
return this.name; | ||
} | ||
serviceUrl() { | ||
return this.url; | ||
} | ||
|
||
async isAlive(): Promise<ServiceStatus> { | ||
return resolveServiceStatus(sendGetRequest(this.url)); | ||
async isAlive(url = this.url): Promise<ServiceStatus> { | ||
if (!url) throw new Error("Can't access before initialization"); | ||
return resolveServiceStatus( | ||
sendRequest(url, { | ||
method: "POST", | ||
headers: { "content-type": "application/json" }, | ||
body: JSON.stringify({ | ||
query: "query monitoring{__typename}", | ||
}), | ||
}), | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,19 +1,14 @@ | ||
import { resolveServiceStatus, sendGetRequest } from "../helpers/utils"; | ||
import { resolveServiceStatus, sendRequest } from "../helpers/utils"; | ||
import { ILivenessChecker, ServiceStatus } from "../types"; | ||
import { ServiceBase } from "./serviceBase"; | ||
|
||
export class GridProxyMonitor implements ILivenessChecker { | ||
private readonly name = "GridProxy"; | ||
private url: string; | ||
constructor(gridProxyUrl: string) { | ||
this.url = gridProxyUrl; | ||
} | ||
serviceName() { | ||
return this.name; | ||
} | ||
serviceUrl() { | ||
return this.url; | ||
} | ||
async isAlive(): Promise<ServiceStatus> { | ||
return resolveServiceStatus(sendGetRequest(this.url)); | ||
export class GridProxyMonitor extends ServiceBase implements ILivenessChecker { | ||
constructor(ServiceUrl?: string) { | ||
super("GridProxy"); | ||
if (ServiceUrl) this.url = ServiceUrl; | ||
} | ||
async isAlive(url = this.url): Promise<ServiceStatus> { | ||
if (!url) throw new Error("Can't access before initialization"); | ||
return resolveServiceStatus(sendRequest(url, { method: "Get" })); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,31 +1,31 @@ | ||
import { KeypairType } from "@polkadot/util-crypto/types"; | ||
import { Client as RMBClient } from "@threefold/rmb_direct_client"; | ||
import { RequestError } from "@threefold/types"; | ||
|
||
import { generateString, resolveServiceStatus } from "../helpers/utils"; | ||
import { IDisconnectHandler, ILivenessChecker, ServiceStatus } from "../types"; | ||
|
||
export class RMBMonitor implements ILivenessChecker, IDisconnectHandler { | ||
private name = "RMB"; | ||
private url: string; | ||
private rmbClient: RMBClient; | ||
constructor(relayUrl: string, chainUrl: string, mnemonic: string, keypairType: KeypairType) { | ||
this.url = relayUrl; | ||
this.rmbClient = new RMBClient(chainUrl, relayUrl, mnemonic, generateString(10), keypairType, 0); | ||
} | ||
private async setUp() { | ||
await this.rmbClient.connect(); | ||
} | ||
public serviceName() { | ||
return this.name; | ||
} | ||
public serviceUrl() { | ||
return this.url; | ||
} | ||
public async isAlive(): Promise<ServiceStatus> { | ||
if (!this.rmbClient?.con?.OPEN) await this.setUp(); | ||
return resolveServiceStatus(this.rmbClient.ping(2)); | ||
import { ILivenessChecker, ServiceStatus } from "../types"; | ||
import { ServiceBase } from "./serviceBase"; | ||
export class RMBMonitor extends ServiceBase implements ILivenessChecker { | ||
constructor(ServiceUrl?: string) { | ||
super("RMB"); | ||
if (ServiceUrl) this.url = ServiceUrl; | ||
} | ||
public async disconnect() { | ||
await this.rmbClient.disconnect(); | ||
async isAlive(url = this.url): Promise<ServiceStatus> { | ||
if (!url) throw new Error("Can't access before initialization"); | ||
const proxyUrl = url.replace("wss://relay", "https://gridproxy"); | ||
try { | ||
const res = await fetch(proxyUrl + "/health"); | ||
if (!res?.ok) throw Error(`HTTP Response Code: ${res?.status}`); | ||
const rmb_conn = (await res.json())?.rmb_conn; | ||
if (rmb_conn === "ok") { | ||
return { | ||
alive: true, | ||
}; | ||
} else { | ||
return { | ||
alive: false, | ||
error: new Error(`rmb_conn is ${rmb_conn}`), | ||
}; | ||
} | ||
} catch (e) { | ||
throw new RequestError(`HTTP request failed due to ${e}.`); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import { IServiceBase } from "../types"; | ||
|
||
export class ServiceBase implements IServiceBase { | ||
private _url?: string; | ||
constructor(private readonly _name: string) {} | ||
public get name() { | ||
return this._name; | ||
} | ||
public get url() { | ||
return this._url ?? ""; | ||
} | ||
public set url(url: string) { | ||
this._url = url; | ||
} | ||
} |
Oops, something went wrong.