Skip to content

Commit

Permalink
fix: cleanup events reload
Browse files Browse the repository at this point in the history
Signed-off-by: gfanton <[email protected]>
  • Loading branch information
gfanton committed Jan 25, 2024
1 parent b180849 commit 9f38998
Show file tree
Hide file tree
Showing 8 changed files with 199 additions and 168 deletions.
2 changes: 1 addition & 1 deletion contribs/gnodev/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ replace github.com/gnolang/gno => ../..
require (
github.com/fsnotify/fsnotify v1.7.0
github.com/gnolang/gno v0.0.0-00010101000000-000000000000
golang.org/x/term v0.16.0
github.com/gorilla/websocket v1.5.1
golang.org/x/term v0.16.0
)

require (
Expand Down
13 changes: 2 additions & 11 deletions contribs/gnodev/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -304,16 +304,7 @@ func setupRawTerm(io commands.IO) (rt *rawterm.RawTerm, restore func() error, er

// correctly format output for terminal
io.SetOut(commands.WriteNopCloser(rt))

restoreWithRecover := func() error {
if r := recover(); r != nil {
rt.Taskf("panic", "%v\n", r)
}

return restore()
}

return rt, restoreWithRecover, nil
return rt, restore, nil
}

// setupDevNode initializes and returns a new DevNode.
Expand All @@ -322,7 +313,7 @@ func setupDevNode(ctx context.Context, emitter events.Emitter, rt *rawterm.RawTe

logger := tmlog.NewTMLogger(nodeOut)
logger.SetLevel(tmlog.LevelError)
return gnodev.NewDevNode(ctx, emitter, logger, pkgspath)
return gnodev.NewDevNode(ctx, logger, emitter, pkgspath)
}

// setupGnowebServer initializes and starts the Gnoweb server.
Expand Down
156 changes: 80 additions & 76 deletions contribs/gnodev/pkg/dev/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
"github.com/gnolang/gno/tm2/pkg/bft/node"
bft "github.com/gnolang/gno/tm2/pkg/bft/types"
"github.com/gnolang/gno/tm2/pkg/crypto"
tm2events "github.com/gnolang/gno/tm2/pkg/events"
"github.com/gnolang/gno/tm2/pkg/log"
"github.com/gnolang/gno/tm2/pkg/std"
//backup "github.com/gnolang/tx-archive/backup/client"
Expand All @@ -28,9 +29,9 @@ const gnoDevChainID = "tendermint_test" // XXX: this is hardcoded and cannot be
type Node struct {
*node.Node

events events.Emitter
logger log.Logger
pkgs PkgsMap // path -> pkg
emitter events.Emitter
logger log.Logger
pkgs PkgsMap // path -> pkg
}

var (
Expand All @@ -44,7 +45,7 @@ var (
}
)

func NewDevNode(ctx context.Context, emitter events.Emitter, logger log.Logger, pkgslist []string) (*Node, error) {
func NewDevNode(ctx context.Context, logger log.Logger, emitter events.Emitter, pkgslist []string) (*Node, error) {
mpkgs, err := newPkgsMap(pkgslist)
if err != nil {
return nil, fmt.Errorf("unable map pkgs list: %w", err)
Expand All @@ -61,27 +62,16 @@ func NewDevNode(ctx context.Context, emitter events.Emitter, logger log.Logger,
Txs: txs,
}

node, err := newNode(logger, genesis)
node, err := newNode(ctx, logger, emitter, genesis)
if err != nil {
return nil, fmt.Errorf("unable to create the node: %w", err)
}

if err := node.Start(); err != nil {
return nil, fmt.Errorf("unable to start node: %w", err)
}

// Wait for readiness
select {
case <-gnoland.GetNodeReadiness(node): // ok
case <-ctx.Done():
return nil, ctx.Err()
}

return &Node{
events: emitter,
Node: node,
pkgs: mpkgs,
logger: logger,
emitter: emitter,
Node: node,
pkgs: mpkgs,
logger: logger,
}, nil
}

Expand Down Expand Up @@ -146,11 +136,13 @@ func (d *Node) Reset(ctx context.Context) error {
}

// Reset the node with the new genesis state.
if err := d.reset(ctx, genesis); err != nil {
node, err := newNode(ctx, d.logger, d.emitter, genesis)
if err != nil {
return fmt.Errorf("unable to reset the node: %w", err)
}

d.events.Emit(events.NewEventReset())
d.Node = node
d.emitter.Emit(events.NewEventReset())
return nil
}

Expand Down Expand Up @@ -199,7 +191,8 @@ func (d *Node) Reload(ctx context.Context) error {
}

// Reset the node with the new genesis state.
if err := d.reset(ctx, genesis); err != nil {
node, err := newNode(ctx, d.logger, d.emitter, genesis)
if err != nil {
return fmt.Errorf("unable to reset the node: %w", err)
}

Expand All @@ -210,66 +203,19 @@ func (d *Node) Reload(ctx context.Context) error {
}

if err := d.SendTransaction(&tx); err != nil {
return fmt.Errorf("unable to send transaction: %w", err)
d.logger.Error("unable to send transaction", "error", err)
}
}

if err != nil {
return fmt.Errorf("unable to reload the node: %w", err)
}

d.events.Emit(events.NewEventReload())
d.Node = node
d.emitter.Emit(events.NewEventReload())
return nil
}

func (d *Node) reset(ctx context.Context, genesis gnoland.GnoGenesisState) error {
var err error

// recoverError handles panics and converts them to errors.
recoverError := func() {
if r := recover(); r != nil {
panicErr, ok := r.(error)
if !ok {
panic(r) // Re-panic if not an error.
}

err = panicErr
}
}

createNode := func() {
defer recoverError()

node, nodeErr := newNode(d.logger, genesis)
if nodeErr != nil {
err = fmt.Errorf("unable to create node: %w", nodeErr)
return
}

if startErr := node.Start(); startErr != nil {
err = fmt.Errorf("unable to start the node: %w", startErr)
return
}

d.Node = node
}

// Execute node creation and handle any errors.
createNode()
if err != nil {
return err
}

// Wait for the node to be ready
select {
case <-d.GetNodeReadiness(): // Ok
case <-ctx.Done():
return ctx.Err()
}

return err
}

// GetBlockTransactions returns the transactions contained
// within the specified block, if any
func (d *Node) GetBlockTransactions(blockNum uint64) ([]std.Tx, error) {
Expand Down Expand Up @@ -416,13 +362,71 @@ func (pm PkgsMap) Load(creator bft.Address, fee std.Fee, deposit std.Coins) ([]s
return txs, nil
}

func newNode(logger log.Logger, genesis gnoland.GnoGenesisState) (*node.Node, error) {
func newNode(ctx context.Context, logger log.Logger, emitter events.Emitter, genesis gnoland.GnoGenesisState) (*node.Node, error) {
rootdir := gnoenv.RootDir()

// Setup node config
nodeConfig := gnoland.NewDefaultInMemoryNodeConfig(rootdir)
nodeConfig.SkipFailingGenesisTxs = true
nodeConfig.TMConfig.Consensus.SkipTimeoutCommit = false // avoid time drifting, see issue #1507

nodeConfig.Genesis.AppState = genesis
return gnoland.NewInMemoryNode(logger, nodeConfig)

// Generate a new node
var err error

// recoverError handles panics and converts them to errors.
recoverError := func() {
if r := recover(); r != nil {
panicErr, ok := r.(error)
if !ok {
panic(r) // Re-panic if not an error.
}

err = panicErr
}
}

createNode := func() *node.Node {
defer recoverError()

node, nodeErr := gnoland.NewInMemoryNode(logger, nodeConfig)
if nodeErr != nil {
err = fmt.Errorf("unable to create node: %w", nodeErr)
return nil
}

node.EventSwitch().AddListener("dev-emitter", func(evt tm2events.Event) {
switch data := evt.(type) {
case bft.EventTx:
evtTx, err := events.NewTxEventResult(data.Result)
if err != nil {
logger.Error("unable to create an event from tx result", "error", err)
return
}

emitter.Emit(evtTx)
}
})

if startErr := node.Start(); startErr != nil {
err = fmt.Errorf("unable to start the node: %w", startErr)
return nil
}

return node
}

// Execute node creation and handle any errors.
node := createNode()
if err != nil {
return nil, err
}

// Wait for the node to be ready
select {
case <-gnoland.GetNodeReadiness(node): // Ok
return node, nil
case <-ctx.Done():
return nil, ctx.Err()
}
}
47 changes: 41 additions & 6 deletions contribs/gnodev/pkg/events/events.go
Original file line number Diff line number Diff line change
@@ -1,16 +1,26 @@
package events

import (
"fmt"

"github.com/gnolang/gno/tm2/pkg/amino"
abci "github.com/gnolang/gno/tm2/pkg/bft/abci/types"
"github.com/gnolang/gno/tm2/pkg/bft/types"
"github.com/gnolang/gno/tm2/pkg/std"
)

type EventType string

const (
EvtReload EventType = "NODE_RELOAD"
EvtReset EventType = "NODE_RESET"
EvtPackagesUpdate EventType = "PACKAGES_UPDATE"
EvtReload EventType = "EVENT_NODE_RELOAD"
EvtReset EventType = "EVENT_NODE_RESET"
EvtPackagesUpdate EventType = "EVENT_PACKAGES_UPDATE"
EvtTxResult EventType = "EVENT_TX_RESULT"
)

type Event struct {
Type EventType `json:"type"`
Data interface{} `json:"data"`
Type EventType `json:"type"`
Data any `json:"data"`
}

// Event Reload
Expand All @@ -30,7 +40,7 @@ type EventReset struct{}

func NewEventReset() *Event {
return &Event{
Type: EvtReload,
Type: EvtReset,
Data: &EventReset{},
}
}
Expand All @@ -54,3 +64,28 @@ func NewPackagesUpdateEvent(pkgs []PackageUpdate) *Event {
},
}
}

// Event Tx is an alias to TxResult

type EventTxResult struct {
Height int64 `json:"height"`
Index uint32 `json:"index"`
Tx std.Tx `json:"tx"`
Response abci.ResponseDeliverTx `json:"response"`
}

func NewTxEventResult(result types.TxResult) (*Event, error) {
evt := &EventTxResult{
Height: result.Height,
Index: result.Index,
Response: result.Response,
}
if err := amino.Unmarshal(result.Tx, &evt.Tx); err != nil {
return nil, fmt.Errorf("unable unmarshal tx: %w", err)
}

return &Event{
Type: EvtTxResult,
Data: evt,
}, nil
}
Loading

0 comments on commit 9f38998

Please sign in to comment.