Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adjust actor event API after review #11649

Merged

Conversation

rvagg
Copy link
Member

@rvagg rvagg commented Feb 23, 2024

From review discussions in #11618, WIP

  • TipSetCid -> TipSetKey (this is still nillable on the filter because omitempty doesn't play as nice, but should confirm that this is reasonable given existing API precedents)
  • EmitterAddr -> Emitter
    • Document that this will end up being an ID address in the future
  • Epoch -> Height
  • FromHeight and ToHeight take nillable abi.ChainEpochs (ints) that must be >= 0 when set
  • Heights are interpreted as being exact, there is no longer a "whatever you have"
    • Documented that this will be strict in the future after we can say for sure whether or not we have those events
  • Removed Prefill option in SubscribeActorEvents API and collapsed the argument structure, FromHeight will do that work implicitly.
  • nil for FromHeight will:
    • For GetActorEvents be interpreted to mean "current epoch"
    • For SubscribeActorEvents will be interpreted to mean "next epoch" (TODO: confirm we want to do this because current impl I think will just do a prefill of current epoch)
  • nil for ToHeight will:
    • For GetActorEvents be interpreted to mean "current epoch"
    • For SubscribeActorEvents be interpreted to mean that there is no height-based stopping condition
  • EnableActorEventsAPI config option has been moved to a new ActorEvents top-level section; could also just be Events as per previous discussions? Events section. (future TODO of moving other events config options into there so it won't be lonely)
  • Halt SubscribeActorEvents when we ToHeight is set and we have reached that position; currently will just stay open giving you nothing.
  • Add Limit option to the filter to limit the number of epochs to process, counting from whatever the start epoch is calculated to be (Discussed here, I'm not sure I see a use for this given the global limit that's in place and the way you can use From and To as a user).
  • Make send-buffer handling for SubscribeActorEvents smarter:
    • Prefill should have a minimum rate that is acceptable to send events, abort if they are too slow (perhaps calculate based on the speed at which you receive an epoch—you should be able to catch up in reasonable time)
    • Ongoing subscription shouldn't end up lagging but should be able to deal with large numbers of events per epoch
    • Tests for all this fancy footwork

@rvagg rvagg force-pushed the rvagg/actor-events-api-tweaks branch from 47548b4 to ac997e6 Compare February 23, 2024 11:46
@rvagg rvagg force-pushed the rvagg/actor-events-api-tweaks branch from ac997e6 to 90f1988 Compare February 26, 2024 01:27
@rvagg rvagg force-pushed the rvagg/actor-events-api-tweaks branch from 538dd6f to 6a34c7d Compare February 26, 2024 04:17
@rvagg rvagg force-pushed the rvagg/actor-events-api-tweaks branch from 6a34c7d to 8a3a461 Compare February 26, 2024 04:35
}
var buffer []*types.ActorEvent
const α = 0.2 // decay factor for the events per height EMA
var eventsPerHeightEma float64 = 256 // exponential moving average of events per height, initially guess at 256
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One problem we encounter at this point is if we've spent a lot of time sending historical data and we have a lot of new data backed up and ready to go we may blow our budget (almost) immediately. We could be more forgiving up front (according to what terms? how complicated do we want to get?). Or we could just say "bad luck, you shouldn't have requested so much historical data, use GetActorEvents for that.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See above. IMO, we wait one block time (30s) then give up.

@rvagg rvagg marked this pull request as ready for review February 26, 2024 10:28
@rvagg rvagg requested a review from a team as a code owner February 26, 2024 10:28
@rvagg rvagg requested review from snadrus and aarshkshah1992 and removed request for a team February 26, 2024 10:28
@rvagg
Copy link
Member Author

rvagg commented Feb 26, 2024

@Stebalien I'm going to call this one "ready for review", but it's lacking some unit testing for the new stream backlog handling code (and maybe some other minor things). I don't want to invest in figuring out how to build something for that without getting agreement on the approach.

@rvagg
Copy link
Member Author

rvagg commented Feb 26, 2024

Alternatively, we can just merge this in to #11618 and go from there. Whatever's easiest to review.

// If `TipSetCid` is present in the filter criteria, then neither `FromEpoch` nor `ToEpoch` are allowed.
TipSetCid *cid.Cid `json:"tipsetCid,omitempty"`
// If `TipSetKey` is legt empty in the filter criteria, then neither `FromHeight` nor `ToHeight` are allowed.
TipSetKey *TipSetKey `json:"tipsetKey,omitempty"`
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pointer here may not be idiomatic; I just wanted to avoid an unnecessary [] in the json form, mainly. I think maybe if [] is omitted on the input side that it may still resolve to the zero-value here, I'm not sure.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pointer is fine. I'm actually kind of surprised we don't marshal these to strings... but ok.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if [] is omitted on the input side that it may still resolve to the zero-value here, I'm not sure.

It will.

Copy link
Member

@Stebalien Stebalien left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ideally we'd be able to:

  1. Query for historical events.
  2. Send them.
  3. Query for more.
  4. Send them.
  5. Etc...

Then, when we're all caught up, we'd subscribe. But that seems like a lot of work. Also, I assume the limits will prevent that from really being an issues (we should never have to send that many events.

// If `TipSetCid` is present in the filter criteria, then neither `FromEpoch` nor `ToEpoch` are allowed.
TipSetCid *cid.Cid `json:"tipsetCid,omitempty"`
// If `TipSetKey` is legt empty in the filter criteria, then neither `FromHeight` nor `ToHeight` are allowed.
TipSetKey *TipSetKey `json:"tipsetKey,omitempty"`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pointer is fine. I'm actually kind of surprised we don't marshal these to strings... but ok.

// If `TipSetCid` is present in the filter criteria, then neither `FromEpoch` nor `ToEpoch` are allowed.
TipSetCid *cid.Cid `json:"tipsetCid,omitempty"`
// If `TipSetKey` is legt empty in the filter criteria, then neither `FromHeight` nor `ToHeight` are allowed.
TipSetKey *TipSetKey `json:"tipsetKey,omitempty"`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if [] is omitted on the input side that it may still resolve to the zero-value here, I'm not sure.

It will.

node/impl/full/actor_events.go Show resolved Hide resolved
node/impl/full/actor_events.go Outdated Show resolved Hide resolved
node/impl/full/actor_events.go Outdated Show resolved Hide resolved
Comment on lines 220 to 225
ticker := time.NewTicker(time.Second)
defer ticker.Stop()

const maxSlowTicks = 3 // slightly forgiving, allow 3 slow ticks (seconds) before giving up
slowTicks := 0
sentEvents := 0.0
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given that we're doing a single batch here, there's no need for a ticker. We can just have a global timeout.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(I mean, the right way to handle slow reads is in the JSON-RPC library... anyways)

}
var buffer []*types.ActorEvent
const α = 0.2 // decay factor for the events per height EMA
var eventsPerHeightEma float64 = 256 // exponential moving average of events per height, initially guess at 256
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See above. IMO, we wait one block time (30s) then give up.

Use BlockDelay as the window for receiving events on the SubscribeActorEvents
channel. We expect the user to have received the initial batch of historical
events (if any) in one block's time. For real-time events we expect them to
not fall behind by roughly one block's time.
@rvagg rvagg force-pushed the rvagg/actor-events-api-tweaks branch from 31feee3 to 9fd3e02 Compare March 1, 2024 06:37
@rvagg
Copy link
Member Author

rvagg commented Mar 1, 2024

Pretty rough coming up with nice unit tests for SubscribeActorEvents given they're time-based, but I think I got there.

In response to last round of feedback we have two things for keeping track of "are you getting the events fast enough":

  • Historical events must all be received within one block's time, you have ~30s to receive what you've asked for before we consider you delinquent (really, use GetActorEvents for historical stuff).
  • For real-time events we (conceptually) keep track of the oldest event you haven't yet received and if it takes you longer than a block's time to get it, then you're delinquent and you get disconnected.

Basically: don't fall more than ~one block's time behind in receiving your events and you'll be dine.

Bunch of related refactorings in the last commit.

@rvagg
Copy link
Member Author

rvagg commented Mar 1, 2024

Going to take this back to #11618 and proceed from there

@rvagg rvagg merged commit 4abc21e into rvagg/feat/builtin-actor-events Mar 1, 2024
89 of 90 checks passed
@rvagg rvagg deleted the rvagg/actor-events-api-tweaks branch March 1, 2024 07:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: ☑️ Done (Archive)
Development

Successfully merging this pull request may close these issues.

2 participants