Skip to content

Commit

Permalink
Merge branch 'feat/chain-go-sdk' into sovereign-merge-demo-refactor
Browse files Browse the repository at this point in the history
# Conflicts:
#	cmd/sovereignnode/go.mod
#	cmd/sovereignnode/go.sum
#	cmd/sovereignnode/sovereignNodeRunner.go
#	errors/errors.go
#	factory/api/apiResolverFactory.go
#	go.mod
#	go.sum
  • Loading branch information
axenteoctavian committed Jan 30, 2024
2 parents ff50782 + 5c25b88 commit fad1584
Show file tree
Hide file tree
Showing 640 changed files with 20,559 additions and 12,028 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/create_release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,8 @@ jobs:
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
hub release create --draft --message="Release draft from Github Actions" vNext
gh release create --draft --notes="Release draft from Github Actions" vNext
sleep 10
for i in $(find ./assets -name '*.tgz' -type f); do
hub release edit --attach=${i} --message="" vNext
gh release upload vNext ${i}
done
30 changes: 30 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,36 @@ sudo cp protoc-gen-gogoslick /usr/bin/

Done

## Running p2p Prometheus dashboards
1. Start the node with `--p2p-prometheus-metrics` flag. This exposes a metrics collection at http://localhost:8080/debug/metrics/prometheus (port defined by -rest-api-interface flag, default 8080)
2. Clone libp2p repository: `git clone https://github.com/libp2p/go-libp2p`
3. `cd go-libp2p/dasboards/swarm` and under the
```
"templating": {
"list": [
```
section, add the following lines:
```
{
"hide": 0,
"label": "datasource",
"name": "DS_PROMETHEUS",
"options": [],
"query": "prometheus",
"refresh": 1,
"regex": "",
"type": "datasource"
},
```
(this step will be removed once it will be fixed on libp2p)
4. `cd ..` to dashboards directory and update the port of `host.docker.internal` from `prometheus.yml` to node's Rest API port(default `8080`)
5. From this directory, run the following docker compose command:
```
sudo docker compose -f docker-compose.base.yml -f docker-compose-linux.yml up --force-recreate
```
**Note:** If you choose to install the new Docker version manually, please make sure that installation is done for all users of the system. Otherwise, the docker command will fail because it needs the super-user privileges.
6. The preconfigured dashboards should be now available on Grafana at http://localhost:3000/dashboards

## Progress

### Done
Expand Down
3 changes: 3 additions & 0 deletions api/errors/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -171,3 +171,6 @@ var ErrGetEligibleManagedKeys = errors.New("error getting the eligible managed k

// ErrGetWaitingManagedKeys signals that an error occurred while getting the waiting managed keys
var ErrGetWaitingManagedKeys = errors.New("error getting the waiting managed keys")

// ErrGetWaitingEpochsLeftForPublicKey signals that an error occurred while getting the waiting epochs left for public key
var ErrGetWaitingEpochsLeftForPublicKey = errors.New("error getting the waiting epochs left for public key")
7 changes: 6 additions & 1 deletion api/gin/common_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,12 @@ func TestCommon_checkArgs(t *testing.T) {
err := checkArgs(args)
require.True(t, errors.Is(err, apiErrors.ErrCannotCreateGinWebServer))

args.Facade, err = initial.NewInitialNodeFacade("api interface", false, &testscommon.StatusMetricsStub{})
args.Facade, err = initial.NewInitialNodeFacade(initial.ArgInitialNodeFacade{
ApiInterface: "api interface",
PprofEnabled: false,
P2PPrometheusMetricsEnabled: false,
StatusMetricsHandler: &testscommon.StatusMetricsStub{},
})
require.NoError(t, err)
err = checkArgs(args)
require.NoError(t, err)
Expand Down
12 changes: 11 additions & 1 deletion api/gin/webServer.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,13 @@ import (
"github.com/multiversx/mx-chain-go/config"
"github.com/multiversx/mx-chain-go/facade"
logger "github.com/multiversx/mx-chain-logger-go"
"github.com/prometheus/client_golang/prometheus/promhttp"
)

var log = logger.GetOrCreate("api/gin")

const prometheusMetricsRoute = "/debug/metrics/prometheus"

// ArgsNewWebServer holds the arguments needed to create a new instance of webServer
type ArgsNewWebServer struct {
Facade shared.FacadeHandler
Expand Down Expand Up @@ -227,6 +230,10 @@ func (ws *webServer) registerRoutes(ginRouter *gin.Engine) {
if ws.facade.PprofEnabled() {
pprof.Register(ginRouter)
}

if ws.facade.P2PPrometheusMetricsEnabled() {
ginRouter.GET(prometheusMetricsRoute, gin.WrapH(promhttp.Handler()))
}
}

func (ws *webServer) createMiddlewareLimiters() ([]shared.MiddlewareProcessor, error) {
Expand Down Expand Up @@ -281,8 +288,11 @@ func (ws *webServer) Close() error {
ws.cancelFunc()
}

var err error
ws.Lock()
err := ws.httpServer.Close()
if !check.IfNil(ws.httpServer) {
err = ws.httpServer.Close()
}
ws.Unlock()

if err != nil {
Expand Down
29 changes: 29 additions & 0 deletions api/gin/webServer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package gin

import (
"errors"
"fmt"
"net/http"
"strings"
"testing"
Expand All @@ -14,6 +15,7 @@ import (
"github.com/multiversx/mx-chain-go/config"
"github.com/multiversx/mx-chain-go/facade"
"github.com/multiversx/mx-chain-go/testscommon/api"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

Expand Down Expand Up @@ -174,3 +176,30 @@ func TestWebServer_UpdateFacade(t *testing.T) {
require.Nil(t, err)
})
}

func TestWebServer_CloseWithDisabledServerShouldNotPanic(t *testing.T) {
t.Parallel()

defer func() {
r := recover()
if r != nil {
assert.Fail(t, fmt.Sprintf("should have not panicked %v", r))
}
}()

args := createMockArgsNewWebServer()
args.Facade = &mock.FacadeStub{
RestApiInterfaceCalled: func() string {
return facade.DefaultRestPortOff
},
}

ws, _ := NewGinWebServerHandler(args)
require.NotNil(t, ws)

err := ws.StartHttpServer()
require.Nil(t, err)

err = ws.Close()
assert.Nil(t, err)
}
19 changes: 19 additions & 0 deletions api/groups/nodeGroup.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ const (
managedKeysCount = "/managed-keys/count"
eligibleManagedKeys = "/managed-keys/eligible"
waitingManagedKeys = "/managed-keys/waiting"
epochsLeftInWaiting = "/waiting-epochs-left/:key"
)

// nodeFacadeHandler defines the methods to be implemented by a facade for node requests
Expand All @@ -45,6 +46,7 @@ type nodeFacadeHandler interface {
GetManagedKeys() []string
GetEligibleManagedKeys() ([]string, error)
GetWaitingManagedKeys() ([]string, error)
GetWaitingEpochsLeftForPublicKey(publicKey string) (uint32, error)
IsInterfaceNil() bool
}

Expand Down Expand Up @@ -137,6 +139,11 @@ func NewNodeGroup(facade nodeFacadeHandler) (*nodeGroup, error) {
Method: http.MethodGet,
Handler: ng.managedKeysWaiting,
},
{
Path: epochsLeftInWaiting,
Method: http.MethodGet,
Handler: ng.waitingEpochsLeft,
},
}
ng.endpoints = endpoints

Expand Down Expand Up @@ -440,6 +447,18 @@ func (ng *nodeGroup) managedKeysWaiting(c *gin.Context) {
)
}

// waitingEpochsLeft returns the number of epochs left for the public key until it becomes eligible
func (ng *nodeGroup) waitingEpochsLeft(c *gin.Context) {
publicKey := c.Param("key")
epochsLeft, err := ng.getFacade().GetWaitingEpochsLeftForPublicKey(publicKey)
if err != nil {
shared.RespondWithInternalError(c, errors.ErrGetWaitingEpochsLeftForPublicKey, err)
return
}

shared.RespondWithSuccess(c, gin.H{"epochsLeft": epochsLeft})
}

func (ng *nodeGroup) getFacade() nodeFacadeHandler {
ng.mutFacade.RLock()
defer ng.mutFacade.RUnlock()
Expand Down
87 changes: 87 additions & 0 deletions api/groups/nodeGroup_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,13 @@ type managedWaitingKeysResponse struct {
generalResponse
}

type waitingEpochsLeftResponse struct {
Data struct {
EpochsLeft uint32 `json:"epochsLeft"`
} `json:"data"`
generalResponse
}

func init() {
gin.SetMode(gin.TestMode)
}
Expand Down Expand Up @@ -276,6 +283,30 @@ func TestBootstrapStatusMetrics_ShouldWork(t *testing.T) {
func TestNodeGroup_GetConnectedPeersRatings(t *testing.T) {
t.Parallel()

t.Run("facade error should error", func(t *testing.T) {
t.Parallel()

facade := mock.FacadeStub{
GetConnectedPeersRatingsOnMainNetworkCalled: func() (string, error) {
return "", expectedErr
},
}

nodeGroup, err := groups.NewNodeGroup(&facade)
require.NoError(t, err)

ws := startWebServer(nodeGroup, "node", getNodeRoutesConfig())

req, _ := http.NewRequest("GET", "/node/connected-peers-ratings", nil)
resp := httptest.NewRecorder()
ws.ServeHTTP(resp, req)

response := &shared.GenericAPIResponse{}
loadResponse(resp.Body, response)

assert.Equal(t, http.StatusInternalServerError, resp.Code)
assert.True(t, strings.Contains(response.Error, expectedErr.Error()))
})
t.Run("should work", func(t *testing.T) {
t.Parallel()

Expand Down Expand Up @@ -851,6 +882,61 @@ func TestNodeGroup_ManagedKeysWaiting(t *testing.T) {
})
}

func TestNodeGroup_WaitingEpochsLeft(t *testing.T) {
t.Parallel()

t.Run("facade error should error", func(t *testing.T) {
t.Parallel()

facade := mock.FacadeStub{
GetWaitingEpochsLeftForPublicKeyCalled: func(publicKey string) (uint32, error) {
return 0, expectedErr
},
}

nodeGroup, err := groups.NewNodeGroup(&facade)
require.NoError(t, err)

ws := startWebServer(nodeGroup, "node", getNodeRoutesConfig())

req, _ := http.NewRequest("GET", "/node/waiting-epochs-left/key", nil)
resp := httptest.NewRecorder()
ws.ServeHTTP(resp, req)

response := &shared.GenericAPIResponse{}
loadResponse(resp.Body, response)

assert.Equal(t, http.StatusInternalServerError, resp.Code)
assert.True(t, strings.Contains(response.Error, expectedErr.Error()))
})
t.Run("should work", func(t *testing.T) {
t.Parallel()

providedEpochsLeft := uint32(10)
facade := mock.FacadeStub{
GetWaitingEpochsLeftForPublicKeyCalled: func(publicKey string) (uint32, error) {
return providedEpochsLeft, nil
},
}

nodeGroup, err := groups.NewNodeGroup(&facade)
require.NoError(t, err)

ws := startWebServer(nodeGroup, "node", getNodeRoutesConfig())

req, _ := http.NewRequest("GET", "/node/waiting-epochs-left/key", nil)
resp := httptest.NewRecorder()
ws.ServeHTTP(resp, req)

response := &waitingEpochsLeftResponse{}
loadResponse(resp.Body, response)

assert.Equal(t, http.StatusOK, resp.Code)
assert.Equal(t, "", response.Error)
assert.Equal(t, providedEpochsLeft, response.Data.EpochsLeft)
})
}

func TestNodeGroup_UpdateFacade(t *testing.T) {
t.Parallel()

Expand Down Expand Up @@ -962,6 +1048,7 @@ func getNodeRoutesConfig() config.ApiRoutesConfig {
{Name: "/managed-keys", Open: true},
{Name: "/managed-keys/eligible", Open: true},
{Name: "/managed-keys/waiting", Open: true},
{Name: "/waiting-epochs-left/:key", Open: true},
},
},
},
Expand Down
Loading

0 comments on commit fad1584

Please sign in to comment.