Initial commit
This commit is contained in:
commit
7a8c56631d
|
@ -0,0 +1,2 @@
|
||||||
|
p2p-health-bot
|
||||||
|
p2p-health-bot_linux
|
|
@ -0,0 +1,45 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"log"
|
||||||
|
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
|
"github.com/status-im/status-go-sdk"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
var (
|
||||||
|
name = flag.String("name", "randomstring", "Public chat name used for this health bots")
|
||||||
|
interval = flag.Duration("interval", 5*time.Second, "Interval for health check")
|
||||||
|
rpcHost = flag.String("rpc", "http://localhost:8545", "Host:port to statusd's RPC endpoint")
|
||||||
|
isSender = flag.Bool("send", true, "Select bot role, sender or responder")
|
||||||
|
)
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
|
rpcClient, err := rpc.Dial(*rpcHost)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
client := sdk.New(rpcClient)
|
||||||
|
|
||||||
|
a, err := client.SignupAndLogin("password")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
ch, err := a.JoinPublicChannel(*name)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if *isSender {
|
||||||
|
startSender(ch, *interval)
|
||||||
|
} else {
|
||||||
|
startReceiver(ch)
|
||||||
|
select {}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Msg represents health check message.
|
||||||
|
type Msg string
|
||||||
|
|
||||||
|
// NewRequestMsg constructs new request health message.
|
||||||
|
func NewRequestMsg(counter int) Msg {
|
||||||
|
return Msg(fmt.Sprintf("Health Check Request|%d", counter))
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewResponseMsg constructs new request health message.
|
||||||
|
func NewResponseMsg(counter int) Msg {
|
||||||
|
return Msg(fmt.Sprintf("Health Check Response|%d", counter))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Counter returns counter value from health message.
|
||||||
|
func (m *Msg) Counter() (int, error) {
|
||||||
|
fields := strings.Split(string(*m), "|")
|
||||||
|
if len(fields) != 2 {
|
||||||
|
return 0, fmt.Errorf("wrong length: %s", *m)
|
||||||
|
}
|
||||||
|
c, err := strconv.ParseInt(fields[1], 10, 0)
|
||||||
|
if err != nil {
|
||||||
|
return 0, fmt.Errorf("wrong counter value: %s", err)
|
||||||
|
}
|
||||||
|
return int(c), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Msg) IsRequest() bool {
|
||||||
|
return strings.Contains(string(*m), "Health Check Request")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Msg) IsResponse() bool {
|
||||||
|
return strings.Contains(string(*m), "Health Check Response")
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
|
||||||
|
"github.com/status-im/status-go-sdk"
|
||||||
|
)
|
||||||
|
|
||||||
|
func startReceiver(ch *sdk.Channel) {
|
||||||
|
if _, err := ch.Subscribe(func(m *sdk.Msg) {
|
||||||
|
log.Println("[DEBUG] Got message: %v", m)
|
||||||
|
rawmsg, ok := m.Properties.(*sdk.PublishMsg)
|
||||||
|
if !ok {
|
||||||
|
log.Println("[ERROR] Wrong message props type received: %T", m.Properties)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
msg := Msg(rawmsg.Text)
|
||||||
|
if msg.IsRequest() {
|
||||||
|
counter, err := msg.Counter()
|
||||||
|
if err != nil {
|
||||||
|
log.Println("[ERROR] Can't extract counter: %v", err)
|
||||||
|
}
|
||||||
|
go func(counter int) {
|
||||||
|
var body = NewResponseMsg(counter)
|
||||||
|
if err := ch.Publish(string(body)); err != nil {
|
||||||
|
log.Println("[ERROR] Can't send response: %v", err)
|
||||||
|
}
|
||||||
|
}(counter)
|
||||||
|
}
|
||||||
|
}); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,65 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/status-im/status-go-sdk"
|
||||||
|
)
|
||||||
|
|
||||||
|
func startSender(ch *sdk.Channel, interval time.Duration) {
|
||||||
|
var (
|
||||||
|
counter int
|
||||||
|
ticker = time.NewTicker(interval)
|
||||||
|
statsTicker = time.NewTicker(10 * time.Second)
|
||||||
|
pending = make(map[int]time.Time)
|
||||||
|
recvCh = make(chan Msg, 1000)
|
||||||
|
)
|
||||||
|
|
||||||
|
if _, err := ch.Subscribe(func(m *sdk.Msg) {
|
||||||
|
rawmsg, ok := m.Properties.(*sdk.PublishMsg)
|
||||||
|
if !ok {
|
||||||
|
log.Println("Wrong message props type received: %T", m.Properties)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
msg := Msg(rawmsg.Text)
|
||||||
|
if msg.IsResponse() {
|
||||||
|
recvCh <- msg
|
||||||
|
}
|
||||||
|
}); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
stats := NewStats()
|
||||||
|
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-ticker.C:
|
||||||
|
var body = NewRequestMsg(counter)
|
||||||
|
err := ch.Publish(string(body))
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("[ERROR] Failed to send health message: %s", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
pending[counter] = time.Now()
|
||||||
|
counter++
|
||||||
|
stats.AddSent()
|
||||||
|
case msg := <-recvCh:
|
||||||
|
c, err := msg.Counter()
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("[ERROR] Failed to parse health message: %s", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
start, ok := pending[c]
|
||||||
|
if !ok {
|
||||||
|
log.Printf("[ERROR] Received response for counter never sent (another sender bot running?): %s", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
delete(pending, c)
|
||||||
|
dur := time.Since(start)
|
||||||
|
stats.AddRountrip(dur)
|
||||||
|
case <-statsTicker.C:
|
||||||
|
stats.Print()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Stats represents messages' statistics.
|
||||||
|
type Stats struct {
|
||||||
|
mx sync.RWMutex
|
||||||
|
sent int
|
||||||
|
received int
|
||||||
|
delays []time.Duration
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewStats returns new empty Stats object.
|
||||||
|
func NewStats() *Stats {
|
||||||
|
return &Stats{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddSent adds information about sent messages.
|
||||||
|
func (s *Stats) AddSent() {
|
||||||
|
s.mx.Lock()
|
||||||
|
defer s.mx.Unlock()
|
||||||
|
s.sent++
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddRoundtrip adds information about successful message roundtrip.
|
||||||
|
func (s *Stats) AddRountrip(d time.Duration) {
|
||||||
|
s.mx.Lock()
|
||||||
|
defer s.mx.Unlock()
|
||||||
|
s.received++
|
||||||
|
s.delays = append(s.delays, d)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Print dumps stats to the console.
|
||||||
|
func (s *Stats) Print() {
|
||||||
|
s.mx.RLock()
|
||||||
|
defer s.mx.RUnlock()
|
||||||
|
fmt.Println("-------------------------")
|
||||||
|
fmt.Println("Time:", time.Now())
|
||||||
|
fmt.Println("Sent:", s.sent)
|
||||||
|
fmt.Println("Received:", s.received)
|
||||||
|
fmt.Println("Delays:", s.delays)
|
||||||
|
fmt.Println("-------------------------")
|
||||||
|
}
|
Loading…
Reference in New Issue