mirror of
https://github.com/tendermint/tendermint.git
synced 2026-06-02 04:16:20 +00:00
pubsub: Refactor Event Subscription (#6634)
This commit is contained in:
committed by
GitHub
parent
b0a413eb17
commit
414130aee1
@@ -3,6 +3,7 @@ package types
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/tendermint/tendermint/abci/types"
|
||||
"github.com/tendermint/tendermint/libs/log"
|
||||
@@ -100,47 +101,31 @@ 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 {
|
||||
func (b *EventBus) Publish(eventValue string, eventData TMEventData) error {
|
||||
// no explicit deadline for publishing events
|
||||
ctx := context.Background()
|
||||
return b.pubsub.PublishWithEvents(ctx, eventData, map[string][]string{EventTypeKey: {eventType}})
|
||||
}
|
||||
|
||||
// validateAndStringifyEvents takes a slice of event objects and creates a
|
||||
// map of stringified events where each key is composed of the event
|
||||
// type and each of the event's attributes keys in the form of
|
||||
// "{event.Type}.{attribute.Key}" and the value is each attribute's value.
|
||||
func (b *EventBus) validateAndStringifyEvents(events []types.Event, logger log.Logger) map[string][]string {
|
||||
result := make(map[string][]string)
|
||||
for _, event := range events {
|
||||
if len(event.Type) == 0 {
|
||||
logger.Debug("Got an event with an empty type (skipping)", "event", event)
|
||||
continue
|
||||
}
|
||||
|
||||
for _, attr := range event.Attributes {
|
||||
if len(attr.Key) == 0 {
|
||||
logger.Debug("Got an event attribute with an empty key(skipping)", "event", event)
|
||||
continue
|
||||
}
|
||||
|
||||
compositeTag := fmt.Sprintf("%s.%s", event.Type, attr.Key)
|
||||
result[compositeTag] = append(result[compositeTag], attr.Value)
|
||||
}
|
||||
tokens := strings.Split(EventTypeKey, ".")
|
||||
event := types.Event{
|
||||
Type: tokens[0],
|
||||
Attributes: []types.EventAttribute{
|
||||
{
|
||||
Key: tokens[1],
|
||||
Value: eventValue,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
return result
|
||||
return b.pubsub.PublishWithEvents(ctx, eventData, []types.Event{event})
|
||||
}
|
||||
|
||||
func (b *EventBus) PublishEventNewBlock(data EventDataNewBlock) error {
|
||||
// no explicit deadline for publishing events
|
||||
ctx := context.Background()
|
||||
events := append(data.ResultBeginBlock.Events, data.ResultEndBlock.Events...)
|
||||
|
||||
resultEvents := append(data.ResultBeginBlock.Events, data.ResultEndBlock.Events...)
|
||||
events := b.validateAndStringifyEvents(resultEvents, b.Logger.With("block", data.Block.StringShort()))
|
||||
|
||||
// add predefined new block event
|
||||
events[EventTypeKey] = append(events[EventTypeKey], EventNewBlock)
|
||||
// add Tendermint-reserved new block event
|
||||
events = append(events, EventNewBlock)
|
||||
|
||||
return b.pubsub.PublishWithEvents(ctx, data, events)
|
||||
}
|
||||
@@ -148,27 +133,24 @@ func (b *EventBus) PublishEventNewBlock(data EventDataNewBlock) error {
|
||||
func (b *EventBus) PublishEventNewBlockHeader(data EventDataNewBlockHeader) error {
|
||||
// no explicit deadline for publishing events
|
||||
ctx := context.Background()
|
||||
events := append(data.ResultBeginBlock.Events, data.ResultEndBlock.Events...)
|
||||
|
||||
resultTags := append(data.ResultBeginBlock.Events, data.ResultEndBlock.Events...)
|
||||
// TODO: Create StringShort method for Header and use it in logger.
|
||||
events := b.validateAndStringifyEvents(resultTags, b.Logger.With("header", data.Header))
|
||||
|
||||
// add predefined new block header event
|
||||
events[EventTypeKey] = append(events[EventTypeKey], EventNewBlockHeader)
|
||||
// add Tendermint-reserved new block header event
|
||||
events = append(events, EventNewBlockHeader)
|
||||
|
||||
return b.pubsub.PublishWithEvents(ctx, data, events)
|
||||
}
|
||||
|
||||
func (b *EventBus) PublishEventNewEvidence(evidence EventDataNewEvidence) error {
|
||||
return b.Publish(EventNewEvidence, evidence)
|
||||
return b.Publish(EventNewEvidenceValue, evidence)
|
||||
}
|
||||
|
||||
func (b *EventBus) PublishEventVote(data EventDataVote) error {
|
||||
return b.Publish(EventVote, data)
|
||||
return b.Publish(EventVoteValue, data)
|
||||
}
|
||||
|
||||
func (b *EventBus) PublishEventValidBlock(data EventDataRoundState) error {
|
||||
return b.Publish(EventValidBlock, data)
|
||||
return b.Publish(EventValidBlockValue, data)
|
||||
}
|
||||
|
||||
// PublishEventTx publishes tx event with events from Result. Note it will add
|
||||
@@ -177,55 +159,74 @@ func (b *EventBus) PublishEventValidBlock(data EventDataRoundState) error {
|
||||
func (b *EventBus) PublishEventTx(data EventDataTx) error {
|
||||
// no explicit deadline for publishing events
|
||||
ctx := context.Background()
|
||||
events := data.Result.Events
|
||||
|
||||
events := b.validateAndStringifyEvents(data.Result.Events, b.Logger.With("tx", data.Tx))
|
||||
// add Tendermint-reserved events
|
||||
events = append(events, EventTx)
|
||||
|
||||
// add predefined compositeKeys
|
||||
events[EventTypeKey] = append(events[EventTypeKey], EventTx)
|
||||
events[TxHashKey] = append(events[TxHashKey], fmt.Sprintf("%X", Tx(data.Tx).Hash()))
|
||||
events[TxHeightKey] = append(events[TxHeightKey], fmt.Sprintf("%d", data.Height))
|
||||
tokens := strings.Split(TxHashKey, ".")
|
||||
events = append(events, types.Event{
|
||||
Type: tokens[0],
|
||||
Attributes: []types.EventAttribute{
|
||||
{
|
||||
Key: tokens[1],
|
||||
Value: fmt.Sprintf("%X", Tx(data.Tx).Hash()),
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
tokens = strings.Split(TxHeightKey, ".")
|
||||
events = append(events, types.Event{
|
||||
Type: tokens[0],
|
||||
Attributes: []types.EventAttribute{
|
||||
{
|
||||
Key: tokens[1],
|
||||
Value: fmt.Sprintf("%d", data.Height),
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
return b.pubsub.PublishWithEvents(ctx, data, events)
|
||||
}
|
||||
|
||||
func (b *EventBus) PublishEventNewRoundStep(data EventDataRoundState) error {
|
||||
return b.Publish(EventNewRoundStep, data)
|
||||
return b.Publish(EventNewRoundStepValue, data)
|
||||
}
|
||||
|
||||
func (b *EventBus) PublishEventTimeoutPropose(data EventDataRoundState) error {
|
||||
return b.Publish(EventTimeoutPropose, data)
|
||||
return b.Publish(EventTimeoutProposeValue, data)
|
||||
}
|
||||
|
||||
func (b *EventBus) PublishEventTimeoutWait(data EventDataRoundState) error {
|
||||
return b.Publish(EventTimeoutWait, data)
|
||||
return b.Publish(EventTimeoutWaitValue, data)
|
||||
}
|
||||
|
||||
func (b *EventBus) PublishEventNewRound(data EventDataNewRound) error {
|
||||
return b.Publish(EventNewRound, data)
|
||||
return b.Publish(EventNewRoundValue, data)
|
||||
}
|
||||
|
||||
func (b *EventBus) PublishEventCompleteProposal(data EventDataCompleteProposal) error {
|
||||
return b.Publish(EventCompleteProposal, data)
|
||||
return b.Publish(EventCompleteProposalValue, data)
|
||||
}
|
||||
|
||||
func (b *EventBus) PublishEventPolka(data EventDataRoundState) error {
|
||||
return b.Publish(EventPolka, data)
|
||||
return b.Publish(EventPolkaValue, data)
|
||||
}
|
||||
|
||||
func (b *EventBus) PublishEventUnlock(data EventDataRoundState) error {
|
||||
return b.Publish(EventUnlock, data)
|
||||
return b.Publish(EventUnlockValue, data)
|
||||
}
|
||||
|
||||
func (b *EventBus) PublishEventRelock(data EventDataRoundState) error {
|
||||
return b.Publish(EventRelock, data)
|
||||
return b.Publish(EventRelockValue, data)
|
||||
}
|
||||
|
||||
func (b *EventBus) PublishEventLock(data EventDataRoundState) error {
|
||||
return b.Publish(EventLock, data)
|
||||
return b.Publish(EventLockValue, data)
|
||||
}
|
||||
|
||||
func (b *EventBus) PublishEventValidatorSetUpdates(data EventDataValidatorSetUpdates) error {
|
||||
return b.Publish(EventValidatorSetUpdates, data)
|
||||
return b.Publish(EventValidatorSetUpdatesValue, data)
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
@@ -342,7 +342,7 @@ func TestEventBusPublish(t *testing.T) {
|
||||
}
|
||||
}()
|
||||
|
||||
err = eventBus.Publish(EventNewBlockHeader, EventDataNewBlockHeader{})
|
||||
err = eventBus.Publish(EventNewBlockHeaderValue, EventDataNewBlockHeader{})
|
||||
require.NoError(t, err)
|
||||
err = eventBus.PublishEventNewBlock(EventDataNewBlock{})
|
||||
require.NoError(t, err)
|
||||
@@ -447,16 +447,16 @@ func benchmarkEventBus(numClients int, randQueries bool, randEvents bool, b *tes
|
||||
}()
|
||||
}
|
||||
|
||||
eventType := EventNewBlock
|
||||
eventValue := EventNewBlockValue
|
||||
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
if randEvents {
|
||||
eventType = randEvent()
|
||||
eventValue = randEventValue()
|
||||
}
|
||||
|
||||
err := eventBus.Publish(eventType, EventDataString("Gamora"))
|
||||
err := eventBus.Publish(eventValue, EventDataString("Gamora"))
|
||||
if err != nil {
|
||||
b.Error(err)
|
||||
}
|
||||
@@ -464,20 +464,21 @@ func benchmarkEventBus(numClients int, randQueries bool, randEvents bool, b *tes
|
||||
}
|
||||
|
||||
var events = []string{
|
||||
EventNewBlock,
|
||||
EventNewBlockHeader,
|
||||
EventNewRound,
|
||||
EventNewRoundStep,
|
||||
EventTimeoutPropose,
|
||||
EventCompleteProposal,
|
||||
EventPolka,
|
||||
EventUnlock,
|
||||
EventLock,
|
||||
EventRelock,
|
||||
EventTimeoutWait,
|
||||
EventVote}
|
||||
EventNewBlockValue,
|
||||
EventNewBlockHeaderValue,
|
||||
EventNewRoundValue,
|
||||
EventNewRoundStepValue,
|
||||
EventTimeoutProposeValue,
|
||||
EventCompleteProposalValue,
|
||||
EventPolkaValue,
|
||||
EventUnlockValue,
|
||||
EventLockValue,
|
||||
EventRelockValue,
|
||||
EventTimeoutWaitValue,
|
||||
EventVoteValue,
|
||||
}
|
||||
|
||||
func randEvent() string {
|
||||
func randEventValue() string {
|
||||
return events[mrand.Intn(len(events))]
|
||||
}
|
||||
|
||||
|
||||
114
types/events.go
114
types/events.go
@@ -2,6 +2,7 @@ package types
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
abci "github.com/tendermint/tendermint/abci/types"
|
||||
tmjson "github.com/tendermint/tendermint/libs/json"
|
||||
@@ -16,26 +17,69 @@ const (
|
||||
// after a block has been committed.
|
||||
// These are also used by the tx indexer for async indexing.
|
||||
// All of this data can be fetched through the rpc.
|
||||
EventNewBlock = "NewBlock"
|
||||
EventNewBlockHeader = "NewBlockHeader"
|
||||
EventNewEvidence = "NewEvidence"
|
||||
EventTx = "Tx"
|
||||
EventValidatorSetUpdates = "ValidatorSetUpdates"
|
||||
EventNewBlockValue = "NewBlock"
|
||||
EventNewBlockHeaderValue = "NewBlockHeader"
|
||||
EventNewEvidenceValue = "NewEvidence"
|
||||
EventTxValue = "Tx"
|
||||
EventValidatorSetUpdatesValue = "ValidatorSetUpdates"
|
||||
|
||||
// Internal consensus events.
|
||||
// These are used for testing the consensus state machine.
|
||||
// They can also be used to build real-time consensus visualizers.
|
||||
EventCompleteProposal = "CompleteProposal"
|
||||
EventLock = "Lock"
|
||||
EventNewRound = "NewRound"
|
||||
EventNewRoundStep = "NewRoundStep"
|
||||
EventPolka = "Polka"
|
||||
EventRelock = "Relock"
|
||||
EventTimeoutPropose = "TimeoutPropose"
|
||||
EventTimeoutWait = "TimeoutWait"
|
||||
EventUnlock = "Unlock"
|
||||
EventValidBlock = "ValidBlock"
|
||||
EventVote = "Vote"
|
||||
EventCompleteProposalValue = "CompleteProposal"
|
||||
EventLockValue = "Lock"
|
||||
EventNewRoundValue = "NewRound"
|
||||
EventNewRoundStepValue = "NewRoundStep"
|
||||
EventPolkaValue = "Polka"
|
||||
EventRelockValue = "Relock"
|
||||
EventTimeoutProposeValue = "TimeoutPropose"
|
||||
EventTimeoutWaitValue = "TimeoutWait"
|
||||
EventUnlockValue = "Unlock"
|
||||
EventValidBlockValue = "ValidBlock"
|
||||
EventVoteValue = "Vote"
|
||||
)
|
||||
|
||||
// Pre-populated ABCI Tendermint-reserved events
|
||||
var (
|
||||
EventNewBlock = abci.Event{
|
||||
Type: strings.Split(EventTypeKey, ".")[0],
|
||||
Attributes: []abci.EventAttribute{
|
||||
{
|
||||
Key: strings.Split(EventTypeKey, ".")[1],
|
||||
Value: EventNewBlockValue,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
EventNewBlockHeader = abci.Event{
|
||||
Type: strings.Split(EventTypeKey, ".")[0],
|
||||
Attributes: []abci.EventAttribute{
|
||||
{
|
||||
Key: strings.Split(EventTypeKey, ".")[1],
|
||||
Value: EventNewBlockHeaderValue,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
EventNewEvidence = abci.Event{
|
||||
Type: strings.Split(EventTypeKey, ".")[0],
|
||||
Attributes: []abci.EventAttribute{
|
||||
{
|
||||
Key: strings.Split(EventTypeKey, ".")[1],
|
||||
Value: EventNewEvidenceValue,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
EventTx = abci.Event{
|
||||
Type: strings.Split(EventTypeKey, ".")[0],
|
||||
Attributes: []abci.EventAttribute{
|
||||
{
|
||||
Key: strings.Split(EventTypeKey, ".")[1],
|
||||
Value: EventTxValue,
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
// ENCODING / DECODING
|
||||
@@ -147,30 +191,30 @@ const (
|
||||
)
|
||||
|
||||
var (
|
||||
EventQueryCompleteProposal = QueryForEvent(EventCompleteProposal)
|
||||
EventQueryLock = QueryForEvent(EventLock)
|
||||
EventQueryNewBlock = QueryForEvent(EventNewBlock)
|
||||
EventQueryNewBlockHeader = QueryForEvent(EventNewBlockHeader)
|
||||
EventQueryNewEvidence = QueryForEvent(EventNewEvidence)
|
||||
EventQueryNewRound = QueryForEvent(EventNewRound)
|
||||
EventQueryNewRoundStep = QueryForEvent(EventNewRoundStep)
|
||||
EventQueryPolka = QueryForEvent(EventPolka)
|
||||
EventQueryRelock = QueryForEvent(EventRelock)
|
||||
EventQueryTimeoutPropose = QueryForEvent(EventTimeoutPropose)
|
||||
EventQueryTimeoutWait = QueryForEvent(EventTimeoutWait)
|
||||
EventQueryTx = QueryForEvent(EventTx)
|
||||
EventQueryUnlock = QueryForEvent(EventUnlock)
|
||||
EventQueryValidatorSetUpdates = QueryForEvent(EventValidatorSetUpdates)
|
||||
EventQueryValidBlock = QueryForEvent(EventValidBlock)
|
||||
EventQueryVote = QueryForEvent(EventVote)
|
||||
EventQueryCompleteProposal = QueryForEvent(EventCompleteProposalValue)
|
||||
EventQueryLock = QueryForEvent(EventLockValue)
|
||||
EventQueryNewBlock = QueryForEvent(EventNewBlockValue)
|
||||
EventQueryNewBlockHeader = QueryForEvent(EventNewBlockHeaderValue)
|
||||
EventQueryNewEvidence = QueryForEvent(EventNewEvidenceValue)
|
||||
EventQueryNewRound = QueryForEvent(EventNewRoundValue)
|
||||
EventQueryNewRoundStep = QueryForEvent(EventNewRoundStepValue)
|
||||
EventQueryPolka = QueryForEvent(EventPolkaValue)
|
||||
EventQueryRelock = QueryForEvent(EventRelockValue)
|
||||
EventQueryTimeoutPropose = QueryForEvent(EventTimeoutProposeValue)
|
||||
EventQueryTimeoutWait = QueryForEvent(EventTimeoutWaitValue)
|
||||
EventQueryTx = QueryForEvent(EventTxValue)
|
||||
EventQueryUnlock = QueryForEvent(EventUnlockValue)
|
||||
EventQueryValidatorSetUpdates = QueryForEvent(EventValidatorSetUpdatesValue)
|
||||
EventQueryValidBlock = QueryForEvent(EventValidBlockValue)
|
||||
EventQueryVote = QueryForEvent(EventVoteValue)
|
||||
)
|
||||
|
||||
func EventQueryTxFor(tx Tx) tmpubsub.Query {
|
||||
return tmquery.MustParse(fmt.Sprintf("%s='%s' AND %s='%X'", EventTypeKey, EventTx, TxHashKey, tx.Hash()))
|
||||
return tmquery.MustParse(fmt.Sprintf("%s='%s' AND %s='%X'", EventTypeKey, EventTxValue, TxHashKey, tx.Hash()))
|
||||
}
|
||||
|
||||
func QueryForEvent(eventType string) tmpubsub.Query {
|
||||
return tmquery.MustParse(fmt.Sprintf("%s='%s'", EventTypeKey, eventType))
|
||||
func QueryForEvent(eventValue string) tmpubsub.Query {
|
||||
return tmquery.MustParse(fmt.Sprintf("%s='%s'", EventTypeKey, eventValue))
|
||||
}
|
||||
|
||||
// BlockEventPublisher publishes all block related events
|
||||
|
||||
@@ -18,10 +18,10 @@ func TestQueryTxFor(t *testing.T) {
|
||||
func TestQueryForEvent(t *testing.T) {
|
||||
assert.Equal(t,
|
||||
"tm.event='NewBlock'",
|
||||
QueryForEvent(EventNewBlock).String(),
|
||||
QueryForEvent(EventNewBlockValue).String(),
|
||||
)
|
||||
assert.Equal(t,
|
||||
"tm.event='NewEvidence'",
|
||||
QueryForEvent(EventNewEvidence).String(),
|
||||
QueryForEvent(EventNewEvidenceValue).String(),
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user