From e6f583a038415b300c071618fd7e3d111f59ddae Mon Sep 17 00:00:00 2001 From: Sergey <83376337+freak12techno@users.noreply.github.com> Date: Sat, 23 Dec 2023 01:15:58 +0300 Subject: [PATCH] chore: move HTTP requests to different class (#63) --- pkg/fetchers/cosmos/fetcher.go | 63 ++----------------- pkg/fetchers/cosmos/params.go | 2 +- pkg/fetchers/cosmos/proposals_v1.go | 2 +- pkg/fetchers/cosmos/proposals_v1beta1.go | 2 +- pkg/fetchers/cosmos/tally.go | 2 +- pkg/fetchers/cosmos/vote.go | 2 +- pkg/http/client.go | 77 ++++++++++++++++++++++++ 7 files changed, 86 insertions(+), 64 deletions(-) create mode 100644 pkg/http/client.go diff --git a/pkg/fetchers/cosmos/fetcher.go b/pkg/fetchers/cosmos/fetcher.go index f66377d..fa1aa13 100644 --- a/pkg/fetchers/cosmos/fetcher.go +++ b/pkg/fetchers/cosmos/fetcher.go @@ -1,11 +1,8 @@ package cosmos import ( - "encoding/json" "main/pkg/fetchers/cosmos/responses" - "net/http" - "time" - + "main/pkg/http" "main/pkg/types" "github.com/rs/zerolog" @@ -15,17 +12,17 @@ const PaginationLimit = 1000 type RPC struct { ChainConfig *types.Chain - URLs []string ProposalsType string + Client *http.Client Logger zerolog.Logger } func NewRPC(chainConfig *types.Chain, logger zerolog.Logger) *RPC { return &RPC{ ChainConfig: chainConfig, - URLs: chainConfig.LCDEndpoints, ProposalsType: chainConfig.ProposalsType, Logger: logger.With().Str("component", "rpc").Logger(), + Client: http.NewClient(chainConfig.Name, chainConfig.LCDEndpoints, logger), } } @@ -41,7 +38,7 @@ func (rpc *RPC) GetStakingPool() (*responses.PoolRPCResponse, *types.QueryError) url := "/cosmos/staking/v1beta1/pool" var pool responses.PoolRPCResponse - if errs := rpc.Get(url, &pool); len(errs) > 0 { + if errs := rpc.Client.Get(url, &pool); len(errs) > 0 { return nil, &types.QueryError{ QueryError: nil, NodeErrors: errs, @@ -50,55 +47,3 @@ func (rpc *RPC) GetStakingPool() (*responses.PoolRPCResponse, *types.QueryError) return &pool, nil } - -func (rpc *RPC) Get(url string, target interface{}) []types.NodeError { - nodeErrors := make([]types.NodeError, len(rpc.URLs)) - - for index, lcd := range rpc.URLs { - fullURL := lcd + url - rpc.Logger.Trace().Str("url", fullURL).Msg("Trying making request to LCD") - - err := rpc.GetFull( - fullURL, - target, - ) - - if err == nil { - return nil - } - - rpc.Logger.Warn().Str("url", fullURL).Err(err).Msg("LCD request failed") - nodeErrors[index] = types.NodeError{ - Node: lcd, - Error: types.NewJSONError(err), - } - } - - rpc.Logger.Warn().Str("url", url).Msg("All LCD requests failed") - return nodeErrors -} - -func (rpc *RPC) GetFull(url string, target interface{}) error { - client := &http.Client{Timeout: 300 * time.Second} - start := time.Now() - - req, err := http.NewRequest(http.MethodGet, url, nil) - if err != nil { - return err - } - - req.Header.Set("User-Agent", "cosmos-proposals-checker") - - rpc.Logger.Debug().Str("url", url).Msg("Doing a query...") - - res, err := client.Do(req) - if err != nil { - rpc.Logger.Warn().Str("url", url).Err(err).Msg("Query failed") - return err - } - defer res.Body.Close() - - rpc.Logger.Debug().Str("url", url).Dur("duration", time.Since(start)).Msg("Query is finished") - - return json.NewDecoder(res.Body).Decode(target) -} diff --git a/pkg/fetchers/cosmos/params.go b/pkg/fetchers/cosmos/params.go index 21d2674..1dff656 100644 --- a/pkg/fetchers/cosmos/params.go +++ b/pkg/fetchers/cosmos/params.go @@ -11,7 +11,7 @@ func (rpc *RPC) GetGovParams(paramsType string) (*responses.ParamsResponse, *typ url := fmt.Sprintf("/cosmos/gov/v1beta1/params/%s", paramsType) var params responses.ParamsResponse - if errs := rpc.Get(url, ¶ms); len(errs) > 0 { + if errs := rpc.Client.Get(url, ¶ms); len(errs) > 0 { return nil, &types.QueryError{ QueryError: nil, NodeErrors: errs, diff --git a/pkg/fetchers/cosmos/proposals_v1.go b/pkg/fetchers/cosmos/proposals_v1.go index dfe8278..706b535 100644 --- a/pkg/fetchers/cosmos/proposals_v1.go +++ b/pkg/fetchers/cosmos/proposals_v1.go @@ -21,7 +21,7 @@ func (rpc *RPC) GetAllV1Proposals() ([]types.Proposal, *types.QueryError) { ) var batchProposals responses.V1ProposalsRPCResponse - if errs := rpc.Get(url, &batchProposals); len(errs) > 0 { + if errs := rpc.Client.Get(url, &batchProposals); len(errs) > 0 { return nil, &types.QueryError{ QueryError: nil, NodeErrors: errs, diff --git a/pkg/fetchers/cosmos/proposals_v1beta1.go b/pkg/fetchers/cosmos/proposals_v1beta1.go index 7dfbbf9..8eb4089 100644 --- a/pkg/fetchers/cosmos/proposals_v1beta1.go +++ b/pkg/fetchers/cosmos/proposals_v1beta1.go @@ -21,7 +21,7 @@ func (rpc *RPC) GetAllV1beta1Proposals() ([]types.Proposal, *types.QueryError) { ) var batchProposals responses.V1Beta1ProposalsRPCResponse - if errs := rpc.Get(url, &batchProposals); len(errs) > 0 { + if errs := rpc.Client.Get(url, &batchProposals); len(errs) > 0 { return nil, &types.QueryError{ QueryError: nil, NodeErrors: errs, diff --git a/pkg/fetchers/cosmos/tally.go b/pkg/fetchers/cosmos/tally.go index 83c95e5..af22ac9 100644 --- a/pkg/fetchers/cosmos/tally.go +++ b/pkg/fetchers/cosmos/tally.go @@ -16,7 +16,7 @@ func (rpc *RPC) GetTally(proposal string) (*types.Tally, *types.QueryError) { ) var tally responses.TallyRPCResponse - if errs := rpc.Get(url, &tally); len(errs) > 0 { + if errs := rpc.Client.Get(url, &tally); len(errs) > 0 { return nil, &types.QueryError{ QueryError: nil, NodeErrors: errs, diff --git a/pkg/fetchers/cosmos/vote.go b/pkg/fetchers/cosmos/vote.go index aa34dce..1d54d05 100644 --- a/pkg/fetchers/cosmos/vote.go +++ b/pkg/fetchers/cosmos/vote.go @@ -16,7 +16,7 @@ func (rpc *RPC) GetVote(proposal, voter string) (*types.Vote, *types.QueryError) ) var vote responses.VoteRPCResponse - if errs := rpc.Get(url, &vote); len(errs) > 0 { + if errs := rpc.Client.Get(url, &vote); len(errs) > 0 { return nil, &types.QueryError{ QueryError: nil, NodeErrors: errs, diff --git a/pkg/http/client.go b/pkg/http/client.go new file mode 100644 index 0000000..f0f6eee --- /dev/null +++ b/pkg/http/client.go @@ -0,0 +1,77 @@ +package http + +import ( + "encoding/json" + "main/pkg/types" + "net/http" + "time" + + "github.com/rs/zerolog" +) + +type Client struct { + Hosts []string + Logger zerolog.Logger +} + +func NewClient(chainName string, hosts []string, logger zerolog.Logger) *Client { + return &Client{ + Hosts: hosts, + Logger: logger.With(). + Str("component", "http"). + Str("chain", chainName). + Logger(), + } +} + +func (client *Client) Get(url string, target interface{}) []types.NodeError { + nodeErrors := make([]types.NodeError, len(client.Hosts)) + + for index, lcd := range client.Hosts { + fullURL := lcd + url + client.Logger.Trace().Str("url", fullURL).Msg("Trying making request to LCD") + + err := client.GetFull( + fullURL, + target, + ) + + if err == nil { + return nil + } + + client.Logger.Warn().Str("url", fullURL).Err(err).Msg("LCD request failed") + nodeErrors[index] = types.NodeError{ + Node: lcd, + Error: types.NewJSONError(err), + } + } + + client.Logger.Warn().Str("url", url).Msg("All LCD requests failed") + return nodeErrors +} + +func (client *Client) GetFull(url string, target interface{}) error { + httpClient := &http.Client{Timeout: 300 * time.Second} + start := time.Now() + + req, err := http.NewRequest(http.MethodGet, url, nil) + if err != nil { + return err + } + + req.Header.Set("User-Agent", "cosmos-proposals-checker") + + client.Logger.Debug().Str("url", url).Msg("Doing a query...") + + res, err := httpClient.Do(req) + if err != nil { + client.Logger.Warn().Str("url", url).Err(err).Msg("Query failed") + return err + } + defer res.Body.Close() + + client.Logger.Debug().Str("url", url).Dur("duration", time.Since(start)).Msg("Query is finished") + + return json.NewDecoder(res.Body).Decode(target) +}