Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add watchdog and monit #2329

Merged
merged 19 commits into from
Jul 8, 2024
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions examples/gno.land/p/demo/watchdog/gno.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module gno.land/p/demo/watchdog

require gno.land/p/demo/uassert v0.0.0-latest
39 changes: 39 additions & 0 deletions examples/gno.land/p/demo/watchdog/watchdog.gno
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package watchdog

import "time"

type Watchdog struct {
Duration time.Duration
lastUpdate time.Time
lastDown time.Time
}

func (w *Watchdog) Alive() {
now := time.Now()
if !w.IsAlive() {
w.lastDown = now
}
w.lastUpdate = now
}

func (w Watchdog) Status() string {
if w.IsAlive() {
return "OK"
}
return "KO"
zivkovicmilos marked this conversation as resolved.
Show resolved Hide resolved
}

func (w Watchdog) IsAlive() bool {
return time.Since(w.lastUpdate) < w.Duration
}

func (w Watchdog) UpSince() time.Time {
return w.lastDown
}

func (w Watchdog) DownSince() time.Time {
if !w.IsAlive() {
return w.lastUpdate
}
return time.Time{}
}
16 changes: 16 additions & 0 deletions examples/gno.land/p/demo/watchdog/watchdog_test.gno
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package watchdog

import (
"testing"
"time"

"gno.land/p/demo/uassert"
)

func TestPackage(t *testing.T) {
w := Watchdog{Duration: 5 * time.Minute}
uassert.False(t, w.IsAlive())
w.Alive()
uassert.True(t, w.IsAlive())
// XXX: add more tests when we'll be able to "skip time".
}
8 changes: 8 additions & 0 deletions examples/gno.land/r/gnoland/monit/gno.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
module monit
zivkovicmilos marked this conversation as resolved.
Show resolved Hide resolved

require (
gno.land/p/demo/ownable v0.0.0-latest
gno.land/p/demo/uassert v0.0.0-latest
gno.land/p/demo/ufmt v0.0.0-latest
gno.land/p/demo/watchdog v0.0.0-latest
)
59 changes: 59 additions & 0 deletions examples/gno.land/r/gnoland/monit/monit.gno
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// Package monit links a monitoring system with the chain in both directions.
//
// The agent will periodically call Incr() and verify that the value is always
// higher than the previously known one. The contract will store the last update
// time and use it to detect whether or not the monitoring agent is functioning
// correctly.
package monit

import (
"std"
"time"

"gno.land/p/demo/ownable"
"gno.land/p/demo/ufmt"
"gno.land/p/demo/watchdog"
)

var (
counter int
lastUpdate time.Time
lastCaller std.Address
wd = watchdog.Watchdog{Duration: 5 * time.Minute}
owner = ownable.New() // TODO: replace with -> ownable.NewWithAddress...
watchdogDuration = 5 * time.Minute
)

// Incr increments the counter and informs the watchdog that we're alive.
// This function can be called by anyone.
func Incr() int {
counter++
lastUpdate = time.Now()
lastCaller = std.PrevRealm().Addr()
wd.Alive()
return counter
}

// Reset resets the realm state.
// This function can only be called by the admin.
func Reset() {
if owner.CallerIsOwner() != nil { // TODO: replace with owner.AssertCallerIsOwner
panic("unauthorized")
}
counter = 0
lastCaller = std.PrevRealm().Addr()
lastUpdate = time.Now()
wd = watchdog.Watchdog{Duration: 5 * time.Minute}
}

func Render(_ string) string {
status := wd.Status()
return ufmt.Sprintf(
"counter=%d\nlast update=%s\nlast caller=%s\nstatus=%s",
counter, lastUpdate, lastCaller, status,
)
}

// TransferOwnership transfers ownership to a new owner. This is a proxy to
// ownable.Ownable.TransferOwnership.
func TransferOwnership(newOwner std.Address) { owner.TransferOwnership(newOwner) }
56 changes: 56 additions & 0 deletions examples/gno.land/r/gnoland/monit/monit_test.gno
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package monit

import (
"testing"

"gno.land/p/demo/uassert"
)

func TestPackage(t *testing.T) {
// initial state, watchdog is KO.
{
expected := `counter=0
last update=0001-01-01 00:00:00 +0000 UTC
last caller=
status=KO`
got := Render("")
uassert.Equal(t, expected, got)
}

// call Incr(), watchdog is OK.
Incr()
Incr()
Incr()
{
expected := `counter=3
last update=2009-02-13 23:31:30 +0000 UTC m=+1234567890.000000001
last caller=g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm
status=OK`
got := Render("")
uassert.Equal(t, expected, got)
}

/* XXX: improve tests once we've the missing std.TestSkipTime feature
// wait 1h, watchdog is KO.
use std.TestSkipTime(time.Hour)
{
expected := `counter=3
last update=2009-02-13 22:31:30 +0000 UTC m=+1234564290.000000001
last caller=g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm
status=KO`
got := Render("")
uassert.Equal(t, expected, got)
}

// call Incr(), watchdog is OK.
Incr()
{
expected := `counter=4
last update=2009-02-13 23:31:30 +0000 UTC m=+1234567890.000000001
last caller=g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm
status=OK`
got := Render("")
uassert.Equal(t, expected, got)
}
*/
}
Loading