mirror of
https://github.com/tendermint/tendermint.git
synced 2026-01-10 06:57:24 +00:00
new pubsub package
comment out failing consensus tests for now rewrite rpc httpclient to use new pubsub package import pubsub as tmpubsub, query as tmquery make event IDs constants EventKey -> EventTypeKey rename EventsPubsub to PubSub mempool does not use pubsub rename eventsSub to pubsub new subscribe API fix channel size issues and consensus tests bugs refactor rpc client add missing discardFromChan method add mutex rename pubsub to eventBus remove IsRunning from WSRPCConnection interface (not needed) add a comment in broadcastNewRoundStepsAndVotes rename registerEventCallbacks to broadcastNewRoundStepsAndVotes See https://dave.cheney.net/2014/03/19/channel-axioms stop eventBuses after reactor tests remove unnecessary Unsubscribe return subscribe helper function move discardFromChan to where it is used subscribe now returns an err this gives us ability to refuse to subscribe if pubsub is at its max capacity. use context for control overflow cache queries handle err when subscribing in replay_test rename testClientID to testSubscriber extract var set channel buffer capacity to 1 in replay_file fix byzantine_test unsubscribe from single event, not all events refactor httpclient to return events to appropriate channels return failing testReplayCrashBeforeWriteVote test fix TestValidatorSetChanges refactor code a bit fix testReplayCrashBeforeWriteVote add comment fix TestValidatorSetChanges fixes from Bucky's review update comment [ci skip] test TxEventBuffer update changelog fix TestValidatorSetChanges (2nd attempt) only do wg.Done when no errors benchmark event bus create pubsub server inside NewEventBus only expose config params (later if needed) set buffer capacity to 0 so we are not testing cache new tx event format: key = "Tx" plus a tag {"tx.hash": XYZ} This should allow to subscribe to all transactions! or a specific one using a query: "tm.events.type = Tx and tx.hash = '013ABF99434...'" use TimeoutCommit instead of afterPublishEventNewBlockTimeout TimeoutCommit is the time a node waits after committing a block, before it goes into the next height. So it will finish everything from the last block, but then wait a bit. The idea is this gives it time to hear more votes from other validators, to strengthen the commit it includes in the next block. But it also gives it time to hear about new transactions. waitForBlockWithUpdatedVals rewrite WAL crash tests Task: test that we can recover from any WAL crash. Solution: the old tests were relying on event hub being run in the same thread (we were injecting the private validator's last signature). when considering a rewrite, we considered two possible solutions: write a "fuzzy" testing system where WAL is crashing upon receiving a new message, or inject failures and trigger them in tests using something like https://github.com/coreos/gofail. remove sleep no cs.Lock around wal.Save test different cases (empty block, non-empty block, ...) comments add comments test 4 cases: empty block, non-empty block, non-empty block with smaller part size, many blocks fixes as per Bucky's last review reset subscriptions on UnsubscribeAll use a simple counter to track message for which we panicked also, set a smaller part size for all test cases
This commit is contained in:
46
types/event_buffer.go
Normal file
46
types/event_buffer.go
Normal file
@@ -0,0 +1,46 @@
|
||||
package types
|
||||
|
||||
// Interface assertions
|
||||
var _ TxEventPublisher = (*TxEventBuffer)(nil)
|
||||
|
||||
// TxEventBuffer is a buffer of events, which uses a slice to temporary store
|
||||
// events.
|
||||
type TxEventBuffer struct {
|
||||
next TxEventPublisher
|
||||
capacity int
|
||||
events []EventDataTx
|
||||
}
|
||||
|
||||
// NewTxEventBuffer accepts an EventBus and returns a new buffer with the given
|
||||
// capacity.
|
||||
func NewTxEventBuffer(next TxEventPublisher, capacity int) *TxEventBuffer {
|
||||
return &TxEventBuffer{
|
||||
next: next,
|
||||
capacity: capacity,
|
||||
events: make([]EventDataTx, 0, capacity),
|
||||
}
|
||||
}
|
||||
|
||||
// Len returns the number of events cached.
|
||||
func (b TxEventBuffer) Len() int {
|
||||
return len(b.events)
|
||||
}
|
||||
|
||||
// PublishEventTx buffers an event to be fired upon finality.
|
||||
func (b *TxEventBuffer) PublishEventTx(e EventDataTx) error {
|
||||
b.events = append(b.events, e)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Flush publishes events by running next.PublishWithTags on all cached events.
|
||||
// Blocks. Clears cached events.
|
||||
func (b *TxEventBuffer) Flush() error {
|
||||
for _, e := range b.events {
|
||||
err := b.next.PublishEventTx(e)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
b.events = make([]EventDataTx, 0, b.capacity)
|
||||
return nil
|
||||
}
|
||||
21
types/event_buffer_test.go
Normal file
21
types/event_buffer_test.go
Normal file
@@ -0,0 +1,21 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
type eventBusMock struct{}
|
||||
|
||||
func (eventBusMock) PublishEventTx(e EventDataTx) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestEventBuffer(t *testing.T) {
|
||||
b := NewTxEventBuffer(eventBusMock{}, 1)
|
||||
b.PublishEventTx(EventDataTx{})
|
||||
assert.Equal(t, 1, b.Len())
|
||||
b.Flush()
|
||||
assert.Equal(t, 0, b.Len())
|
||||
}
|
||||
133
types/event_bus.go
Normal file
133
types/event_bus.go
Normal file
@@ -0,0 +1,133 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
cmn "github.com/tendermint/tmlibs/common"
|
||||
"github.com/tendermint/tmlibs/log"
|
||||
tmpubsub "github.com/tendermint/tmlibs/pubsub"
|
||||
)
|
||||
|
||||
const defaultCapacity = 1000
|
||||
|
||||
// EventBus is a common bus for all events going through the system. All calls
|
||||
// are proxied to underlying pubsub server. All events must be published using
|
||||
// EventBus to ensure correct data types.
|
||||
type EventBus struct {
|
||||
cmn.BaseService
|
||||
pubsub *tmpubsub.Server
|
||||
}
|
||||
|
||||
// NewEventBus returns a new event bus.
|
||||
func NewEventBus() *EventBus {
|
||||
return NewEventBusWithBufferCapacity(defaultCapacity)
|
||||
}
|
||||
|
||||
// NewEventBusWithBufferCapacity returns a new event bus with the given buffer capacity.
|
||||
func NewEventBusWithBufferCapacity(cap int) *EventBus {
|
||||
// capacity could be exposed later if needed
|
||||
pubsub := tmpubsub.NewServer(tmpubsub.BufferCapacity(cap))
|
||||
b := &EventBus{pubsub: pubsub}
|
||||
b.BaseService = *cmn.NewBaseService(nil, "EventBus", b)
|
||||
return b
|
||||
}
|
||||
|
||||
func (b *EventBus) SetLogger(l log.Logger) {
|
||||
b.BaseService.SetLogger(l)
|
||||
b.pubsub.SetLogger(l.With("module", "pubsub"))
|
||||
}
|
||||
|
||||
func (b *EventBus) OnStart() error {
|
||||
return b.pubsub.OnStart()
|
||||
}
|
||||
|
||||
func (b *EventBus) OnStop() {
|
||||
b.pubsub.OnStop()
|
||||
}
|
||||
|
||||
func (b *EventBus) Subscribe(ctx context.Context, subscriber string, query tmpubsub.Query, out chan<- interface{}) error {
|
||||
return b.pubsub.Subscribe(ctx, subscriber, query, out)
|
||||
}
|
||||
|
||||
func (b *EventBus) Unsubscribe(ctx context.Context, subscriber string, query tmpubsub.Query) error {
|
||||
return b.pubsub.Unsubscribe(ctx, subscriber, query)
|
||||
}
|
||||
|
||||
func (b *EventBus) UnsubscribeAll(ctx context.Context, subscriber string) error {
|
||||
return b.pubsub.UnsubscribeAll(ctx, subscriber)
|
||||
}
|
||||
|
||||
func (b *EventBus) publish(eventType string, eventData TMEventData) error {
|
||||
if b.pubsub != nil {
|
||||
// no explicit deadline for publishing events
|
||||
ctx := context.Background()
|
||||
b.pubsub.PublishWithTags(ctx, eventData, map[string]interface{}{EventTypeKey: eventType})
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
//--- block, tx, and vote events
|
||||
|
||||
func (b *EventBus) PublishEventNewBlock(block EventDataNewBlock) error {
|
||||
return b.publish(EventNewBlock, TMEventData{block})
|
||||
}
|
||||
|
||||
func (b *EventBus) PublishEventNewBlockHeader(header EventDataNewBlockHeader) error {
|
||||
return b.publish(EventNewBlockHeader, TMEventData{header})
|
||||
}
|
||||
|
||||
func (b *EventBus) PublishEventVote(vote EventDataVote) error {
|
||||
return b.publish(EventVote, TMEventData{vote})
|
||||
}
|
||||
|
||||
func (b *EventBus) PublishEventTx(tx EventDataTx) error {
|
||||
if b.pubsub != nil {
|
||||
// no explicit deadline for publishing events
|
||||
ctx := context.Background()
|
||||
b.pubsub.PublishWithTags(ctx, TMEventData{tx}, map[string]interface{}{EventTypeKey: EventTx, TxHashKey: fmt.Sprintf("%X", tx.Tx.Hash())})
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
//--- EventDataRoundState events
|
||||
|
||||
func (b *EventBus) PublishEventNewRoundStep(rs EventDataRoundState) error {
|
||||
return b.publish(EventNewRoundStep, TMEventData{rs})
|
||||
}
|
||||
|
||||
func (b *EventBus) PublishEventTimeoutPropose(rs EventDataRoundState) error {
|
||||
return b.publish(EventTimeoutPropose, TMEventData{rs})
|
||||
}
|
||||
|
||||
func (b *EventBus) PublishEventTimeoutWait(rs EventDataRoundState) error {
|
||||
return b.publish(EventTimeoutWait, TMEventData{rs})
|
||||
}
|
||||
|
||||
func (b *EventBus) PublishEventNewRound(rs EventDataRoundState) error {
|
||||
return b.publish(EventNewRound, TMEventData{rs})
|
||||
}
|
||||
|
||||
func (b *EventBus) PublishEventCompleteProposal(rs EventDataRoundState) error {
|
||||
return b.publish(EventCompleteProposal, TMEventData{rs})
|
||||
}
|
||||
|
||||
func (b *EventBus) PublishEventPolka(rs EventDataRoundState) error {
|
||||
return b.publish(EventPolka, TMEventData{rs})
|
||||
}
|
||||
|
||||
func (b *EventBus) PublishEventUnlock(rs EventDataRoundState) error {
|
||||
return b.publish(EventUnlock, TMEventData{rs})
|
||||
}
|
||||
|
||||
func (b *EventBus) PublishEventRelock(rs EventDataRoundState) error {
|
||||
return b.publish(EventRelock, TMEventData{rs})
|
||||
}
|
||||
|
||||
func (b *EventBus) PublishEventLock(rs EventDataRoundState) error {
|
||||
return b.publish(EventLock, TMEventData{rs})
|
||||
}
|
||||
|
||||
func (b *EventBus) PublishEventProposalHeartbeat(ph EventDataProposalHeartbeat) error {
|
||||
return b.publish(EventProposalHeartbeat, TMEventData{ph})
|
||||
}
|
||||
122
types/event_bus_test.go
Normal file
122
types/event_bus_test.go
Normal file
@@ -0,0 +1,122 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
tmpubsub "github.com/tendermint/tmlibs/pubsub"
|
||||
)
|
||||
|
||||
func BenchmarkEventBus(b *testing.B) {
|
||||
benchmarks := []struct {
|
||||
name string
|
||||
numClients int
|
||||
randQueries bool
|
||||
randEvents bool
|
||||
}{
|
||||
{"10Clients1Query1Event", 10, false, false},
|
||||
{"100Clients", 100, false, false},
|
||||
{"1000Clients", 1000, false, false},
|
||||
|
||||
{"10ClientsRandQueries1Event", 10, true, false},
|
||||
{"100Clients", 100, true, false},
|
||||
{"1000Clients", 1000, true, false},
|
||||
|
||||
{"10ClientsRandQueriesRandEvents", 10, true, true},
|
||||
{"100Clients", 100, true, true},
|
||||
{"1000Clients", 1000, true, true},
|
||||
|
||||
{"10Clients1QueryRandEvents", 10, false, true},
|
||||
{"100Clients", 100, false, true},
|
||||
{"1000Clients", 1000, false, true},
|
||||
}
|
||||
|
||||
for _, bm := range benchmarks {
|
||||
b.Run(bm.name, func(b *testing.B) {
|
||||
benchmarkEventBus(bm.numClients, bm.randQueries, bm.randEvents, b)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func benchmarkEventBus(numClients int, randQueries bool, randEvents bool, b *testing.B) {
|
||||
// for random* functions
|
||||
rand.Seed(time.Now().Unix())
|
||||
|
||||
eventBus := NewEventBusWithBufferCapacity(0) // set buffer capacity to 0 so we are not testing cache
|
||||
eventBus.Start()
|
||||
defer eventBus.Stop()
|
||||
|
||||
ctx := context.Background()
|
||||
q := EventQueryNewBlock
|
||||
|
||||
for i := 0; i < numClients; i++ {
|
||||
ch := make(chan interface{})
|
||||
go func() {
|
||||
for range ch {
|
||||
}
|
||||
}()
|
||||
if randQueries {
|
||||
q = randQuery()
|
||||
}
|
||||
eventBus.Subscribe(ctx, fmt.Sprintf("client-%d", i), q, ch)
|
||||
}
|
||||
|
||||
eventType := EventNewBlock
|
||||
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
if randEvents {
|
||||
eventType = randEvent()
|
||||
}
|
||||
|
||||
eventBus.publish(eventType, TMEventData{"Gamora"})
|
||||
}
|
||||
}
|
||||
|
||||
var events = []string{EventBond,
|
||||
EventUnbond,
|
||||
EventRebond,
|
||||
EventDupeout,
|
||||
EventFork,
|
||||
EventNewBlock,
|
||||
EventNewBlockHeader,
|
||||
EventNewRound,
|
||||
EventNewRoundStep,
|
||||
EventTimeoutPropose,
|
||||
EventCompleteProposal,
|
||||
EventPolka,
|
||||
EventUnlock,
|
||||
EventLock,
|
||||
EventRelock,
|
||||
EventTimeoutWait,
|
||||
EventVote}
|
||||
|
||||
func randEvent() string {
|
||||
return events[rand.Intn(len(events))]
|
||||
}
|
||||
|
||||
var queries = []tmpubsub.Query{EventQueryBond,
|
||||
EventQueryUnbond,
|
||||
EventQueryRebond,
|
||||
EventQueryDupeout,
|
||||
EventQueryFork,
|
||||
EventQueryNewBlock,
|
||||
EventQueryNewBlockHeader,
|
||||
EventQueryNewRound,
|
||||
EventQueryNewRoundStep,
|
||||
EventQueryTimeoutPropose,
|
||||
EventQueryCompleteProposal,
|
||||
EventQueryPolka,
|
||||
EventQueryUnlock,
|
||||
EventQueryLock,
|
||||
EventQueryRelock,
|
||||
EventQueryTimeoutWait,
|
||||
EventQueryVote}
|
||||
|
||||
func randQuery() tmpubsub.Query {
|
||||
return queries[rand.Intn(len(queries))]
|
||||
}
|
||||
205
types/events.go
205
types/events.go
@@ -1,39 +1,40 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
// for registering TMEventData as events.EventData
|
||||
"fmt"
|
||||
|
||||
abci "github.com/tendermint/abci/types"
|
||||
"github.com/tendermint/go-wire/data"
|
||||
cmn "github.com/tendermint/tmlibs/common"
|
||||
"github.com/tendermint/tmlibs/events"
|
||||
tmpubsub "github.com/tendermint/tmlibs/pubsub"
|
||||
tmquery "github.com/tendermint/tmlibs/pubsub/query"
|
||||
)
|
||||
|
||||
// Functions to generate eventId strings
|
||||
// Reserved event types
|
||||
const (
|
||||
EventBond = "Bond"
|
||||
EventCompleteProposal = "CompleteProposal"
|
||||
EventDupeout = "Dupeout"
|
||||
EventFork = "Fork"
|
||||
EventLock = "Lock"
|
||||
EventNewBlock = "NewBlock"
|
||||
EventNewBlockHeader = "NewBlockHeader"
|
||||
EventNewRound = "NewRound"
|
||||
EventNewRoundStep = "NewRoundStep"
|
||||
EventPolka = "Polka"
|
||||
EventRebond = "Rebond"
|
||||
EventRelock = "Relock"
|
||||
EventTimeoutPropose = "TimeoutPropose"
|
||||
EventTimeoutWait = "TimeoutWait"
|
||||
EventTx = "Tx"
|
||||
EventUnbond = "Unbond"
|
||||
EventUnlock = "Unlock"
|
||||
EventVote = "Vote"
|
||||
EventProposalHeartbeat = "ProposalHeartbeat"
|
||||
)
|
||||
|
||||
// Reserved
|
||||
func EventStringBond() string { return "Bond" }
|
||||
func EventStringUnbond() string { return "Unbond" }
|
||||
func EventStringRebond() string { return "Rebond" }
|
||||
func EventStringDupeout() string { return "Dupeout" }
|
||||
func EventStringFork() string { return "Fork" }
|
||||
func EventStringTx(tx Tx) string { return cmn.Fmt("Tx:%X", tx.Hash()) }
|
||||
|
||||
func EventStringNewBlock() string { return "NewBlock" }
|
||||
func EventStringNewBlockHeader() string { return "NewBlockHeader" }
|
||||
func EventStringNewRound() string { return "NewRound" }
|
||||
func EventStringNewRoundStep() string { return "NewRoundStep" }
|
||||
func EventStringTimeoutPropose() string { return "TimeoutPropose" }
|
||||
func EventStringCompleteProposal() string { return "CompleteProposal" }
|
||||
func EventStringPolka() string { return "Polka" }
|
||||
func EventStringUnlock() string { return "Unlock" }
|
||||
func EventStringLock() string { return "Lock" }
|
||||
func EventStringRelock() string { return "Relock" }
|
||||
func EventStringTimeoutWait() string { return "TimeoutWait" }
|
||||
func EventStringVote() string { return "Vote" }
|
||||
|
||||
func EventStringProposalHeartbeat() string { return "ProposalHeartbeat" }
|
||||
|
||||
//----------------------------------------
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// ENCODING / DECODING
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
var (
|
||||
EventDataNameNewBlock = "new_block"
|
||||
@@ -45,11 +46,9 @@ var (
|
||||
EventDataNameProposalHeartbeat = "proposer_heartbeat"
|
||||
)
|
||||
|
||||
//----------------------------------------
|
||||
|
||||
// implements events.EventData
|
||||
type TMEventDataInner interface {
|
||||
events.EventData
|
||||
// empty interface
|
||||
}
|
||||
|
||||
type TMEventData struct {
|
||||
@@ -140,112 +139,54 @@ type EventDataVote struct {
|
||||
Vote *Vote
|
||||
}
|
||||
|
||||
func (_ EventDataNewBlock) AssertIsTMEventData() {}
|
||||
func (_ EventDataNewBlockHeader) AssertIsTMEventData() {}
|
||||
func (_ EventDataTx) AssertIsTMEventData() {}
|
||||
func (_ EventDataRoundState) AssertIsTMEventData() {}
|
||||
func (_ EventDataVote) AssertIsTMEventData() {}
|
||||
|
||||
func (_ EventDataNewBlock) AssertIsTMEventData() {}
|
||||
func (_ EventDataNewBlockHeader) AssertIsTMEventData() {}
|
||||
func (_ EventDataTx) AssertIsTMEventData() {}
|
||||
func (_ EventDataRoundState) AssertIsTMEventData() {}
|
||||
func (_ EventDataVote) AssertIsTMEventData() {}
|
||||
func (_ EventDataProposalHeartbeat) AssertIsTMEventData() {}
|
||||
|
||||
//----------------------------------------
|
||||
// Wrappers for type safety
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// PUBSUB
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
type Fireable interface {
|
||||
events.Fireable
|
||||
const (
|
||||
// EventTypeKey is a reserved key, used to specify event type in tags.
|
||||
EventTypeKey = "tm.events.type"
|
||||
// TxHashKey is a reserved key, used to specify transaction's hash.
|
||||
// see EventBus#PublishEventTx
|
||||
TxHashKey = "tx.hash"
|
||||
)
|
||||
|
||||
var (
|
||||
EventQueryBond = queryForEvent(EventBond)
|
||||
EventQueryUnbond = queryForEvent(EventUnbond)
|
||||
EventQueryRebond = queryForEvent(EventRebond)
|
||||
EventQueryDupeout = queryForEvent(EventDupeout)
|
||||
EventQueryFork = queryForEvent(EventFork)
|
||||
EventQueryNewBlock = queryForEvent(EventNewBlock)
|
||||
EventQueryNewBlockHeader = queryForEvent(EventNewBlockHeader)
|
||||
EventQueryNewRound = queryForEvent(EventNewRound)
|
||||
EventQueryNewRoundStep = queryForEvent(EventNewRoundStep)
|
||||
EventQueryTimeoutPropose = queryForEvent(EventTimeoutPropose)
|
||||
EventQueryCompleteProposal = queryForEvent(EventCompleteProposal)
|
||||
EventQueryPolka = queryForEvent(EventPolka)
|
||||
EventQueryUnlock = queryForEvent(EventUnlock)
|
||||
EventQueryLock = queryForEvent(EventLock)
|
||||
EventQueryRelock = queryForEvent(EventRelock)
|
||||
EventQueryTimeoutWait = queryForEvent(EventTimeoutWait)
|
||||
EventQueryVote = queryForEvent(EventVote)
|
||||
EventQueryProposalHeartbeat = queryForEvent(EventProposalHeartbeat)
|
||||
)
|
||||
|
||||
func EventQueryTx(tx Tx) tmpubsub.Query {
|
||||
return tmquery.MustParse(fmt.Sprintf("%s='%s' AND %s='%X'", EventTypeKey, EventTx, TxHashKey, tx.Hash()))
|
||||
}
|
||||
|
||||
type Eventable interface {
|
||||
SetEventSwitch(EventSwitch)
|
||||
func queryForEvent(eventType string) tmpubsub.Query {
|
||||
return tmquery.MustParse(fmt.Sprintf("%s='%s'", EventTypeKey, eventType))
|
||||
}
|
||||
|
||||
type EventSwitch interface {
|
||||
events.EventSwitch
|
||||
}
|
||||
|
||||
type EventCache interface {
|
||||
Fireable
|
||||
Flush()
|
||||
}
|
||||
|
||||
func NewEventSwitch() EventSwitch {
|
||||
return events.NewEventSwitch()
|
||||
}
|
||||
|
||||
func NewEventCache(evsw EventSwitch) EventCache {
|
||||
return events.NewEventCache(evsw)
|
||||
}
|
||||
|
||||
// All events should be based on this FireEvent to ensure they are TMEventData
|
||||
func fireEvent(fireable events.Fireable, event string, data TMEventData) {
|
||||
if fireable != nil {
|
||||
fireable.FireEvent(event, data)
|
||||
}
|
||||
}
|
||||
|
||||
func AddListenerForEvent(evsw EventSwitch, id, event string, cb func(data TMEventData)) {
|
||||
evsw.AddListenerForEvent(id, event, func(data events.EventData) {
|
||||
cb(data.(TMEventData))
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
//--- block, tx, and vote events
|
||||
|
||||
func FireEventNewBlock(fireable events.Fireable, block EventDataNewBlock) {
|
||||
fireEvent(fireable, EventStringNewBlock(), TMEventData{block})
|
||||
}
|
||||
|
||||
func FireEventNewBlockHeader(fireable events.Fireable, header EventDataNewBlockHeader) {
|
||||
fireEvent(fireable, EventStringNewBlockHeader(), TMEventData{header})
|
||||
}
|
||||
|
||||
func FireEventVote(fireable events.Fireable, vote EventDataVote) {
|
||||
fireEvent(fireable, EventStringVote(), TMEventData{vote})
|
||||
}
|
||||
|
||||
func FireEventTx(fireable events.Fireable, tx EventDataTx) {
|
||||
fireEvent(fireable, EventStringTx(tx.Tx), TMEventData{tx})
|
||||
}
|
||||
|
||||
//--- EventDataRoundState events
|
||||
|
||||
func FireEventNewRoundStep(fireable events.Fireable, rs EventDataRoundState) {
|
||||
fireEvent(fireable, EventStringNewRoundStep(), TMEventData{rs})
|
||||
}
|
||||
|
||||
func FireEventTimeoutPropose(fireable events.Fireable, rs EventDataRoundState) {
|
||||
fireEvent(fireable, EventStringTimeoutPropose(), TMEventData{rs})
|
||||
}
|
||||
|
||||
func FireEventTimeoutWait(fireable events.Fireable, rs EventDataRoundState) {
|
||||
fireEvent(fireable, EventStringTimeoutWait(), TMEventData{rs})
|
||||
}
|
||||
|
||||
func FireEventNewRound(fireable events.Fireable, rs EventDataRoundState) {
|
||||
fireEvent(fireable, EventStringNewRound(), TMEventData{rs})
|
||||
}
|
||||
|
||||
func FireEventCompleteProposal(fireable events.Fireable, rs EventDataRoundState) {
|
||||
fireEvent(fireable, EventStringCompleteProposal(), TMEventData{rs})
|
||||
}
|
||||
|
||||
func FireEventPolka(fireable events.Fireable, rs EventDataRoundState) {
|
||||
fireEvent(fireable, EventStringPolka(), TMEventData{rs})
|
||||
}
|
||||
|
||||
func FireEventUnlock(fireable events.Fireable, rs EventDataRoundState) {
|
||||
fireEvent(fireable, EventStringUnlock(), TMEventData{rs})
|
||||
}
|
||||
|
||||
func FireEventRelock(fireable events.Fireable, rs EventDataRoundState) {
|
||||
fireEvent(fireable, EventStringRelock(), TMEventData{rs})
|
||||
}
|
||||
|
||||
func FireEventLock(fireable events.Fireable, rs EventDataRoundState) {
|
||||
fireEvent(fireable, EventStringLock(), TMEventData{rs})
|
||||
}
|
||||
|
||||
func FireEventProposalHeartbeat(fireable events.Fireable, rs EventDataProposalHeartbeat) {
|
||||
fireEvent(fireable, EventStringProposalHeartbeat(), TMEventData{rs})
|
||||
type TxEventPublisher interface {
|
||||
PublishEventTx(EventDataTx) error
|
||||
}
|
||||
|
||||
77
types/nop_event_bus.go
Normal file
77
types/nop_event_bus.go
Normal file
@@ -0,0 +1,77 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
tmpubsub "github.com/tendermint/tmlibs/pubsub"
|
||||
)
|
||||
|
||||
type NopEventBus struct{}
|
||||
|
||||
func (NopEventBus) Subscribe(ctx context.Context, subscriber string, query tmpubsub.Query, out chan<- interface{}) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (NopEventBus) Unsubscribe(ctx context.Context, subscriber string, query tmpubsub.Query) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (NopEventBus) UnsubscribeAll(ctx context.Context, subscriber string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
//--- block, tx, and vote events
|
||||
|
||||
func (NopEventBus) PublishEventNewBlock(block EventDataNewBlock) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (NopEventBus) PublishEventNewBlockHeader(header EventDataNewBlockHeader) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (NopEventBus) PublishEventVote(vote EventDataVote) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (NopEventBus) PublishEventTx(tx EventDataTx) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
//--- EventDataRoundState events
|
||||
|
||||
func (NopEventBus) PublishEventNewRoundStep(rs EventDataRoundState) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (NopEventBus) PublishEventTimeoutPropose(rs EventDataRoundState) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (NopEventBus) PublishEventTimeoutWait(rs EventDataRoundState) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (NopEventBus) PublishEventNewRound(rs EventDataRoundState) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (NopEventBus) PublishEventCompleteProposal(rs EventDataRoundState) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (NopEventBus) PublishEventPolka(rs EventDataRoundState) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (NopEventBus) PublishEventUnlock(rs EventDataRoundState) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (NopEventBus) PublishEventRelock(rs EventDataRoundState) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (NopEventBus) PublishEventLock(rs EventDataRoundState) error {
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user