Fix concerns and docs identified by review
This commit is contained in:
parent
61dd381a3d
commit
a0483a4950
@ -909,14 +909,17 @@ type FullNode interface {
|
|||||||
|
|
||||||
// Actor events
|
// Actor events
|
||||||
|
|
||||||
// GetActorEvents returns all FVM and built-in Actor events that match the given filter.
|
// GetActorEvents returns all user-programmed and built-in actor events that match the given
|
||||||
|
// filter.
|
||||||
// This is a request/response API.
|
// This is a request/response API.
|
||||||
// Results available from this API may be limited by the MaxFilterResults and MaxFilterHeightRange
|
// Results available from this API may be limited by the MaxFilterResults and MaxFilterHeightRange
|
||||||
// configuration options and also the amount of historical data available in the node.
|
// configuration options and also the amount of historical data available in the node.
|
||||||
|
//
|
||||||
|
// This is an EXPERIMENTAL API and may be subject to change.
|
||||||
GetActorEvents(ctx context.Context, filter *types.ActorEventFilter) ([]*types.ActorEvent, error) //perm:read
|
GetActorEvents(ctx context.Context, filter *types.ActorEventFilter) ([]*types.ActorEvent, error) //perm:read
|
||||||
|
|
||||||
// SubscribeActorEvents returns a long-lived stream of all FVM and built-in Actor events that
|
// SubscribeActorEvents returns a long-lived stream of all user-programmed and built-in actor
|
||||||
// match the given filter.
|
// events that match the given filter.
|
||||||
// Events that match the given filter are written to the stream in real-time as they are emitted
|
// Events that match the given filter are written to the stream in real-time as they are emitted
|
||||||
// from the FVM.
|
// from the FVM.
|
||||||
// The response stream is closed when the client disconnects, when a ToHeight is specified and is
|
// The response stream is closed when the client disconnects, when a ToHeight is specified and is
|
||||||
@ -926,7 +929,9 @@ type FullNode interface {
|
|||||||
// FromHeight.
|
// FromHeight.
|
||||||
// Results available from this API may be limited by the MaxFilterResults and MaxFilterHeightRange
|
// Results available from this API may be limited by the MaxFilterResults and MaxFilterHeightRange
|
||||||
// configuration options and also the amount of historical data available in the node.
|
// configuration options and also the amount of historical data available in the node.
|
||||||
// NOTE: THIS API IS ONLY SUPPORTED OVER WEBSOCKETS FOR NOW
|
//
|
||||||
|
// Note: this API is only available via websocket connections.
|
||||||
|
// This is an EXPERIMENTAL API and may be subject to change.
|
||||||
SubscribeActorEvents(ctx context.Context, filter *types.ActorEventFilter) (<-chan *types.ActorEvent, error) //perm:read
|
SubscribeActorEvents(ctx context.Context, filter *types.ActorEventFilter) (<-chan *types.ActorEvent, error) //perm:read
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Binary file not shown.
@ -41,7 +41,7 @@ type eventFilter struct {
|
|||||||
minHeight abi.ChainEpoch // minimum epoch to apply filter or -1 if no minimum
|
minHeight abi.ChainEpoch // minimum epoch to apply filter or -1 if no minimum
|
||||||
maxHeight abi.ChainEpoch // maximum epoch to apply filter or -1 if no maximum
|
maxHeight abi.ChainEpoch // maximum epoch to apply filter or -1 if no maximum
|
||||||
tipsetCid cid.Cid
|
tipsetCid cid.Cid
|
||||||
addresses []address.Address // list of f4 actor addresses that are extpected to emit the event
|
addresses []address.Address // list of actor addresses that are extpected to emit the event
|
||||||
|
|
||||||
keysWithCodec map[string][]types.ActorEventBlock // map of key names to a list of alternate values that may match
|
keysWithCodec map[string][]types.ActorEventBlock // map of key names to a list of alternate values that may match
|
||||||
maxResults int // maximum number of results to collect, 0 is unlimited
|
maxResults int // maximum number of results to collect, 0 is unlimited
|
||||||
@ -56,7 +56,7 @@ var _ Filter = (*eventFilter)(nil)
|
|||||||
|
|
||||||
type CollectedEvent struct {
|
type CollectedEvent struct {
|
||||||
Entries []types.EventEntry
|
Entries []types.EventEntry
|
||||||
EmitterAddr address.Address // f4 address of emitter
|
EmitterAddr address.Address // address of emitter
|
||||||
EventIdx int // index of the event within the list of emitted events
|
EventIdx int // index of the event within the list of emitted events
|
||||||
Reverted bool
|
Reverted bool
|
||||||
Height abi.ChainEpoch
|
Height abi.ChainEpoch
|
||||||
|
@ -3390,11 +3390,14 @@ Response:
|
|||||||
|
|
||||||
|
|
||||||
### GetActorEvents
|
### GetActorEvents
|
||||||
GetActorEvents returns all FVM and built-in Actor events that match the given filter.
|
GetActorEvents returns all user-programmed and built-in actor events that match the given
|
||||||
|
filter.
|
||||||
This is a request/response API.
|
This is a request/response API.
|
||||||
Results available from this API may be limited by the MaxFilterResults and MaxFilterHeightRange
|
Results available from this API may be limited by the MaxFilterResults and MaxFilterHeightRange
|
||||||
configuration options and also the amount of historical data available in the node.
|
configuration options and also the amount of historical data available in the node.
|
||||||
|
|
||||||
|
This is an EXPERIMENTAL API and may be subject to change.
|
||||||
|
|
||||||
|
|
||||||
Perms: read
|
Perms: read
|
||||||
|
|
||||||
@ -8829,8 +8832,8 @@ Response:
|
|||||||
|
|
||||||
|
|
||||||
### SubscribeActorEvents
|
### SubscribeActorEvents
|
||||||
SubscribeActorEvents returns a long-lived stream of all FVM and built-in Actor events that
|
SubscribeActorEvents returns a long-lived stream of all user-programmed and built-in actor
|
||||||
match the given filter.
|
events that match the given filter.
|
||||||
Events that match the given filter are written to the stream in real-time as they are emitted
|
Events that match the given filter are written to the stream in real-time as they are emitted
|
||||||
from the FVM.
|
from the FVM.
|
||||||
The response stream is closed when the client disconnects, when a ToHeight is specified and is
|
The response stream is closed when the client disconnects, when a ToHeight is specified and is
|
||||||
@ -8840,7 +8843,9 @@ real-time events are written to the response stream if the filter specifies an e
|
|||||||
FromHeight.
|
FromHeight.
|
||||||
Results available from this API may be limited by the MaxFilterResults and MaxFilterHeightRange
|
Results available from this API may be limited by the MaxFilterResults and MaxFilterHeightRange
|
||||||
configuration options and also the amount of historical data available in the node.
|
configuration options and also the amount of historical data available in the node.
|
||||||
NOTE: THIS API IS ONLY SUPPORTED OVER WEBSOCKETS FOR NOW
|
|
||||||
|
Note: this API is only available via websocket connections.
|
||||||
|
This is an EXPERIMENTAL API and may be subject to change.
|
||||||
|
|
||||||
|
|
||||||
Perms: read
|
Perms: read
|
||||||
|
@ -232,6 +232,11 @@ func (a *ActorEventHandler) SubscribeActorEvents(ctx context.Context, evtFilter
|
|||||||
|
|
||||||
out := make(chan *types.ActorEvent)
|
out := make(chan *types.ActorEvent)
|
||||||
|
|
||||||
|
// When we start sending real-time events, we want to make sure that we don't fall behind more
|
||||||
|
// than one epoch's worth of events (approximately). Capture this value now, before we send
|
||||||
|
// historical events to allow for a little bit of slack in the historical event sending.
|
||||||
|
minBacklogHeight := a.chain.GetHeaviestTipSet().Height() - 1
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
defer func() {
|
defer func() {
|
||||||
// tell the caller we're done
|
// tell the caller we're done
|
||||||
@ -242,11 +247,6 @@ func (a *ActorEventHandler) SubscribeActorEvents(ctx context.Context, evtFilter
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// When we start sending real-time events, we want to make sure that we don't fall behind more
|
|
||||||
// than one epoch's worth of events (approximately). Capture this value now, before we send
|
|
||||||
// historical events to allow for a little bit of slack in the historical event sending.
|
|
||||||
minBacklogHeight := a.chain.GetHeaviestTipSet().Height() - 1
|
|
||||||
|
|
||||||
// Handle any historical events that our filter may have picked up -----------------------------
|
// Handle any historical events that our filter may have picked up -----------------------------
|
||||||
|
|
||||||
evs := getCollected(ctx, fm)
|
evs := getCollected(ctx, fm)
|
||||||
@ -270,7 +270,7 @@ func (a *ActorEventHandler) SubscribeActorEvents(ctx context.Context, evtFilter
|
|||||||
|
|
||||||
// for the case where we have a MaxHeight set, we don't get a signal from the filter when we
|
// for the case where we have a MaxHeight set, we don't get a signal from the filter when we
|
||||||
// reach that height, so we need to check it ourselves, do it now but also in the loop
|
// reach that height, so we need to check it ourselves, do it now but also in the loop
|
||||||
if params.MaxHeight > 0 && a.chain.GetHeaviestTipSet().Height() > params.MaxHeight {
|
if params.MaxHeight > 0 && minBacklogHeight+1 >= params.MaxHeight {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -246,9 +246,6 @@ func TestGetActorEvents(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestSubscribeActorEvents(t *testing.T) {
|
func TestSubscribeActorEvents(t *testing.T) {
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
seed = 984651320
|
seed = 984651320
|
||||||
maxFilterHeightRange = 100
|
maxFilterHeightRange = 100
|
||||||
@ -279,14 +276,13 @@ func TestSubscribeActorEvents(t *testing.T) {
|
|||||||
{"1.5 block speed", blockDelay * 3 / 2, false, -1},
|
{"1.5 block speed", blockDelay * 3 / 2, false, -1},
|
||||||
{"twice block speed", blockDelay * 2, false, -1},
|
{"twice block speed", blockDelay * 2, false, -1},
|
||||||
} {
|
} {
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
tc := tc
|
tc := tc
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
req := require.New(t)
|
req := require.New(t)
|
||||||
|
|
||||||
ctx, cancel := context.WithCancel(ctx)
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
mockClock.Set(time.Now())
|
mockClock.Set(time.Now())
|
||||||
mockFilterManager := newMockEventFilterManager(t)
|
mockFilterManager := newMockEventFilterManager(t)
|
||||||
allEvents := makeCollectedEvents(t, rng, filterStartHeight, eventsPerEpoch, finishHeight)
|
allEvents := makeCollectedEvents(t, rng, filterStartHeight, eventsPerEpoch, finishHeight)
|
||||||
@ -326,7 +322,10 @@ func TestSubscribeActorEvents(t *testing.T) {
|
|||||||
// Ticker to simulate both time and the chain advancing, including emitting events at
|
// Ticker to simulate both time and the chain advancing, including emitting events at
|
||||||
// the right time directly to the filter.
|
// the right time directly to the filter.
|
||||||
|
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
wg.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
for thisHeight := int64(currentHeight); ctx.Err() == nil; thisHeight++ {
|
for thisHeight := int64(currentHeight); ctx.Err() == nil; thisHeight++ {
|
||||||
ts, err := types.NewTipSet([]*types.BlockHeader{newBlockHeader(minerAddr, thisHeight)})
|
ts, err := types.NewTipSet([]*types.BlockHeader{newBlockHeader(minerAddr, thisHeight)})
|
||||||
req.NoError(err)
|
req.NoError(err)
|
||||||
@ -334,9 +333,9 @@ func TestSubscribeActorEvents(t *testing.T) {
|
|||||||
|
|
||||||
var eventsThisEpoch []*filter.CollectedEvent
|
var eventsThisEpoch []*filter.CollectedEvent
|
||||||
if thisHeight <= finishHeight {
|
if thisHeight <= finishHeight {
|
||||||
eventsThisEpoch = allEvents[(thisHeight-filterStartHeight)*eventsPerEpoch : (thisHeight-filterStartHeight+1)*eventsPerEpoch]
|
eventsThisEpoch = allEvents[(thisHeight-filterStartHeight)*eventsPerEpoch : (thisHeight-filterStartHeight+2)*eventsPerEpoch]
|
||||||
}
|
}
|
||||||
for i := 0; i < eventsPerEpoch; i++ {
|
for i := 0; i < eventsPerEpoch && ctx.Err() == nil; i++ {
|
||||||
if len(eventsThisEpoch) > 0 {
|
if len(eventsThisEpoch) > 0 {
|
||||||
mockFilter.sendEventToChannel(eventsThisEpoch[0])
|
mockFilter.sendEventToChannel(eventsThisEpoch[0])
|
||||||
eventsThisEpoch = eventsThisEpoch[1:]
|
eventsThisEpoch = eventsThisEpoch[1:]
|
||||||
@ -406,14 +405,14 @@ func TestSubscribeActorEvents(t *testing.T) {
|
|||||||
// cleanup
|
// cleanup
|
||||||
mockFilter.requireClearSubChannelCalledEventually(500 * time.Millisecond)
|
mockFilter.requireClearSubChannelCalledEventually(500 * time.Millisecond)
|
||||||
mockFilterManager.requireRemovedEventually(mockFilter.ID(), 500*time.Millisecond)
|
mockFilterManager.requireRemovedEventually(mockFilter.ID(), 500*time.Millisecond)
|
||||||
|
cancel()
|
||||||
|
wg.Wait() // wait for the chain to stop advancing
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSubscribeActorEvents_OnlyHistorical(t *testing.T) {
|
func TestSubscribeActorEvents_OnlyHistorical(t *testing.T) {
|
||||||
// Similar to TestSubscribeActorEvents but we set an explicit end that caps out at the current height
|
// Similar to TestSubscribeActorEvents but we set an explicit end that caps out at the current height
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
|
|
||||||
defer cancel()
|
|
||||||
const (
|
const (
|
||||||
seed = 984651320
|
seed = 984651320
|
||||||
maxFilterHeightRange = 100
|
maxFilterHeightRange = 100
|
||||||
@ -439,6 +438,8 @@ func TestSubscribeActorEvents_OnlyHistorical(t *testing.T) {
|
|||||||
{"1.5 block speed", 1.5, false},
|
{"1.5 block speed", 1.5, false},
|
||||||
{"twice block speed", 2, false},
|
{"twice block speed", 2, false},
|
||||||
} {
|
} {
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
tc := tc
|
tc := tc
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
@ -446,7 +447,7 @@ func TestSubscribeActorEvents_OnlyHistorical(t *testing.T) {
|
|||||||
|
|
||||||
mockClock.Set(time.Now())
|
mockClock.Set(time.Now())
|
||||||
mockFilterManager := newMockEventFilterManager(t)
|
mockFilterManager := newMockEventFilterManager(t)
|
||||||
allEvents := makeCollectedEvents(t, rng, filterStartHeight, eventsPerEpoch, currentHeight-1)
|
allEvents := makeCollectedEvents(t, rng, filterStartHeight, eventsPerEpoch, currentHeight)
|
||||||
mockFilter := newMockFilter(ctx, t, rng, allEvents)
|
mockFilter := newMockFilter(ctx, t, rng, allEvents)
|
||||||
mockFilterManager.expectInstall(abi.ChainEpoch(0), abi.ChainEpoch(currentHeight), cid.Undef, nil, nil, false, mockFilter)
|
mockFilterManager.expectInstall(abi.ChainEpoch(0), abi.ChainEpoch(currentHeight), cid.Undef, nil, nil, false, mockFilter)
|
||||||
|
|
||||||
@ -464,11 +465,10 @@ func TestSubscribeActorEvents_OnlyHistorical(t *testing.T) {
|
|||||||
|
|
||||||
// assume we can cleanly pick up all historical events in one go
|
// assume we can cleanly pick up all historical events in one go
|
||||||
receiveLoop:
|
receiveLoop:
|
||||||
for len(gotEvents) < len(allEvents) && ctx.Err() == nil {
|
for ctx.Err() == nil {
|
||||||
select {
|
select {
|
||||||
case e, ok := <-eventChan:
|
case e, ok := <-eventChan:
|
||||||
if tc.expectComplete || ok {
|
if ok {
|
||||||
req.True(ok)
|
|
||||||
gotEvents = append(gotEvents, e)
|
gotEvents = append(gotEvents, e)
|
||||||
mockClock.Add(time.Duration(float64(blockDelay) * tc.blockTimeToComplete / float64(len(allEvents))))
|
mockClock.Add(time.Duration(float64(blockDelay) * tc.blockTimeToComplete / float64(len(allEvents))))
|
||||||
// no need to advance the chain, we're also testing that's not necessary
|
// no need to advance the chain, we're also testing that's not necessary
|
||||||
|
Loading…
Reference in New Issue
Block a user