mirror of
https://github.com/tendermint/tendermint.git
synced 2026-08-27 19:37:08 +00:00
pubsub: Refactor Event Subscription (#6634)
This commit is contained in:
@@ -1,11 +1,15 @@
|
||||
package query
|
||||
|
||||
import (
|
||||
"github.com/tendermint/tendermint/abci/types"
|
||||
)
|
||||
|
||||
// Empty query matches any set of events.
|
||||
type Empty struct {
|
||||
}
|
||||
|
||||
// Matches always returns true.
|
||||
func (Empty) Matches(tags map[string][]string) (bool, error) {
|
||||
func (Empty) Matches(events []types.Event) (bool, error) {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -3,8 +3,8 @@ package query_test
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
abci "github.com/tendermint/tendermint/abci/types"
|
||||
"github.com/tendermint/tendermint/libs/pubsub/query"
|
||||
)
|
||||
|
||||
@@ -12,17 +12,44 @@ func TestEmptyQueryMatchesAnything(t *testing.T) {
|
||||
q := query.Empty{}
|
||||
|
||||
testCases := []struct {
|
||||
query map[string][]string
|
||||
events []abci.Event
|
||||
}{
|
||||
{map[string][]string{}},
|
||||
{map[string][]string{"Asher": {"Roth"}}},
|
||||
{map[string][]string{"Route": {"66"}}},
|
||||
{map[string][]string{"Route": {"66"}, "Billy": {"Blue"}}},
|
||||
{
|
||||
[]abci.Event{},
|
||||
},
|
||||
{
|
||||
[]abci.Event{
|
||||
{
|
||||
Type: "Asher",
|
||||
Attributes: []abci.EventAttribute{{Key: "Roth"}},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
[]abci.Event{
|
||||
{
|
||||
Type: "Route",
|
||||
Attributes: []abci.EventAttribute{{Key: "66"}},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
[]abci.Event{
|
||||
{
|
||||
Type: "Route",
|
||||
Attributes: []abci.EventAttribute{{Key: "66"}},
|
||||
},
|
||||
{
|
||||
Type: "Billy",
|
||||
Attributes: []abci.EventAttribute{{Key: "Blue"}},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
match, err := q.Matches(tc.query)
|
||||
assert.Nil(t, err)
|
||||
assert.True(t, match)
|
||||
match, err := q.Matches(tc.events)
|
||||
require.Nil(t, err)
|
||||
require.True(t, match)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,8 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/tendermint/tendermint/abci/types"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -198,11 +200,13 @@ func (q *Query) Conditions() ([]Condition, error) {
|
||||
//
|
||||
// For example, query "name=John" matches events = {"name": ["John", "Eric"]}.
|
||||
// More examples could be found in parser_test.go and query_test.go.
|
||||
func (q *Query) Matches(events map[string][]string) (bool, error) {
|
||||
if len(events) == 0 {
|
||||
func (q *Query) Matches(rawEvents []types.Event) (bool, error) {
|
||||
if len(rawEvents) == 0 {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
events := flattenEvents(rawEvents)
|
||||
|
||||
var (
|
||||
eventAttr string
|
||||
op Operator
|
||||
@@ -500,3 +504,24 @@ func matchValue(value string, op Operator, operand reflect.Value) (bool, error)
|
||||
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func flattenEvents(events []types.Event) map[string][]string {
|
||||
flattened := make(map[string][]string)
|
||||
|
||||
for _, event := range events {
|
||||
if len(event.Type) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
for _, attr := range event.Attributes {
|
||||
if len(attr.Key) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
compositeEvent := fmt.Sprintf("%s.%s", event.Type, attr.Key)
|
||||
flattened[compositeEvent] = append(flattened[compositeEvent], attr.Value)
|
||||
}
|
||||
}
|
||||
|
||||
return flattened
|
||||
}
|
||||
|
||||
@@ -2,15 +2,38 @@ package query_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
abci "github.com/tendermint/tendermint/abci/types"
|
||||
"github.com/tendermint/tendermint/libs/pubsub/query"
|
||||
)
|
||||
|
||||
func expandEvents(flattenedEvents map[string][]string) []abci.Event {
|
||||
events := make([]abci.Event, len(flattenedEvents))
|
||||
|
||||
for composite, values := range flattenedEvents {
|
||||
tokens := strings.Split(composite, ".")
|
||||
|
||||
attrs := make([]abci.EventAttribute, len(values))
|
||||
for i, v := range values {
|
||||
attrs[i] = abci.EventAttribute{
|
||||
Key: tokens[len(tokens)-1],
|
||||
Value: v,
|
||||
}
|
||||
}
|
||||
|
||||
events = append(events, abci.Event{
|
||||
Type: strings.Join(tokens[:len(tokens)-1], "."),
|
||||
Attributes: attrs,
|
||||
})
|
||||
}
|
||||
|
||||
return events
|
||||
}
|
||||
|
||||
func TestMatches(t *testing.T) {
|
||||
var (
|
||||
txDate = "2017-01-01"
|
||||
@@ -159,21 +182,23 @@ func TestMatches(t *testing.T) {
|
||||
}
|
||||
require.NotNil(t, q, "Query '%s' should not be nil", tc.s)
|
||||
|
||||
rawEvents := expandEvents(tc.events)
|
||||
|
||||
if tc.matches {
|
||||
match, err := q.Matches(tc.events)
|
||||
assert.Nil(t, err, "Query '%s' should not error on match %v", tc.s, tc.events)
|
||||
assert.True(t, match, "Query '%s' should match %v", tc.s, tc.events)
|
||||
match, err := q.Matches(rawEvents)
|
||||
require.Nil(t, err, "Query '%s' should not error on match %v", tc.s, tc.events)
|
||||
require.True(t, match, "Query '%s' should match %v", tc.s, tc.events)
|
||||
} else {
|
||||
match, err := q.Matches(tc.events)
|
||||
assert.Equal(t, tc.matchErr, err != nil, "Unexpected error for query '%s' match %v", tc.s, tc.events)
|
||||
assert.False(t, match, "Query '%s' should not match %v", tc.s, tc.events)
|
||||
match, err := q.Matches(rawEvents)
|
||||
require.Equal(t, tc.matchErr, err != nil, "Unexpected error for query '%s' match %v", tc.s, tc.events)
|
||||
require.False(t, match, "Query '%s' should not match %v", tc.s, tc.events)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestMustParse(t *testing.T) {
|
||||
assert.Panics(t, func() { query.MustParse("=") })
|
||||
assert.NotPanics(t, func() { query.MustParse("tm.events.type='NewBlock'") })
|
||||
require.Panics(t, func() { query.MustParse("=") })
|
||||
require.NotPanics(t, func() { query.MustParse("tm.events.type='NewBlock'") })
|
||||
}
|
||||
|
||||
func TestConditions(t *testing.T) {
|
||||
@@ -217,6 +242,6 @@ func TestConditions(t *testing.T) {
|
||||
|
||||
c, err := q.Conditions()
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, tc.conditions, c)
|
||||
require.Equal(t, tc.conditions, c)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user