Skip to content

Commit

Permalink
add check for hedgehog connection at startup and pass in the hedgehog…
Browse files Browse the repository at this point in the history
…Url or use the hard coded default
  • Loading branch information
dekm committed Mar 13, 2024
1 parent 0611d18 commit 910958d
Show file tree
Hide file tree
Showing 6 changed files with 159 additions and 1 deletion.
5 changes: 4 additions & 1 deletion cmd/paxd/cmd/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,10 @@ import (
"github.com/spf13/cobra"
"github.com/spf13/viper"

"pax/app"

"github.com/CosmWasm/wasmd/x/wasm"
wasmcli "github.com/CosmWasm/wasmd/x/wasm/client/cli"
"pax/app"
)

func initRootCmd(
Expand Down Expand Up @@ -144,6 +145,8 @@ func newApp(
if err != nil {
panic(err)
}
homePath := appOpts.Get(flags.FlagHome).(string)
InitializeConfig(homePath)
return app
}

Expand Down
2 changes: 2 additions & 0 deletions cmd/paxd/cmd/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import (
"pax/app"
)

var HedgehogUrl string

func initSDKConfig() {
// Set prefixes
accountPubKeyPrefix := app.AccountAddressPrefix + "pub"
Expand Down
56 changes: 56 additions & 0 deletions cmd/paxd/cmd/root.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package cmd

import (
"fmt"
"os"
"path/filepath"
"strings"

"cosmossdk.io/client/v2/autocli"
Expand All @@ -23,10 +25,16 @@ import (
"github.com/cosmos/cosmos-sdk/x/auth/types"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
"github.com/spf13/viper"

"pax/app"
)

const DefaultHedgehogUrl = "https://149.102.147.45:39886"

// testing localhost hedgehog
//const DefaultHedgehogUrl = "https://127.0.0.1:39886"

// NewRootCmd creates a new root command for paxd. It is called once in the main function.
func NewRootCmd() *cobra.Command {
initSDKConfig()
Expand Down Expand Up @@ -113,6 +121,12 @@ func NewRootCmd() *cobra.Command {
autoCliOpts.Modules[name] = mod
}

// param for the hedgehog url to be passed at startup
rootCmd.PersistentFlags().StringVar(&HedgehogUrl, "hedgehog", "", "Pass the Hedgehog URL")
//fmt.Println("Value of --hedgehog flag:", HedgehogUrl)

viper.BindPFlag("hedgehog.hedgehog_url", rootCmd.PersistentFlags().Lookup("hedgehog"))

initRootCmd(rootCmd, clientCtx.TxConfig, clientCtx.InterfaceRegistry, clientCtx.Codec, moduleBasicManager)

overwriteFlagDefaults(rootCmd, map[string]string{
Expand Down Expand Up @@ -173,3 +187,45 @@ func ProvideKeyring(clientCtx client.Context, addressCodec address.Codec) (clien

return keyring.NewAutoCLIKeyring(kb)
}

// InitializeConfig reads the hedgehog configuration file and ENV variables if set.
// if there is no flag or config we use DefaultHedgehogUrl
func InitializeConfig(home string) {
viper.SetConfigName("hedgehog")
viper.SetConfigType("toml")
configPath := filepath.Join(home, "config")
viper.AddConfigPath(configPath)

// Print the full path of the file it's looking for
fullPath := filepath.Join(configPath, "hedgehog.toml")
fmt.Println("Searching for config file at:", fullPath)

err := viper.ReadInConfig()
if err != nil {
// Check if the error is due to the file not being found
if _, ok := err.(viper.ConfigFileNotFoundError); ok {
// Config file not found; ignore or handle as desired
fmt.Println("Warning: Hedgehog Config file not found. Using default settings.")
} else {
// Some other error occurred; handle or print it
fmt.Printf("Error reading config file: %s", err)
return
}
}

// If HedgehogUrl flag value is set, prioritize it over the configuration file value
if HedgehogUrl != "" {
viper.Set("hedgehog.hedgehog_url", HedgehogUrl)
}

// Get the value of hedgehog_url
hedgehogURL := viper.GetString("hedgehog.hedgehog_url")

// If hedgehogURL is empty, set it to the default value
if hedgehogURL == "" {
hedgehogURL = DefaultHedgehogUrl
viper.Set("hedgehog.hedgehog_url", DefaultHedgehogUrl) // Set the default value in viper
}

fmt.Println("Hedgehog URL:", viper.GetString("hedgehog.hedgehog_url"))
}
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ require (
github.com/spf13/pflag v1.0.5
github.com/spf13/viper v1.18.2
github.com/stretchr/testify v1.8.4
github.com/unigrid-project/cosmos-common v0.0.8
golang.org/x/tools v0.18.0
google.golang.org/genproto/googleapis/api v0.0.0-20231120223509-83a465c0220f
google.golang.org/grpc v1.60.1
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -1092,6 +1092,8 @@ github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZ
github.com/ulikunitz/xz v0.5.10/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
github.com/ulikunitz/xz v0.5.11 h1:kpFauv27b6ynzBNT/Xy+1k+fK4WswhN/6PN5WhFAGw8=
github.com/ulikunitz/xz v0.5.11/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
github.com/unigrid-project/cosmos-common v0.0.8 h1:u7b7NfwKHXbvXj3QGEKaghHrB1TojpaQknA8zgPM0T8=
github.com/unigrid-project/cosmos-common v0.0.8/go.mod h1:1yKYVwjFSztn3PpscSB02WKYUMkFiRpet2qlYB8OBio=
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
github.com/vbatts/tar-split v0.11.5 h1:3bHCTIheBm1qFTcgh9oPu+nNBtX+XJIupG/vacinCts=
Expand Down
94 changes: 94 additions & 0 deletions x/pax/module/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ import (
"context"
"encoding/json"
"fmt"
"io"
"net/http"
"time"

"cosmossdk.io/core/appmodule"
"cosmossdk.io/core/store"
Expand All @@ -17,7 +20,9 @@ import (
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
"github.com/grpc-ecosystem/grpc-gateway/runtime"
"github.com/spf13/viper"

"github.com/unigrid-project/cosmos-common/common/httpclient"
// this line is used by starport scaffolding # 1

modulev1 "pax/api/pax/pax/module"
Expand Down Expand Up @@ -146,6 +151,40 @@ func (AppModule) ConsensusVersion() uint64 { return 1 }
// BeginBlock contains the logic that is automatically triggered at the beginning of each block.
// The begin block implementation is optional.
func (am AppModule) BeginBlock(_ context.Context) error {

hedgehogUrl := viper.GetString("hedgehog.hedgehog_url") + "/gridspork"
fmt.Println("Constructed Hedgehog URL:", hedgehogUrl)

hedgehogAvailable := isConnectedToHedgehog(hedgehogUrl)

if !hedgehogAvailable {
// Start a timer
timer := time.NewTimer(2 * time.Hour) // 2 hours until we panic and shutdown the node

// Set up deferred panic handling
defer func() {
if r := recover(); r != nil {
// Wait for either the timer to expire or the server to become available
select {
case <-timer.C:
// Timer expired, re-panic
panic(r)
case available := <-checkHedgehogAvailability(hedgehogUrl, timer.C):
if available {
fmt.Println("Recovered from panic: Hedgehog server is now available.")
} else {
// Server did not become available in time, re-panic
panic(r)
}
}
}
}()

// Trigger panic
panic("Hedgehog is not available. Node is shutting down.")
}

fmt.Println("Hedgehog is available.")
return nil
}

Expand All @@ -155,6 +194,61 @@ func (am AppModule) EndBlock(_ context.Context) error {
return nil
}

// checkHedgehogAvailability continuously checks if the Hedgehog server becomes available
// and returns a boolean value through a channel when the server is available or the timer expires.
func checkHedgehogAvailability(hedgehogUrl string, timerC <-chan time.Time) <-chan bool {
availabilityChan := make(chan bool)
go func() {
defer close(availabilityChan)
for {
select {
case <-timerC:
fmt.Println("Timer expired in monitoring goroutine")
availabilityChan <- false
return
default:
if isConnectedToHedgehog(hedgehogUrl) {
fmt.Println("Hedgehog server became available")
availabilityChan <- true
return
}
fmt.Println("Checking Hedgehog availability...")
time.Sleep(5 * time.Second) // check interval, adjust as needed
}
}
}()
return availabilityChan
}

// isConnectedToHedgehog performs an HTTP GET request to check the connectivity with the Hedgehog server.
func isConnectedToHedgehog(serverUrl string) bool {

response, err := httpclient.Client.Get(serverUrl)

if err != nil {
fmt.Println("Error accessing hedgehog:", err.Error())
return false
}
defer response.Body.Close()

// Read and discard the response body
_, err = io.ReadAll(response.Body)
if err != nil {
fmt.Println("Error reading response body:", err.Error())
return false
}

// Check if the HTTP status is 200 OK
if response.StatusCode == http.StatusOK {
fmt.Printf("Received OK response from hedgehog server: %d\n", response.StatusCode)
return true
}

fmt.Printf("Received non-OK response from hedgehog server: %d\n", response.StatusCode)

return false
}

// IsOnePerModuleType implements the depinject.OnePerModuleType interface.
func (am AppModule) IsOnePerModuleType() {}

Expand Down

0 comments on commit 910958d

Please sign in to comment.