@@ -36,7 +36,7 @@ import {AssetGroupSelector} from '../graphql/types';
36
36
import { useUpdatingRef } from '../hooks/useUpdatingRef' ;
37
37
import { useBlockTraceUntilTrue } from '../performance/TraceContext' ;
38
38
import { fetchPaginatedData } from '../runs/fetchPaginatedBucketData' ;
39
- import { CacheManager } from '../search/useIndexedDBCachedQuery' ;
39
+ import { getCacheManager } from '../search/useIndexedDBCachedQuery' ;
40
40
import { SyntaxError } from '../selection/CustomErrorListener' ;
41
41
import { LoadingSpinner } from '../ui/Loading' ;
42
42
@@ -54,7 +54,7 @@ export function useCachedAssets({
54
54
} ) {
55
55
const { localCacheIdPrefix} = useContext ( AppContext ) ;
56
56
const cacheManager = useMemo (
57
- ( ) => new CacheManager < AssetTableFragment [ ] > ( `${ localCacheIdPrefix } /allAssetNodes` ) ,
57
+ ( ) => getCacheManager < AssetTableFragment [ ] > ( `${ localCacheIdPrefix } /allAssetNodes` ) ,
58
58
[ localCacheIdPrefix ] ,
59
59
) ;
60
60
@@ -69,6 +69,11 @@ export function useCachedAssets({
69
69
return { cacheManager} ;
70
70
}
71
71
72
+ // Module-level cache variables
73
+ let globalAssetsPromise : Promise < Asset [ ] > | null = null ;
74
+ let cachedAllAssets : Asset [ ] | null = null ;
75
+ let cachedAssetsFetchTime : number = 0 ;
76
+
72
77
export function useAllAssets ( {
73
78
batchLimit = DEFAULT_BATCH_LIMIT ,
74
79
groupSelector,
@@ -77,14 +82,16 @@ export function useAllAssets({
77
82
const [ { error, assets} , setErrorAndAssets ] = useState < {
78
83
error : PythonErrorFragment | undefined ;
79
84
assets : Asset [ ] | undefined ;
80
- } > ( { error : undefined , assets : undefined } ) ;
85
+ } > ( { error : undefined , assets : cachedAllAssets || undefined } ) ;
81
86
82
87
const assetsRef = useUpdatingRef ( assets ) ;
83
88
84
89
const { cacheManager} = useCachedAssets ( {
85
90
onAssetsLoaded : useCallback (
86
91
( data ) => {
92
+ console . log ( 'onAssetsLoaded' , data ) ;
87
93
if ( ! assetsRef . current ) {
94
+ console . log ( 'onAssetsLoaded' , data ) ;
88
95
setErrorAndAssets ( {
89
96
error : undefined ,
90
97
assets : data ,
@@ -95,69 +102,57 @@ export function useAllAssets({
95
102
) ,
96
103
} ) ;
97
104
98
- const allAssetsQuery = useCallback ( async ( ) => {
99
- if ( groupSelector ) {
100
- return ;
105
+ // Query function for all assets
106
+ const fetchAllAssets = useCallback ( async ( ) => {
107
+ if ( cachedAllAssets && Date . now ( ) - cachedAssetsFetchTime < 6000 ) {
108
+ return cachedAllAssets ;
101
109
}
102
- try {
103
- const data = await fetchPaginatedData ( {
104
- async fetchData ( cursor : string | null | undefined ) {
105
- const { data} = await client . query <
106
- AssetCatalogTableQuery ,
107
- AssetCatalogTableQueryVariables
108
- > ( {
109
- query : ASSET_CATALOG_TABLE_QUERY ,
110
- fetchPolicy : 'no-cache' ,
111
- variables : {
112
- cursor,
113
- limit : batchLimit ,
114
- } ,
115
- } ) ;
116
-
117
- if ( data . assetsOrError . __typename === 'PythonError' ) {
118
- return {
119
- data : [ ] ,
120
- cursor : undefined ,
121
- hasMore : false ,
122
- error : data . assetsOrError ,
123
- } ;
124
- }
125
- const assets = data . assetsOrError . nodes ;
126
- const hasMoreData = assets . length === batchLimit ;
127
- const nextCursor = data . assetsOrError . cursor ;
128
- return {
129
- data : assets ,
130
- cursor : nextCursor ,
131
- hasMore : hasMoreData ,
132
- error : undefined ,
133
- } ;
134
- } ,
135
- } ) ;
136
- cacheManager . set ( data , AssetCatalogTableQueryVersion ) ;
137
- setErrorAndAssets ( { error : undefined , assets : data } ) ;
138
- } catch ( e : any ) {
139
- if ( e . __typename === 'PythonError' ) {
140
- setErrorAndAssets ( ( { assets} ) => ( {
141
- error : e ,
142
- assets,
143
- } ) ) ;
144
- }
110
+ if ( ! globalAssetsPromise ) {
111
+ globalAssetsPromise = ( async ( ) => {
112
+ const allAssets = await fetchPaginatedData ( {
113
+ async fetchData ( cursor : string | null | undefined ) {
114
+ const { data} = await client . query <
115
+ AssetCatalogTableQuery ,
116
+ AssetCatalogTableQueryVariables
117
+ > ( {
118
+ query : ASSET_CATALOG_TABLE_QUERY ,
119
+ fetchPolicy : 'no-cache' ,
120
+ variables : { cursor, limit : batchLimit } ,
121
+ } ) ;
122
+ if ( data . assetsOrError . __typename === 'PythonError' ) {
123
+ return {
124
+ data : [ ] ,
125
+ cursor : undefined ,
126
+ hasMore : false ,
127
+ error : data . assetsOrError ,
128
+ } ;
129
+ }
130
+ const assets = data . assetsOrError . nodes ;
131
+ const hasMoreData = assets . length === batchLimit ;
132
+ const nextCursor = data . assetsOrError . cursor ;
133
+ return { data : assets , cursor : nextCursor , hasMore : hasMoreData , error : undefined } ;
134
+ } ,
135
+ } ) ;
136
+ cachedAssetsFetchTime = Date . now ( ) ;
137
+ cachedAllAssets = allAssets ;
138
+ cacheManager . set ( allAssets , AssetCatalogTableQueryVersion ) ;
139
+ globalAssetsPromise = null ;
140
+ return allAssets ;
141
+ } ) ( ) ;
145
142
}
146
- } , [ batchLimit , cacheManager , client , groupSelector ] ) ;
143
+ return globalAssetsPromise ;
144
+ } , [ batchLimit , cacheManager , client ] ) ;
147
145
146
+ // Query function for group assets
148
147
const groupQuery = useCallback ( async ( ) => {
149
- if ( ! groupSelector ) {
150
- return ;
151
- }
152
- function onData ( queryData : typeof data ) {
148
+ const cacheKey = JSON . stringify ( groupSelector ) ;
149
+ if ( groupTableCache . has ( cacheKey ) ) {
150
+ const cachedData = groupTableCache . get ( cacheKey ) ;
153
151
setErrorAndAssets ( {
154
152
error : undefined ,
155
- assets : queryData . assetNodes ?. map ( definitionToAssetTableFragment ) ,
153
+ assets : cachedData . assetNodes ?. map ( definitionToAssetTableFragment ) ,
156
154
} ) ;
157
- }
158
- const cacheKey = JSON . stringify ( groupSelector ) ;
159
- if ( groupTableCache . has ( cacheKey ) ) {
160
- onData ( groupTableCache . get ( cacheKey ) ) ;
155
+ return ;
161
156
}
162
157
const { data} = await client . query <
163
158
AssetCatalogGroupTableQuery ,
@@ -168,23 +163,43 @@ export function useAllAssets({
168
163
fetchPolicy : 'no-cache' ,
169
164
} ) ;
170
165
groupTableCache . set ( cacheKey , data ) ;
171
- onData ( data ) ;
172
- } , [ groupSelector , client ] ) ;
166
+ setErrorAndAssets ( {
167
+ error : undefined ,
168
+ assets : data . assetNodes ?. map ( definitionToAssetTableFragment ) ,
169
+ } ) ;
170
+ } , [ client , groupSelector ] ) ;
173
171
174
- const query = groupSelector ? groupQuery : allAssetsQuery ;
172
+ const query = groupSelector ? groupQuery : fetchAllAssets ;
175
173
176
174
useEffect ( ( ) => {
177
- query ( ) ;
178
- } , [ query ] ) ;
175
+ if ( groupSelector ) {
176
+ groupQuery ( ) ;
177
+ } else {
178
+ fetchAllAssets ( )
179
+ . then ( ( allAssets ) => setErrorAndAssets ( { error : undefined , assets : allAssets } ) )
180
+ . catch ( ( e : any ) => {
181
+ if ( e . __typename === 'PythonError' ) {
182
+ setErrorAndAssets ( ( prev ) => ( { error : e , assets : prev . assets } ) ) ;
183
+ }
184
+ } ) ;
185
+ }
186
+ } , [ fetchAllAssets , groupQuery , groupSelector ] ) ;
179
187
180
- return useMemo ( ( ) => {
181
- return {
188
+ const assetsByAssetKey = useMemo (
189
+ ( ) => Object . fromEntries ( assets ?. map ( ( asset ) => [ tokenForAssetKey ( asset . key ) , asset ] ) ?? [ ] ) ,
190
+ [ assets ] ,
191
+ ) ;
192
+
193
+ return useMemo (
194
+ ( ) => ( {
182
195
assets,
196
+ assetsByAssetKey,
183
197
error,
184
198
loading : ! assets && ! error ,
185
199
query,
186
- } ;
187
- } , [ assets , error , query ] ) ;
200
+ } ) ,
201
+ [ assets , assetsByAssetKey , error , query ] ,
202
+ ) ;
188
203
}
189
204
190
205
interface AssetCatalogTableProps {
@@ -253,7 +268,7 @@ export const AssetsCatalogTable = ({
253
268
[ filtered , prefixPath , view ] ,
254
269
) ;
255
270
256
- const refreshState = useRefreshAtInterval ( {
271
+ const refreshState = useRefreshAtInterval < any > ( {
257
272
refresh : query ,
258
273
intervalMs : 4 * FIFTEEN_SECONDS ,
259
274
leading : true ,
0 commit comments