Skip to content

Commit 6c8bcda

Browse files
authored
[Flight] Clarify Semantics for Awaiting Cached Data (facebook#33438)
Technically the async call graph spans basically all the way back to the start of the app potentially, but we don't want to include everything. Similarly we don't want to include everything from previous components in every child component. So we need some heuristics for filtering out data. We roughly want to be able to inspect is what might contribute to a Suspense loading sequence even if it didn't this time e.g. due to a race condition. One flaw with the previous approach was that awaiting a cached promise in a sibling that happened to finish after another sibling would be excluded. However, in a different race condition that might end up being used so I wanted to include an empty "await" in that scenario to have some association from that component. However, for data that resolved fully before the request even started, it's a little different. This can be things that are part of the start up sequence of the app or externally cached data. We decided that this should be excluded because it doesn't contribute to the loading sequence in the expected scenario. I.e. if it's cached. Things that end up being cache misses would still be included. If you want to test externally cached data misses, then it's up to you or the framework to simulate those. E.g. by dropping the cache. This also helps free up some noise since static / cached data can be excluded in visualizations. I also apply this principle to forwarding debug info. If you reuse a cached RSC payload, then the Server Component render time and its awaits gets clamped to the caller as if it has zero render/await time. The I/O entry is still back dated but if it was fully resolved before we started then it's completely excluded.
1 parent b367b60 commit 6c8bcda

File tree

3 files changed

+602
-177
lines changed

3 files changed

+602
-177
lines changed

packages/react-client/src/__tests__/ReactFlight-test.js

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2826,46 +2826,46 @@ describe('ReactFlight', () => {
28262826
expect(getDebugInfo(thirdPartyChildren[0])).toEqual(
28272827
__DEV__
28282828
? [
2829-
{time: 14},
2829+
{time: 22}, // Clamped to the start
28302830
{
28312831
name: 'ThirdPartyComponent',
28322832
env: 'third-party',
28332833
key: null,
28342834
stack: ' in Object.<anonymous> (at **)',
28352835
props: {},
28362836
},
2837-
{time: 15},
2837+
{time: 22},
28382838
{time: 23}, // This last one is when the promise resolved into the first party.
28392839
]
28402840
: undefined,
28412841
);
28422842
expect(getDebugInfo(thirdPartyChildren[1])).toEqual(
28432843
__DEV__
28442844
? [
2845-
{time: 16},
2845+
{time: 22}, // Clamped to the start
28462846
{
28472847
name: 'ThirdPartyLazyComponent',
28482848
env: 'third-party',
28492849
key: null,
28502850
stack: ' in myLazy (at **)\n in lazyInitializer (at **)',
28512851
props: {},
28522852
},
2853-
{time: 17},
2853+
{time: 22},
28542854
]
28552855
: undefined,
28562856
);
28572857
expect(getDebugInfo(thirdPartyChildren[2])).toEqual(
28582858
__DEV__
28592859
? [
2860-
{time: 12},
2860+
{time: 22},
28612861
{
28622862
name: 'ThirdPartyFragmentComponent',
28632863
env: 'third-party',
28642864
key: '3',
28652865
stack: ' in Object.<anonymous> (at **)',
28662866
props: {},
28672867
},
2868-
{time: 13},
2868+
{time: 22},
28692869
]
28702870
: undefined,
28712871
);
@@ -2967,15 +2967,15 @@ describe('ReactFlight', () => {
29672967
expect(getDebugInfo(thirdPartyFragment.props.children)).toEqual(
29682968
__DEV__
29692969
? [
2970-
{time: 12},
2970+
{time: 19}, // Clamp to the start
29712971
{
29722972
name: 'ThirdPartyAsyncIterableComponent',
29732973
env: 'third-party',
29742974
key: null,
29752975
stack: ' in Object.<anonymous> (at **)',
29762976
props: {},
29772977
},
2978-
{time: 13},
2978+
{time: 19},
29792979
]
29802980
: undefined,
29812981
);

0 commit comments

Comments
 (0)