-
Notifications
You must be signed in to change notification settings - Fork 535
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
Simplfied SummarizerNode:refreshLatestSummary logic #17106
Conversation
Are you saying that in today's logging, it's already redundant? Would be interesting to see an example query from Msft-internal telemetry (but up to you whether it's worth taking the time) |
packages/runtime/container-runtime/src/summary/summarizerNode/summarizerNode.ts
Show resolved
Hide resolved
⯆ @fluid-example/bundle-size-tests: -938 Bytes
Baseline commit: 74f413a |
Here's an example:
|
There are scenarios where we log PendingSummaryNotFound but do not log the refreshLatestSummary. Ex. if (this.referenceSequenceNumber >= summaryRefSeq) { I sent you a query in which we log the pendingSummaryNotFound much more frequently than the refreshLatestSummary - I would keep it for now, TBH |
46dcbf3
to
682762e
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
* 2. The latest summary was updated and the summary corresponding to the params was being tracked. | ||
* | ||
* 3. The latest summary was updated but the summary corresponding to the params was not tracked. | ||
* @returns true if the summary is tracked by this node, false otherwise. | ||
*/ | ||
public async refreshLatestSummary( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do you think of renaming this here and elsewhere to handleSummaryAck
or onSummaryAck
or something?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reason why - Besides the obvious (we don't do any "refreshing", just tracking), the return value is typically called isSummaryTracked
, but without all the context we have this reads kind of strangely:
const isSummaryTracked = refreshLatestSummary(...);
How about this:
const pendingSummaryFound = matchAckWithPendingSummary(...);
Or something similar?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would rather not do any such renames in this PR for 3 reasons:
- The PR is already big and it will become even bigger.
- It's will be a breaking change because the call from RunningSummarizer to ContainerRuntime is on a public interface.
- We do "refresh" the latest summary state. It's more of an update but refresh seems fine to me. I would be fine with calling it
updateLatestSummaryState
or something like that.
@@ -846,8 +845,8 @@ export class GarbageCollector implements IGarbageCollector { | |||
* Called to refresh the latest summary state. This happens when either a pending summary is acked or a snapshot | |||
* is downloaded and should be used to update the state. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Update comment
@@ -267,28 +266,23 @@ export class GCSummaryStateTracker { | |||
* Called to refresh the latest summary state. This happens when either a pending summary is acked or a snapshot | |||
* is downloaded and should be used to update the state. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
update comment
this.wasGCRunInLatestSummary = this.configs.shouldRunGC; | ||
} | ||
|
||
if (!result.latestSummaryUpdated || !this.configs.shouldRunGC) { | ||
if (!isSummaryTracked || !this.configs.shouldRunGC) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: Instead of this early return, I think you can just nest an if (this.configs.shouldRunGC)
inside the above if statement and put the code in there. Might be clearer. Or put this early return up top to reduce nesting.
Like this:
if (!isSummaryTracked) {
return;
}
this.wasGCRunInLatestSummary = this.configs.shouldRunGC;
if (this.configs.shouldRunGC) {
// The rest of the stuff
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed it. It looks pretty much the same TBH.
} | ||
|
||
// If the summary for which refresh is called is older than the latest tracked summary, ignore it. | ||
if (this.referenceSequenceNumber >= summaryRefSeq) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Observation: This case is no longer addressed by this function. It's up to the caller. This is probably fine, but I'd want us to think really carefully about the global state here, since this.referenceSequenceNumber
can change throughout this flow.
I think it's fine because it only changes if we are tracking the incoming summary, in which case before his code would be unreachable anyway. And if we're not tracking, then it doesn't change, so it's fine for the caller to check.
Sound correct? Hopefully test coverage helps here too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Weird that this was >=
. Not that they should be able to be equal but not the same (in which case it would be tracked). But you never know what could happen with Summaries!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This check is still there:
if (summaryRefSeq > this.referenceSequenceNumber) {
isSummaryNewer = true;
}
isSummaryNewer
is not returned because the caller has the information to gather this information. I could change it to return this value but I don't think its needed (infact I had it this way in my local repo and changed it).
IMO, the caller should decide what to do based on the return value isSummaryTracked
. If the summary is tracked, the latest summary information (referenceSequenceNumber) will be updated and if not, it won't be.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added isSummaryNewer
to the return of this function and check that at the call site.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm curious Why you brought it back? I thought it was fine after I thought out loud about it. It was just a little hard to trace through the diff.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was on the fence about keeping it vs removing it from the point of view of not making significant changes in one go. With you comment, it seemed like it added some confusion so I added it back. We can remove it later if needed.
* current summary that is tracked, but this summarizer runtime did not produce/track that summary. Thus | ||
* it needs to refresh its state. Today refresh is done by fetching the latest snapshot to update the cache | ||
* and then close as the current main client is likely to be re-elected as the parent summarizer again. | ||
*/ | ||
if (result.latestSummaryUpdated && !result.wasSummaryTracked) { | ||
if (!isSummaryTracked && summaryRefSeq > this.summarizerNode.referenceSequenceNumber) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: Consider inverting this to put the GC call (+early return) under the `if`` and reduce nesting of all this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And it makes me curious if we even need to notify GC in the case where the summary wasn't tracked but was old. Going to read that code again now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you pass false the GC code is a no-op. So we can remove the param from the GC code and this can be
if (isSummaryTracked) {
await this.garbageCollector.refreshLatestSummary();
}
else if (summaryRefSeq > this.summarizerNode.referenceSequenceNumber) {
// the existing fetch-then-close block
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
side note - no GC test passed false for that param :P
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's weird that the closeStaleSummarizer
function doesn't thrown an error but disposes the container and just continues. That's why it has to still call into GC in that scenario as well. You are right that the logic in GC is no-op but I don't want container runtime to assume that. it does the regular flow and GC decides what it wants to do.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM! I left some suggestions for renaming/refactoring. Feel free to punt for this and one of us can do another PR if we like the changes.
Description
#16657 removed the logic to refresh a summary's state by downloading a snapshot. With it gone, summarizer node (and rest of the system) only updates state from a summary that it was tracking. This PR simplifies the logic in
SummarizerNode::refreshLatestSummary
to account for this. It also renames the properties in the returned object to give the caller more context on what happened and what action it can take.Additionally, it removes logging the
PendingSummaryNotFound
telemetry. It is currently logged every time the summarizer loaded for the summary that is loaded from. The reason is that it processes the ack for the summary is loaded from and since the summary was not generated by this instance of the summarizer, this event is logged. Instead, added a propertypendingSummaryTracked
to the refreshLatestSummary_end event.AB#4435