From 92d7197879985a3b5e338cb993e1ef99e48055f8 Mon Sep 17 00:00:00 2001 From: Jennifer Echenim Date: Thu, 21 Dec 2023 16:14:40 +0400 Subject: [PATCH 1/5] wip: add an endpoint for health check --- go/obsclient/obsclient.go | 7 +++++-- integration/networktest/env/dev_network.go | 2 +- integration/networktest/util.go | 2 +- integration/simulation/network/socket.go | 2 +- integration/simulation/simulation.go | 2 +- testnet/launcher/docker.go | 2 +- tools/obscuroscan_v2/backend/obscuroscan_backend.go | 4 ++++ .../backend/webserver/webserver_routes_items.go | 11 +++++++++++ 8 files changed, 25 insertions(+), 7 deletions(-) diff --git a/go/obsclient/obsclient.go b/go/obsclient/obsclient.go index b16021f49f..ea1fe127ae 100644 --- a/go/obsclient/obsclient.go +++ b/go/obsclient/obsclient.go @@ -2,6 +2,7 @@ package obsclient import ( "errors" + "fmt" "math/big" "strings" @@ -86,10 +87,12 @@ func (oc *ObsClient) BatchHeaderByHash(hash gethcommon.Hash) (*common.BatchHeade return batchHeader, err } -// Health returns the health of the node. -func (oc *ObsClient) Health() (bool, error) { +// HealthStatusOfNode returns the health of the node. +func (oc *ObsClient) HealthStatusOfNode() (bool, error) { var healthy *hostcommon.HealthCheck err := oc.rpcClient.Call(&healthy, rpc.Health) + // log to test + fmt.Println("HealthStatusOfNode", healthy, err) if err != nil { return false, err } diff --git a/integration/networktest/env/dev_network.go b/integration/networktest/env/dev_network.go index 89281d564d..c97cf19a09 100644 --- a/integration/networktest/env/dev_network.go +++ b/integration/networktest/env/dev_network.go @@ -50,7 +50,7 @@ func awaitHealthStatus(rpcAddress string, timeout time.Duration) error { return fmt.Errorf("failed dial host (%s): %w", rpcAddress, err) } defer c.Close() - healthy, err := c.Health() + healthy, err := c.HealthStatusOfNode() if err != nil { return fmt.Errorf("failed to get host health (%s): %w", rpcAddress, err) } diff --git a/integration/networktest/util.go b/integration/networktest/util.go index 4ec1f924d4..7c37127b46 100644 --- a/integration/networktest/util.go +++ b/integration/networktest/util.go @@ -24,7 +24,7 @@ func NodeHealthCheck(rpcAddress string) error { if err != nil { return err } - health, err := client.Health() + health, err := client.HealthStatusOfNode() if err != nil { return err } diff --git a/integration/simulation/network/socket.go b/integration/simulation/network/socket.go index 874e5c8125..390a782aa5 100644 --- a/integration/simulation/network/socket.go +++ b/integration/simulation/network/socket.go @@ -173,7 +173,7 @@ func (n *networkOfSocketNodes) createConnections(simParams *params.SimParams) er startTime := time.Now() healthy := false for ; !healthy; time.Sleep(500 * time.Millisecond) { - healthy, _ = client.Health() + healthy, _ = client.HealthStatusOfNode() if time.Now().After(startTime.Add(3 * time.Minute)) { return fmt.Errorf("nodes not healthy after 3 minutes") } diff --git a/integration/simulation/simulation.go b/integration/simulation/simulation.go index e8c697afd2..4006f1ad4a 100644 --- a/integration/simulation/simulation.go +++ b/integration/simulation/simulation.go @@ -288,7 +288,7 @@ func (s *Simulation) prefundL1Accounts() { func (s *Simulation) checkHealthStatus() { for _, client := range s.RPCHandles.ObscuroClients { - if healthy, err := client.Health(); !healthy || err != nil { + if healthy, err := client.HealthStatusOfNode(); !healthy || err != nil { panic("Client is not healthy: " + err.Error()) } } diff --git a/testnet/launcher/docker.go b/testnet/launcher/docker.go index ce936a0542..1622b9de6b 100644 --- a/testnet/launcher/docker.go +++ b/testnet/launcher/docker.go @@ -223,7 +223,7 @@ func waitForHealthyNode(port int) error { // todo: hook the cfg defer client.Stop() obsClient := obsclient.NewObsClient(client) - health, err := obsClient.Health() + health, err := obsClient.HealthStatusOfNode() if err != nil { return err } diff --git a/tools/obscuroscan_v2/backend/obscuroscan_backend.go b/tools/obscuroscan_v2/backend/obscuroscan_backend.go index 7c783d10c9..26741b24b2 100644 --- a/tools/obscuroscan_v2/backend/obscuroscan_backend.go +++ b/tools/obscuroscan_v2/backend/obscuroscan_backend.go @@ -30,6 +30,10 @@ func (b *Backend) GetLatestBatch() (*common.BatchHeader, error) { return b.obsClient.BatchHeaderByNumber(nil) } +func (b *Backend) GetHealthStatus() (bool, error) { + return b.obsClient.HealthStatusOfNode() +} + func (b *Backend) GetLatestRollup() (*common.RollupHeader, error) { return &common.RollupHeader{}, nil } diff --git a/tools/obscuroscan_v2/backend/webserver/webserver_routes_items.go b/tools/obscuroscan_v2/backend/webserver/webserver_routes_items.go index 352d435a67..426f211974 100644 --- a/tools/obscuroscan_v2/backend/webserver/webserver_routes_items.go +++ b/tools/obscuroscan_v2/backend/webserver/webserver_routes_items.go @@ -17,6 +17,17 @@ func routeItems(r *gin.Engine, server *WebServer) { r.GET("/items/batches/", server.getBatchListing) r.GET("/items/blocks/", server.getBlockListing) r.GET("/info/obscuro/", server.getConfig) + r.POST("/info/health/", server.getHealthStatus) +} + +func (w *WebServer) getHealthStatus(c *gin.Context) { + healthStatus, err := w.backend.GetHealthStatus() + if err != nil { + errorHandler(c, fmt.Errorf("unable to execute request %w", err), w.logger) + return + } + + c.JSON(http.StatusOK, healthStatus) } func (w *WebServer) getLatestBatch(c *gin.Context) { From 9896ed7d5d9f273df1926ce413ffe7195b52600e Mon Sep 17 00:00:00 2001 From: Jennifer Echenim Date: Fri, 22 Dec 2023 11:56:54 +0400 Subject: [PATCH 2/5] feat: add endpoint for health check --- go/obsclient/obsclient.go | 3 --- .../backend/webserver/webserver_routes_items.go | 6 +----- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/go/obsclient/obsclient.go b/go/obsclient/obsclient.go index ea1fe127ae..dfae081095 100644 --- a/go/obsclient/obsclient.go +++ b/go/obsclient/obsclient.go @@ -2,7 +2,6 @@ package obsclient import ( "errors" - "fmt" "math/big" "strings" @@ -91,8 +90,6 @@ func (oc *ObsClient) BatchHeaderByHash(hash gethcommon.Hash) (*common.BatchHeade func (oc *ObsClient) HealthStatusOfNode() (bool, error) { var healthy *hostcommon.HealthCheck err := oc.rpcClient.Call(&healthy, rpc.Health) - // log to test - fmt.Println("HealthStatusOfNode", healthy, err) if err != nil { return false, err } diff --git a/tools/obscuroscan_v2/backend/webserver/webserver_routes_items.go b/tools/obscuroscan_v2/backend/webserver/webserver_routes_items.go index 426f211974..3086599dd1 100644 --- a/tools/obscuroscan_v2/backend/webserver/webserver_routes_items.go +++ b/tools/obscuroscan_v2/backend/webserver/webserver_routes_items.go @@ -22,12 +22,8 @@ func routeItems(r *gin.Engine, server *WebServer) { func (w *WebServer) getHealthStatus(c *gin.Context) { healthStatus, err := w.backend.GetHealthStatus() - if err != nil { - errorHandler(c, fmt.Errorf("unable to execute request %w", err), w.logger) - return - } - c.JSON(http.StatusOK, healthStatus) + c.JSON(http.StatusOK, gin.H{"result": healthStatus, "errors": fmt.Sprintf("%s", err)}) } func (w *WebServer) getLatestBatch(c *gin.Context) { From e8beeeed2ee67fe5fd6991ce78bcd3cd88fb89e7 Mon Sep 17 00:00:00 2001 From: Jennifer Echenim Date: Fri, 22 Dec 2023 16:17:33 +0400 Subject: [PATCH 3/5] add ui for health check on Tenscan --- tools/obscuroscan_v3/frontend/api/general.ts | 14 +++++++++++ .../src/components/health-indicator.tsx | 24 +++++++++++++++++++ .../src/components/layouts/header.tsx | 2 ++ .../frontend/src/routes/index.ts | 3 +++ .../src/services/useGeneralService.ts | 19 +++++++++++++++ 5 files changed, 62 insertions(+) create mode 100644 tools/obscuroscan_v3/frontend/api/general.ts create mode 100644 tools/obscuroscan_v3/frontend/src/components/health-indicator.tsx create mode 100644 tools/obscuroscan_v3/frontend/src/services/useGeneralService.ts diff --git a/tools/obscuroscan_v3/frontend/api/general.ts b/tools/obscuroscan_v3/frontend/api/general.ts new file mode 100644 index 0000000000..88324a5255 --- /dev/null +++ b/tools/obscuroscan_v3/frontend/api/general.ts @@ -0,0 +1,14 @@ +import { ResponseDataInterface } from "@/src/types/interfaces"; +import { httpRequest } from "."; +import { pathToUrl } from "@/src/routes/router"; +import { apiRoutes } from "@/src/routes"; + +export const fetchTestnetStatus = async (): Promise< + ResponseDataInterface +> => { + return await httpRequest>({ + method: "post", + url: pathToUrl(apiRoutes.getHealthStatus), + data: { jsonrpc: "2.0", method: "obscuro_health", params: [], id: 1 }, + }); +}; diff --git a/tools/obscuroscan_v3/frontend/src/components/health-indicator.tsx b/tools/obscuroscan_v3/frontend/src/components/health-indicator.tsx new file mode 100644 index 0000000000..6bc25c4827 --- /dev/null +++ b/tools/obscuroscan_v3/frontend/src/components/health-indicator.tsx @@ -0,0 +1,24 @@ +import React from "react"; +import { Badge, badgeVariants } from "./ui/badge"; +import { useGeneralService } from "../services/useGeneralService"; + +const HealthIndicator = () => { + const { testnetStatus } = useGeneralService(); + + return ( +
+

Testnet Status:

+ + {testnetStatus?.result ? "Live" : "Down"} + +
+ ); +}; + +export default HealthIndicator; diff --git a/tools/obscuroscan_v3/frontend/src/components/layouts/header.tsx b/tools/obscuroscan_v3/frontend/src/components/layouts/header.tsx index 7a2b0ce726..d2ddfb493d 100644 --- a/tools/obscuroscan_v3/frontend/src/components/layouts/header.tsx +++ b/tools/obscuroscan_v3/frontend/src/components/layouts/header.tsx @@ -5,6 +5,7 @@ import Link from "next/link"; import { HamburgerMenuIcon } from "@radix-ui/react-icons"; import { useState } from "react"; import { Button } from "../ui/button"; +import HealthIndicator from "../health-indicator"; export default function Header() { return ( @@ -16,6 +17,7 @@ export default function Header() {
+
diff --git a/tools/obscuroscan_v3/frontend/src/routes/index.ts b/tools/obscuroscan_v3/frontend/src/routes/index.ts index ebd6e29ecd..045b35989d 100644 --- a/tools/obscuroscan_v3/frontend/src/routes/index.ts +++ b/tools/obscuroscan_v3/frontend/src/routes/index.ts @@ -23,6 +23,9 @@ export const apiRoutes = { // **** ROLLUPS **** getRollups: "/items/rollup/latest/", decryptEncryptedRollup: "/actions/decryptTxBlob/", + + // **** INFO **** + getHealthStatus: "/info/health/", }; export const ethMethods = { diff --git a/tools/obscuroscan_v3/frontend/src/services/useGeneralService.ts b/tools/obscuroscan_v3/frontend/src/services/useGeneralService.ts new file mode 100644 index 0000000000..f82c686456 --- /dev/null +++ b/tools/obscuroscan_v3/frontend/src/services/useGeneralService.ts @@ -0,0 +1,19 @@ +import { fetchTestnetStatus } from "@/api/general"; +import { useQuery } from "@tanstack/react-query"; +import { useState } from "react"; + +export const useGeneralService = () => { + const [noPolling, setNoPolling] = useState(false); + + const { + data: testnetStatus, + isLoading: isStatusLoading, + refetch: refetchTestnetStatus, + } = useQuery({ + queryKey: ["testnetStatus"], + queryFn: () => fetchTestnetStatus(), + // refetchInterval: noPolling ? false : pollingInterval, + }); + + return { testnetStatus, isStatusLoading, setNoPolling, refetchTestnetStatus }; +}; From ba87900a58ba9629f052644676050ad660a5a791 Mon Sep 17 00:00:00 2001 From: Jennifer Echenim Date: Fri, 29 Dec 2023 21:34:26 +0400 Subject: [PATCH 4/5] Refactor health status method names --- go/obsclient/obsclient.go | 4 ++-- tools/tenscan/backend/obscuroscan_backend.go | 4 ++-- tools/tenscan/backend/webserver/webserver_routes_items.go | 3 ++- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/go/obsclient/obsclient.go b/go/obsclient/obsclient.go index dfae081095..b16021f49f 100644 --- a/go/obsclient/obsclient.go +++ b/go/obsclient/obsclient.go @@ -86,8 +86,8 @@ func (oc *ObsClient) BatchHeaderByHash(hash gethcommon.Hash) (*common.BatchHeade return batchHeader, err } -// HealthStatusOfNode returns the health of the node. -func (oc *ObsClient) HealthStatusOfNode() (bool, error) { +// Health returns the health of the node. +func (oc *ObsClient) Health() (bool, error) { var healthy *hostcommon.HealthCheck err := oc.rpcClient.Call(&healthy, rpc.Health) if err != nil { diff --git a/tools/tenscan/backend/obscuroscan_backend.go b/tools/tenscan/backend/obscuroscan_backend.go index 26741b24b2..527a4669b3 100644 --- a/tools/tenscan/backend/obscuroscan_backend.go +++ b/tools/tenscan/backend/obscuroscan_backend.go @@ -30,8 +30,8 @@ func (b *Backend) GetLatestBatch() (*common.BatchHeader, error) { return b.obsClient.BatchHeaderByNumber(nil) } -func (b *Backend) GetHealthStatus() (bool, error) { - return b.obsClient.HealthStatusOfNode() +func (b *Backend) GetTenNodeHealthStatus() (bool, error) { + return b.obsClient.Health() } func (b *Backend) GetLatestRollup() (*common.RollupHeader, error) { diff --git a/tools/tenscan/backend/webserver/webserver_routes_items.go b/tools/tenscan/backend/webserver/webserver_routes_items.go index 3086599dd1..f0de58bfbc 100644 --- a/tools/tenscan/backend/webserver/webserver_routes_items.go +++ b/tools/tenscan/backend/webserver/webserver_routes_items.go @@ -21,8 +21,9 @@ func routeItems(r *gin.Engine, server *WebServer) { } func (w *WebServer) getHealthStatus(c *gin.Context) { - healthStatus, err := w.backend.GetHealthStatus() + healthStatus, err := w.backend.GetTenNodeHealthStatus() + // TODO: error handling, since this does not easily tell connection errors from health errors c.JSON(http.StatusOK, gin.H{"result": healthStatus, "errors": fmt.Sprintf("%s", err)}) } From d87f71adf0476e072b2b99b2ef49fd74af6f4c1e Mon Sep 17 00:00:00 2001 From: Jennifer Echenim Date: Fri, 29 Dec 2023 21:39:59 +0400 Subject: [PATCH 5/5] Refactor health check function calls --- integration/networktest/env/dev_network.go | 2 +- integration/networktest/util.go | 2 +- integration/simulation/network/socket.go | 2 +- testnet/launcher/docker.go | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/integration/networktest/env/dev_network.go b/integration/networktest/env/dev_network.go index c97cf19a09..89281d564d 100644 --- a/integration/networktest/env/dev_network.go +++ b/integration/networktest/env/dev_network.go @@ -50,7 +50,7 @@ func awaitHealthStatus(rpcAddress string, timeout time.Duration) error { return fmt.Errorf("failed dial host (%s): %w", rpcAddress, err) } defer c.Close() - healthy, err := c.HealthStatusOfNode() + healthy, err := c.Health() if err != nil { return fmt.Errorf("failed to get host health (%s): %w", rpcAddress, err) } diff --git a/integration/networktest/util.go b/integration/networktest/util.go index 7c37127b46..4ec1f924d4 100644 --- a/integration/networktest/util.go +++ b/integration/networktest/util.go @@ -24,7 +24,7 @@ func NodeHealthCheck(rpcAddress string) error { if err != nil { return err } - health, err := client.HealthStatusOfNode() + health, err := client.Health() if err != nil { return err } diff --git a/integration/simulation/network/socket.go b/integration/simulation/network/socket.go index 83c96df8f6..323ddb2fac 100644 --- a/integration/simulation/network/socket.go +++ b/integration/simulation/network/socket.go @@ -181,7 +181,7 @@ func (n *networkOfSocketNodes) createConnections(simParams *params.SimParams) er startTime := time.Now() healthy := false for ; !healthy; time.Sleep(500 * time.Millisecond) { - healthy, _ = client.HealthStatusOfNode() + healthy, _ = client.Health() if time.Now().After(startTime.Add(3 * time.Minute)) { return fmt.Errorf("nodes not healthy after 3 minutes") } diff --git a/testnet/launcher/docker.go b/testnet/launcher/docker.go index 7d3c8dbc79..2f254307e1 100644 --- a/testnet/launcher/docker.go +++ b/testnet/launcher/docker.go @@ -225,7 +225,7 @@ func waitForHealthyNode(port int) error { // todo: hook the cfg defer client.Stop() obsClient := obsclient.NewObsClient(client) - health, err := obsClient.HealthStatusOfNode() + health, err := obsClient.Health() if err != nil { return err }