mirror of
https://github.com/status-im/status-go-monitor.git
synced 2025-01-12 12:24:36 +00:00
use redux store for managing state of underlying data
Signed-off-by: Jakub Sokołowski <jakub@status.im>
This commit is contained in:
parent
51d299888d
commit
d48daf6481
10
client.go
10
client.go
@ -4,19 +4,19 @@ import (
|
||||
"github.com/ethereum/go-ethereum/rpc"
|
||||
)
|
||||
|
||||
type client struct {
|
||||
type StatusGoClient struct {
|
||||
rpcClient *rpc.Client
|
||||
}
|
||||
|
||||
func newClient(url string) (*client, error) {
|
||||
func newClient(url string) (*StatusGoClient, error) {
|
||||
rpcClient, err := rpc.Dial(url)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &client{rpcClient}, nil
|
||||
return &StatusGoClient{rpcClient}, nil
|
||||
}
|
||||
|
||||
func (c *client) getPeers() ([]Peer, error) {
|
||||
func (c *StatusGoClient) getPeers() ([]Peer, error) {
|
||||
peers := make([]Peer, 0)
|
||||
err := c.rpcClient.Call(&peers, "admin_peers")
|
||||
if err != nil {
|
||||
@ -25,7 +25,7 @@ func (c *client) getPeers() ([]Peer, error) {
|
||||
return peers, nil
|
||||
}
|
||||
|
||||
func (c *client) removePeer(enode string) (bool, error) {
|
||||
func (c *StatusGoClient) removePeer(enode string) (bool, error) {
|
||||
var rval bool
|
||||
err := c.rpcClient.Call(&rval, "admin_removePeer", enode)
|
||||
if err != nil {
|
||||
|
18
keys.go
18
keys.go
@ -24,15 +24,15 @@ func MoveCursor(mod int, vc *ViewController, g *gocui.Gui, v *gocui.View) error
|
||||
}
|
||||
cx, cy := v.Cursor()
|
||||
// get peers
|
||||
ps := vc.State.(*PeersState)
|
||||
peers := ps.list
|
||||
ps := vc.State.GetState()
|
||||
peers := ps.Peers
|
||||
// Don't go beyond available list of peers
|
||||
if cy+mod >= len(peers) || cy+mod < 0 {
|
||||
return nil
|
||||
}
|
||||
// update currently selected peer in the list
|
||||
ps.selected = &peers[cy+mod]
|
||||
writePeerDetails(g, ps.selected)
|
||||
current := &peers[cy+mod]
|
||||
vc.State.SetCurrent(current)
|
||||
if err := v.SetCursor(cx, cy+mod); err != nil {
|
||||
if mod == -1 {
|
||||
return nil
|
||||
@ -45,8 +45,8 @@ func MoveCursor(mod int, vc *ViewController, g *gocui.Gui, v *gocui.View) error
|
||||
return nil
|
||||
}
|
||||
|
||||
func (vc *ViewController) HandleDelete(g *gocui.Gui, v *gocui.View) error {
|
||||
ps := vc.State.(*PeersState)
|
||||
selectedPeer := ps.selected
|
||||
rval := ps.Remove(*selectedPeer)
|
||||
}
|
||||
//func (vc *ViewController) HandleDelete(g *gocui.Gui, v *gocui.View) error {
|
||||
// ps := vc.State.GetState()
|
||||
// currentPeer := ps.Current
|
||||
// return vc.State.Remove(vc.client, *currentPeer)
|
||||
//}
|
||||
|
17
loop.go
Normal file
17
loop.go
Normal file
@ -0,0 +1,17 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
func FetchLoop(client *StatusGoClient, state *State) {
|
||||
for {
|
||||
select {
|
||||
case <-threadDone:
|
||||
return
|
||||
default:
|
||||
state.Fetch(client)
|
||||
}
|
||||
<-time.After(interval * time.Second)
|
||||
}
|
||||
}
|
23
main.go
23
main.go
@ -1,6 +1,7 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
@ -16,19 +17,30 @@ const interval = 5
|
||||
var threadDone = make(chan struct{})
|
||||
|
||||
func main() {
|
||||
// Custom location for log messages
|
||||
clientLogFile, err := os.OpenFile("./app.log", os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644)
|
||||
if err != nil {
|
||||
log.Panicln(err)
|
||||
}
|
||||
log.SetOutput(clientLogFile)
|
||||
|
||||
// Core object for the Terminal UI
|
||||
g, err := gocui.NewGui(gocui.OutputNormal)
|
||||
if err != nil {
|
||||
log.Panicln(err)
|
||||
}
|
||||
defer g.Close()
|
||||
|
||||
peers := NewPeersState(host, port)
|
||||
// Client necessary for doing RPC calls to status-go
|
||||
url := fmt.Sprintf("http://%s:%d", host, port)
|
||||
client, err := newClient(url)
|
||||
if err != nil {
|
||||
log.Panicln(err)
|
||||
}
|
||||
|
||||
state := NewState()
|
||||
// Subscribe rendering method to state changes
|
||||
state.Store.Subscribe(GenRenderFunc(g, state))
|
||||
|
||||
mainView := &ViewController{
|
||||
Name: "main",
|
||||
@ -40,7 +52,7 @@ func main() {
|
||||
Current: true,
|
||||
SelFgColor: gocui.ColorBlack,
|
||||
SelBgColor: gocui.ColorGreen,
|
||||
State: peers,
|
||||
State: state,
|
||||
// corner positions
|
||||
TopLeft: func(mx, my int) (int, int) { return 0, 0 },
|
||||
BotRight: func(mx, my int) (int, int) { return mx - 1, my / 2 },
|
||||
@ -52,8 +64,8 @@ func main() {
|
||||
Binding{gocui.KeyArrowDown, gocui.ModNone, mainView.CursorDown},
|
||||
Binding{'k', gocui.ModNone, mainView.CursorUp},
|
||||
Binding{'j', gocui.ModNone, mainView.CursorDown},
|
||||
Binding{gocui.KeyDelete, gocui.ModNone, mainView.HandleDelete},
|
||||
Binding{'d', gocui.ModNone, mainView.HandleDelete},
|
||||
//Binding{gocui.KeyDelete, gocui.ModNone, mainView.HandleDelete},
|
||||
//Binding{'d', gocui.ModNone, mainView.HandleDelete},
|
||||
}
|
||||
infoView := &ViewController{
|
||||
Name: "info",
|
||||
@ -61,6 +73,7 @@ func main() {
|
||||
Placeholder: "Loading details...",
|
||||
Enabled: true,
|
||||
Wrap: true,
|
||||
State: state,
|
||||
// corner positions
|
||||
TopLeft: func(mx, my int) (int, int) { return 0, (my / 2) + 1 },
|
||||
BotRight: func(mx, my int) (int, int) { return mx - 1, my - 1 },
|
||||
@ -73,7 +86,7 @@ func main() {
|
||||
g.SetManagerFunc(vm.Layout)
|
||||
|
||||
// Start RPC calling routine
|
||||
go peers.FetchLoop(g)
|
||||
go FetchLoop(client, state)
|
||||
|
||||
if err := g.MainLoop(); err != nil && err != gocui.ErrQuit {
|
||||
log.Panicln(err)
|
||||
|
38
model.go
Normal file
38
model.go
Normal file
@ -0,0 +1,38 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/dannypsnl/redux/rematch"
|
||||
)
|
||||
|
||||
type PeersState struct {
|
||||
Peers []Peer
|
||||
Current *Peer
|
||||
}
|
||||
|
||||
type Model struct {
|
||||
rematch.Reducer
|
||||
State PeersState
|
||||
}
|
||||
|
||||
type Todo struct {
|
||||
Title string
|
||||
Done bool
|
||||
}
|
||||
|
||||
func (todo *Model) Current(state PeersState, peer *Peer) PeersState {
|
||||
return PeersState{
|
||||
Peers: state.Peers,
|
||||
Current: peer,
|
||||
}
|
||||
}
|
||||
|
||||
func (todo *Model) Update(state PeersState, peers []Peer) PeersState {
|
||||
current := state.Current
|
||||
if state.Current == nil {
|
||||
current = &peers[0]
|
||||
}
|
||||
return PeersState{
|
||||
Peers: peers,
|
||||
Current: current,
|
||||
}
|
||||
}
|
@ -2,54 +2,25 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/jroimartin/gocui"
|
||||
"log"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/jroimartin/gocui"
|
||||
)
|
||||
|
||||
type PeersState struct {
|
||||
c *client
|
||||
list []Peer
|
||||
selected *Peer
|
||||
func GenRenderFunc(g *gocui.Gui, state *State) func() {
|
||||
return func() {
|
||||
log.Printf("Rendering!")
|
||||
ps := state.GetState()
|
||||
renderPeers(g, ps.Peers)
|
||||
renderPeerInfo(g, ps.Current)
|
||||
}
|
||||
}
|
||||
|
||||
func NewPeersState(host string, port int) *PeersState {
|
||||
url := fmt.Sprintf("http://%s:%d", host, port)
|
||||
c, err := newClient(url)
|
||||
if err != nil {
|
||||
log.Panicln(err)
|
||||
}
|
||||
return &PeersState{c: c}
|
||||
}
|
||||
|
||||
func (p *PeersState) FetchLoop(g *gocui.Gui) {
|
||||
for {
|
||||
select {
|
||||
case <-threadDone:
|
||||
func renderPeers(g *gocui.Gui, peers []Peer) {
|
||||
if len(peers) == 0 {
|
||||
return
|
||||
default:
|
||||
peers := p.Fetch()
|
||||
writePeers(g, peers)
|
||||
writePeerDetails(g, p.selected)
|
||||
}
|
||||
<-time.After(interval * time.Second)
|
||||
}
|
||||
}
|
||||
|
||||
func (p *PeersState) Fetch() []Peer {
|
||||
peers, err := p.c.getPeers()
|
||||
if err != nil {
|
||||
log.Panicln(err)
|
||||
}
|
||||
p.list = peers
|
||||
if p.selected == nil {
|
||||
p.selected = &peers[0]
|
||||
}
|
||||
return peers
|
||||
}
|
||||
|
||||
func writePeers(g *gocui.Gui, peers []Peer) {
|
||||
g.Update(func(g *gocui.Gui) error {
|
||||
v, err := g.View("main")
|
||||
if err != nil {
|
||||
@ -64,15 +35,10 @@ func writePeers(g *gocui.Gui, peers []Peer) {
|
||||
})
|
||||
}
|
||||
|
||||
func (p *PeersState) Remove(peer Peer) error {
|
||||
success, err := p.c.removePeer(peer.Enode)
|
||||
if err != nil || success != true {
|
||||
log.Panicln(err)
|
||||
func renderPeerInfo(g *gocui.Gui, peer *Peer) {
|
||||
if peer == nil {
|
||||
return
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func writePeerDetails(g *gocui.Gui, peer *Peer) {
|
||||
g.Update(func(g *gocui.Gui) error {
|
||||
v, err := g.View("info")
|
||||
if err != nil {
|
67
state.go
Normal file
67
state.go
Normal file
@ -0,0 +1,67 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
_ "github.com/dannypsnl/redux"
|
||||
"github.com/dannypsnl/redux/rematch"
|
||||
"github.com/dannypsnl/redux/store"
|
||||
)
|
||||
|
||||
type State struct {
|
||||
Reducer *Model
|
||||
Store *store.Store
|
||||
updatePeers *rematch.Action
|
||||
setCurrent *rematch.Action
|
||||
}
|
||||
|
||||
func NewState() *State {
|
||||
// Generate the reducer from our model
|
||||
Reducer := &Model{
|
||||
State: PeersState{
|
||||
Peers: make([]Peer, 0),
|
||||
Current: nil,
|
||||
},
|
||||
}
|
||||
// Instantiate the redux state from the reducer
|
||||
return &State{
|
||||
Reducer: Reducer,
|
||||
// Define the store
|
||||
Store: store.New(Reducer),
|
||||
// Define available reducers for the store
|
||||
updatePeers: Reducer.Action(Reducer.Update),
|
||||
setCurrent: Reducer.Action(Reducer.Current),
|
||||
}
|
||||
}
|
||||
|
||||
// Helpers for shorter calls
|
||||
func (s *State) Update(peers []Peer) {
|
||||
s.Store.Dispatch(s.updatePeers.With(peers))
|
||||
}
|
||||
func (s *State) SetCurrent(peer *Peer) {
|
||||
s.Store.Dispatch(s.setCurrent.With(peer))
|
||||
}
|
||||
func (s *State) GetState() PeersState {
|
||||
return s.Store.StateOf(s.Reducer).(PeersState)
|
||||
}
|
||||
func (s *State) Fetch(client *StatusGoClient) {
|
||||
peers, err := client.getPeers()
|
||||
if err != nil {
|
||||
log.Panicln(err)
|
||||
}
|
||||
log.Printf("peers: %v\n", peers)
|
||||
ps := s.GetState()
|
||||
s.Update(peers)
|
||||
if ps.Current == nil {
|
||||
s.SetCurrent(&peers[0])
|
||||
}
|
||||
}
|
||||
|
||||
func (s *State) Remove(client *StatusGoClient, peer Peer) error {
|
||||
success, err := client.removePeer(peer.Enode)
|
||||
if err != nil || success != true {
|
||||
log.Panicln(err)
|
||||
}
|
||||
s.Fetch(client)
|
||||
return nil
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user