Skip to content

Commit

Permalink
Update health endpoint with active peers (#65)
Browse files Browse the repository at this point in the history
* Update health endpoint with active peers

* Fix tests
  • Loading branch information
galt-tr committed Feb 26, 2024
1 parent ea5ac71 commit becd9cf
Show file tree
Hide file tree
Showing 13 changed files with 58 additions and 22 deletions.
20 changes: 13 additions & 7 deletions app/api/base/health.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@ import (

// HealthResponse is the response for the health endpoint
type HealthResponse struct {
Alert models.AlertMessage `json:"alert"`
Sequence uint32 `json:"sequence"`
Synced bool `json:"synced"`
Alert models.AlertMessage `json:"alert"`
Sequence uint32 `json:"sequence"`
Synced bool `json:"synced"`
ActivePeers int `json:"active_peers"`
UnprocessedAlerts int `json:"unprocessed_alerts"`
}

// health will return the health of the API and the current alert
Expand All @@ -32,14 +34,18 @@ func (a *Action) health(w http.ResponseWriter, req *http.Request, _ httprouter.P
return
}

failed, _ := models.GetAllUnprocessedAlerts(req.Context(), nil, model.WithAllDependencies(a.Config))

// Return the response
_ = apirouter.ReturnJSONEncode(
w,
http.StatusOK,
json.NewEncoder(w),
HealthResponse{
Alert: *alert,
Sequence: alert.SequenceNumber,
Synced: true, // TODO actually fetch this state from the DB somehow, or from the server struct
}, []string{"alert", "synced", "sequence"})
Alert: *alert,
Sequence: alert.SequenceNumber,
ActivePeers: a.P2pServer.ActivePeers(),
UnprocessedAlerts: len(failed),
Synced: true, // TODO actually fetch this state from the DB somehow, or from the server struct
}, []string{"alert", "synced", "sequence", "active_peers", "unprocessed_alerts"})
}
6 changes: 4 additions & 2 deletions app/api/base/routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package base
import (
"net/http"

"github.com/bitcoin-sv/alert-system/app/p2p"

"github.com/bitcoin-sv/alert-system/app"
"github.com/bitcoin-sv/alert-system/app/config"
apirouter "github.com/mrz1836/go-api-router"
Expand All @@ -14,10 +16,10 @@ type Action struct {
}

// RegisterRoutes register all the package specific routes
func RegisterRoutes(router *apirouter.Router, conf *config.Config) {
func RegisterRoutes(router *apirouter.Router, conf *config.Config, p2pServ *p2p.Server) {

// Load the actions and set the services
action := &Action{app.Action{Config: conf}}
action := &Action{app.Action{Config: conf, P2pServer: p2pServ}}

// Set the main index page (navigating to slash or the root of the major version)
router.HTTPRouter.GET("/", action.Request(router, action.index))
Expand Down
5 changes: 4 additions & 1 deletion app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,16 @@ package app
import (
"net/http"

"github.com/bitcoin-sv/alert-system/app/p2p"

"github.com/bitcoin-sv/alert-system/app/config"
apirouter "github.com/mrz1836/go-api-router"
)

// Action is the configuration for the actions and related services
type Action struct {
Config *config.Config // Combination of configuration and services, being passed down into the handlers
Config *config.Config // Combination of configuration and services, being passed down into the handlers
P2pServer *p2p.Server // p2p server
}

// APIError is the enriched error message for API related errors
Expand Down
3 changes: 2 additions & 1 deletion app/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,8 @@ type (

// P2PConfig is the configuration for the P2P server and connection
P2PConfig struct {
AlertSystemProtocolID string `json:"alert_system_protocol_id" mapstructure:"alert_system_protocol_id"` // AlertSystemProtocolID is the protocol ID to use on the libp2p network for alert system communication
AlertSystemProtocolID string `json:"alert_system_protocol_id" mapstructure:"alert_system_protocol_id"` // AlertSystemProtocolID is the protocol ID to use on the libp2p network for alert system communication
DHTMode string `json:"dht_mode"`
BootstrapPeer string `json:"bootstrap_peer" mapstructure:"bootstrap_peer"` // BootstrapPeer is the bootstrap peer for the libp2p network
BroadcastIP string `json:"broadcast_ip" mapstructure:"broadcast_ip"` // BroadcastIP is the public facing IP address to broadcast to other peers
IP string `json:"ip" mapstructure:"ip"` // IP is the IP address for the P2P server
Expand Down
1 change: 1 addition & 0 deletions app/config/envs/mainnet.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
"p2p": {
"ip": "0.0.0.0",
"port": "9906",
"dht_mode": "client",
"broadcast_ip": "",
"alert_system_protocol_id": "/bitcoin/alert-system/1.0.0",
"bootstrap_peer": "",
Expand Down
1 change: 1 addition & 0 deletions app/config/envs/stn.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
"p2p": {
"ip": "0.0.0.0",
"port": "9906",
"dht_mode": "client",
"alert_system_protocol_id": "/bitcoin-stn/alert-system/0.0.1",
"bootstrap_peer": "",
"broadcast_ip": "",
Expand Down
1 change: 1 addition & 0 deletions app/config/envs/testnet.json
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@
"bootstrap_peer": "",
"broadcast_ip": "",
"private_key_path": "",
"dht_mode": "client",
"allow_private_ip_addresses": false,
"topic_name": "bitcoin_alert_system_testnet"
},
Expand Down
6 changes: 5 additions & 1 deletion app/p2p/dht.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,11 @@ import (
func (s *Server) initDHT(ctx context.Context) (*dht.IpfsDHT, error) {
logger := s.config.Services.Log
var options []dht.Option
options = append(options, dht.Mode(dht.ModeAutoServer))
mode := dht.ModeAutoServer
if s.config.P2P.DHTMode == "client" {
mode = dht.ModeClient
}
options = append(options, dht.Mode(mode))
options = append(options, dht.QueryFilter(dht.PublicQueryFilter))

// Sync a DHT, for use in peer discovery. We can't just make a new DHT
Expand Down
7 changes: 7 additions & 0 deletions app/p2p/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ type Server struct {
quitAlertProcessingChannel chan bool
quitPeerDiscoveryChannel chan bool
quitPeerInitializationChannel chan bool
activePeers int
//peers []peer.AddrInfo
}

Expand Down Expand Up @@ -338,6 +339,11 @@ func (s *Server) Stop(_ context.Context) error {
return s.dht.Close()
}

// ActivePeers returns the number of active peers
func (s *Server) ActivePeers() int {
return s.activePeers
}

// RunAlertProcessingCron starts a cron job to attempt to retry unprocessed alerts
func (s *Server) RunAlertProcessingCron(ctx context.Context) chan bool {
ticker := time.NewTicker(s.config.AlertProcessingInterval)
Expand Down Expand Up @@ -550,6 +556,7 @@ func (s *Server) discoverPeers(ctx context.Context, routingDiscovery *drouting.R
s.config.Services.Log.Debugf("connected to %d peers\n", len(s.host.Network().Peers()))
s.config.Services.Log.Debugf("peerstore has %d peers\n", len(s.host.Peerstore().Peers()))
s.config.Services.Log.Infof("Successfully discovered %d active peers at %s", connected, time.Now().String())
s.activePeers = connected
s.connected = true
return nil
}
Expand Down
12 changes: 9 additions & 3 deletions app/webserver/webserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import (
"net/http"
"strings"

"github.com/bitcoin-sv/alert-system/app/p2p"

"github.com/bitcoin-sv/alert-system/app/api/base"
"github.com/bitcoin-sv/alert-system/app/config"
apirouter "github.com/mrz1836/go-api-router"
Expand All @@ -23,11 +25,15 @@ type Server struct {
Config *config.Config
Router *apirouter.Router
WebServer *http.Server
P2pServer *p2p.Server
}

// NewServer will return a new server service
func NewServer(conf *config.Config) *Server {
return &Server{Config: conf}
func NewServer(conf *config.Config, serv *p2p.Server) *Server {
return &Server{
Config: conf,
P2pServer: serv,
}
}

// Serve will load a server and start serving
Expand Down Expand Up @@ -100,7 +106,7 @@ func (s *Server) Handlers() *nrhttprouter.Router {
}, ",")

// Register all actions (routes / handlers)
base.RegisterRoutes(s.Router, s.Config)
base.RegisterRoutes(s.Router, s.Config, s.P2pServer)

// Return the router
return s.Router.HTTPRouter
Expand Down
4 changes: 3 additions & 1 deletion app/webserver/webserver_no_race_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import (
"testing"
"time"

"github.com/bitcoin-sv/alert-system/app/p2p"

"github.com/bitcoin-sv/alert-system/app/config"
"github.com/bitcoin-sv/alert-system/app/models"
"github.com/stretchr/testify/require"
Expand All @@ -36,7 +38,7 @@ func TestServer_Shutdown_NoRace(t *testing.T) {
require.NotNil(t, dependencies)

// Sync a new server
s := NewServer(dependencies)
s := NewServer(dependencies, &p2p.Server{})
require.NotNil(t, s)

// todo having an issue starting webserver and shutting down (in different routines)
Expand Down
12 changes: 7 additions & 5 deletions app/webserver/webserver_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import (
"os"
"testing"

"github.com/bitcoin-sv/alert-system/app/p2p"

"github.com/bitcoin-sv/alert-system/app/config"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
Expand All @@ -15,7 +17,7 @@ func TestNewServer(t *testing.T) {
t.Parallel()

t.Run("empty values", func(t *testing.T) {
s := NewServer(nil)
s := NewServer(nil, nil)
require.NotNil(t, s)
assert.Nil(t, s.Config)
assert.Nil(t, s.Router)
Expand All @@ -24,7 +26,7 @@ func TestNewServer(t *testing.T) {

t.Run("set values", func(t *testing.T) {
dependencies := &config.Config{}
s := NewServer(dependencies)
s := NewServer(dependencies, &p2p.Server{})
require.NotNil(t, s)
assert.Equal(t, dependencies, s.Config)
assert.Equal(t, dependencies, s.Config)
Expand All @@ -38,7 +40,7 @@ func TestServer_Shutdown(t *testing.T) {
t.Parallel()

t.Run("no server, services", func(t *testing.T) {
s := NewServer(nil)
s := NewServer(nil, nil)
require.NotNil(t, s)

err := s.Shutdown(context.Background())
Expand All @@ -48,7 +50,7 @@ func TestServer_Shutdown(t *testing.T) {
t.Run("basic app config and services", func(t *testing.T) {
dependencies := &config.Config{}

s := NewServer(dependencies)
s := NewServer(dependencies, &p2p.Server{})
require.NotNil(t, s)

err := s.Shutdown(context.Background())
Expand All @@ -74,7 +76,7 @@ func TestServer_Shutdown(t *testing.T) {
require.NotNil(t, appConfig)

// Sync a new server
s := NewServer(appConfig)
s := NewServer(appConfig, &p2p.Server{})
require.NotNil(t, s)

// Shutdown the server
Expand Down
2 changes: 1 addition & 1 deletion cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ func main() {
}

// Create a new (web) server
webServer := webserver.NewServer(_appConfig)
webServer := webserver.NewServer(_appConfig, p2pServer)

ctx, cancelFunc := context.WithCancel(context.Background())
// Start the p2p server
Expand Down

0 comments on commit becd9cf

Please sign in to comment.