-
Notifications
You must be signed in to change notification settings - Fork 610
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
Fix double render issue (Issue #257) #492
Fix double render issue (Issue #257) #492
Conversation
Codecov Report
@@ Coverage Diff @@
## main #492 +/- ##
==========================================
- Coverage 57.06% 57.03% -0.02%
==========================================
Files 178 176 -2
Lines 7414 7407 -7
Branches 211 226 +15
==========================================
- Hits 4230 4224 -6
+ Misses 2842 2835 -7
- Partials 342 348 +6
Continue to review full report at Codecov.
|
Hey, thank you for your contribution! I think what you can do is to scope the flamebearer to the view in the store, something like this:
which we would then pass as a prop here -> https://github.com/pyroscope-io/pyroscope/blob/main/webapp/javascript/components/ComparisonApp.jsx#L36 That wouldn't be super optimized (for example, |
@eh-am Hi, Thanks a lot for the help, as Sorry for any inconvenience. |
Changed `RECEIVE_TIMELINE` case to receive scope and set appropriate key.
…action and `receiveTimelineAction`.
…ype` & `viewSide` props. Removed previous function that are not needed.
Added logic on `ComparisonApp.jsx` to check for changes on leftRenderURL and rightRenderURL and fetch appropriate timeline.
Hi, Sorry for the delay, did what was previously discussed on this thread and It's working, any changes required or improvements opportunities just let me know. Thanks. |
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.
Hey, nice work! Don't be sorry, I'm enjoying these PRs!
So I've added a couple comments code wise, I think you may be interested in them.
That being said, I think we gonna need one more iteration on this code.
I am not a biiiiiiiig fan of adding flags and doing different things based on these flags, here being the viewType
and viewSide
.
You know what we can do that will simplify this a bit? (And by simplify I mean make it more obvious to the reader.)
a) Dispatch the data from the parent component, pretty much as you have been doing, for example, the comparison page (we would be doing this for all kinds, single, comparison, diff ):
(ComparisonApp.jsx)
actions.fetchTimeline(diffRenderURL, 'comparison');
But then, instead of calling this generic action fetchTimeline
, let's call fetchComparisonApp
(a brand new action) instead.
actions.loadComparison(diffRenderURL, 'comparison');
b) That gives us much more assurance on what we are acting on, for example here in the comparison diff we can REQUIRE the presence of the viewSide
, since we know we need it to be "both" | "left" | "right"
.
actions.loadComparison(diffRenderURL, 'diff', 'both');
c) Now that we know what we are dealing with, we don't have to run deltaDiffWrapper
, except for diff
. Also adding leftTicks
and rightTicks
, that is also something that's only relevant for diff
.
In our example (comparison), in the reducer we have something like:
case RECEIVE_COMPARISON:
const { viewSide } = action.payload;
const { flamebearer, timeline } = data;
let left, right;
switch (viewSide) {
// we are only loading left
// right comes from the existing state
case 'left': {
left = action.payload.left;
right = state.comparison.right;
break;
}
// we are only loading right
// left comes from the existing state
case 'right': {
right = action.payload.right;
left = state.comparison.left;
break;
}
// we are loading both
case 'right': {
right = action.payload.right;
left = action.payload.left;
break;
}
}
return {
...state,
timeline: decodeTimelineData(timeline),
comparison: {
left,
right,
}
}
d) Then the flamegraphRenderer is dumb, as in it doesn't communicate with the state.
It only receives a flamegraph from a prop and that's it.
ComparisonApp.jsx
(props.comparison comes from the state)
<FlameGraphRenderer
flamebearer={props.comparison.left}
viewType="double"
viewSide="left"
data-testid="flamegraph-renderer-left"
/>
<FlameGraphRenderer
flamebearer={props.comparison.right}
viewType="double"
viewSide="right"
data-testid="flamegraph-renderer-right"
/>
Let me know if this too much to do at once, we can definitely do this in smaller, discrete steps!
Thank you @eh-am! Don't worry, It does seem a lot to do but I think I can handle it. I'll start by adding the new actions and making the FlameGraphRenderer dumb and then will work on the minor code comments. If there is anything else I could improve just let me know. |
I just realized I mixed |
…-double-render-issue
…sed correct flamebearer data to dumb `FlameGraphRenderer`
Hey @eh-am, If I'm not mistaken I have covered all the changes we discussed, could you please have a look at it ? Please let me know if there's anything, not the way you expected. |
Hey @gabrielzezze! It seems the flamegraph is a bit broken now: The cypress tests are also failing (which I assume it's because the flamegraph is a bit broken): I had a quick look at the code and it seems it's breaking because So what we can do is to run .then((response) => response.json())
.then((data) => {
const calculatedLevels = deltaDiffWrapper(
data.flamebearer.format,
data.flamebearer.levels
);
data.flamebearer.levels = calculatedLevels;
return data;
}) We gonna repeat the same thing 3 times, but it's fine since I am going to refactor all these fetches into a dataService some time in the future. |
The other thing with the comparison page is that the logic is a bit different:
Using hooks, would be something like this useEffect(() => {
actions.fetchComparisonAppData(renderURL, 'left');
}, [renderURL]);
const mapStateToProps = (state) => ({
...state,
renderURL: buildRenderURL(state),
leftRenderURL: buildRenderURL(state, state.leftFrom, state.leftUntil),
rightRenderURL: buildRenderURL(state, state.rightFrom, state.rightUntil),
});
Let me know if you have any questions! |
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 a couple comments!
…-double-render-issue
…/pyroscope into 257-fix-double-render-issue
…key only when `both` viewSide is passed.
…controller was aborting the other view side fetching
Hi @eh-am, Sorry for the delay, the national holiday got me occupied but now that's over. So what I did was:
I made some checks of my own but was unable to run the Cypress tests locally, let me know if there's anything I've missed. |
I just saw the Cypress tests failed again...I'll work to fix it by tomorrow. |
@gabrielzezze Thank you again! Don't worry about that cypress test! It's flaky and I will probably remove it sometime soon. I did a quick test here and everything looks good, except for the Diff view which is a bit messed up (see screenshot) |
Hey @gabrielzezze , turns out it was a silly thing. I pushed in another branch for you: Everything else looks pretty good! |
Hey @eh-am, thanks for the help! As you pointed out in your branch I was calling I really enjoyed the process of making this PR, thanks for all the support! |
Fix on issue #257.
The duplicate request was caused by fetching the timeline inside
FlameGraphRenderer
component and It's parent.The issue was fixed by removing the
FlameGraphRenderer
fetching and pulling the data from the redux store, this change required the addition of extra keys in the redux store to scope theflamebearer
data as discussed in the thread below to keep the the comparison view and comparison diff functionality.Any suggestions or tips are welcome.
Thanks.