10
10
DBPagination ,
11
11
DBResponse ,
12
12
)
13
+ from services .ui_backend_service .data .cache .card_cache_manager import wait_until_card_is_ready , CARD_API_HTML_WAIT_TIME
14
+ from services .ui_backend_service .data .cache .card_cache_manager import list_cards as list_cards_from_cache
15
+ import time
13
16
from aiohttp import web
17
+ import asyncio
14
18
15
19
16
20
class CardsApi (object ):
17
21
def __init__ (self , app , db , cache = None ):
18
22
self .db = db
19
- self .cache = getattr (cache , "artifact_cache" , None )
20
-
23
+ self .cache = getattr (cache , "card_cache" , None )
21
24
app .router .add_route (
22
25
"GET" ,
23
26
"/flows/{flow_id}/runs/{run_number}/steps/{step_name}/tasks/{task_id}/cards" ,
@@ -91,8 +94,7 @@ async def get_cards_list_for_task(self, request):
91
94
if not task :
92
95
return web_response (404 , {"data" : []})
93
96
94
- invalidate_cache = query_param_enabled (request , "invalidate" )
95
- cards = await get_cards_for_task (self .cache , task , invalidate_cache )
97
+ cards = await get_card_list (self .cache , task , max_wait_time = 1 )
96
98
97
99
if cards is None :
98
100
# Handle edge: Cache failed to return anything, even errors.
@@ -104,7 +106,6 @@ async def get_cards_list_for_task(self, request):
104
106
{"id" : data ["id" ], "hash" : hash , "type" : data ["type" ]}
105
107
for hash , data in cards .items ()
106
108
]
107
-
108
109
# paginate list of cards
109
110
limit , page , offset = get_pagination_params (request )
110
111
_pages = max (len (card_hashes ) // limit , 1 )
@@ -141,31 +142,31 @@ async def get_card_content_by_hash(self, request):
141
142
schema:
142
143
$ref: '#/definitions/ResponsesError405'
143
144
"""
144
-
145
145
hash = request .match_info .get ("hash" )
146
146
task = await self .get_task_by_request (request )
147
147
if not task :
148
148
return web .Response (
149
149
content_type = "text/html" , status = 404 , body = "Task not found."
150
150
)
151
- invalidate_cache = query_param_enabled ( request , "invalidate" )
152
-
153
- cards = await get_cards_for_task (
154
- self . cache , task , invalidate_cache = invalidate_cache
151
+ cards = await get_card_html_for_task_async (
152
+ self . cache ,
153
+ task ,
154
+ hash ,
155
155
)
156
-
157
156
if cards is None :
158
157
return web .Response (
159
158
content_type = "text/html" ,
160
159
status = 404 ,
161
- body = "Card not found for task. Possibly still being processed." ,
160
+ body = "Card not found for task. Possibly still being processed. Please refresh page to check again. " ,
162
161
)
163
162
164
163
if cards and hash in cards :
165
164
return web .Response (content_type = "text/html" , body = cards [hash ]["html" ])
166
165
else :
167
166
return web .Response (
168
- content_type = "text/html" , status = 404 , body = "Card not found for task."
167
+ content_type = "text/html" ,
168
+ status = 404 ,
169
+ body = "Card not found for task." ,
169
170
)
170
171
171
172
@handle_exceptions
@@ -194,16 +195,16 @@ async def get_card_data_by_hash(self, request):
194
195
schema:
195
196
$ref: '#/definitions/ResponsesError405'
196
197
"""
197
-
198
198
_hash = request .match_info .get ("hash" )
199
199
task = await self .get_task_by_request (request )
200
200
if not task :
201
201
return web .Response (
202
202
content_type = "text/html" , status = 404 , body = "Task not found."
203
203
)
204
- invalidate_cache = query_param_enabled (request , "invalidate" )
205
- data = await get_card_data_for_task (
206
- self .cache , task , _hash , invalidate_cache = invalidate_cache
204
+ data = await get_card_data_for_task_async (
205
+ self .cache ,
206
+ task ,
207
+ _hash ,
207
208
)
208
209
209
210
if data is None :
@@ -212,8 +213,21 @@ async def get_card_data_by_hash(self, request):
212
213
return web_response (200 , data )
213
214
214
215
215
- async def get_card_data_for_task (
216
- cache_client , task , card_hash , invalidate_cache = False
216
+ def _card_data_from_cache (local_cache ):
217
+ data = local_cache .read_data ()
218
+ if data is None :
219
+ return None
220
+ return {
221
+ "data" : data ["data" ],
222
+ "id" : local_cache .card_id ,
223
+ "type" : local_cache .card_type ,
224
+ }
225
+
226
+
227
+ async def get_card_html_for_task_async (
228
+ cache_client ,
229
+ task ,
230
+ card_hash ,
217
231
) -> Optional [Dict [str , Dict ]]:
218
232
"""
219
233
Return the card-data from the cache, or nothing.
@@ -232,43 +246,27 @@ async def get_card_data_for_task(
232
246
step_name = task .get ("step_name" ),
233
247
task_id = task .get ("task_name" ) or task .get ("task_id" ),
234
248
)
235
- pathspec_with_hash = "{pathspec}/{card_hash}" .format (
236
- pathspec = pathspec , card_hash = card_hash
249
+ _local_cache = cache_client .cache_manager .get_local_cache (pathspec , card_hash )
250
+ _html = await wait_until_card_is_ready (
251
+ cache_client .cache_manager , _local_cache , max_wait_time = CARD_API_HTML_WAIT_TIME
237
252
)
238
- res = await cache_client .cache .GetCardData (pathspec , card_hash , invalidate_cache )
239
-
240
- if res .has_pending_request ():
241
- async for event in res .stream ():
242
- if event ["type" ] == "error" :
243
- # raise error, there was an exception during fetching.
244
- raise CardException (event ["message" ], event ["id" ], event ["traceback" ])
245
- await res .wait () # wait until results are ready
246
- data = res .get ()
247
- if data and pathspec_with_hash in data :
248
- success , value , detail , trace = unpack_processed_value (data [pathspec_with_hash ])
249
- if success :
250
- return value
251
- else :
252
- if value in ["card-not-present" , "cannot-fetch-card" ]:
253
- return None
254
- raise CardException (detail , value , trace )
255
- return None
253
+ return _html
256
254
257
255
258
- async def get_cards_for_task (
259
- cache_client , task , invalidate_cache = False
256
+ async def get_card_data_for_task_async (
257
+ cache_client ,
258
+ task ,
259
+ card_hash ,
260
260
) -> Optional [Dict [str , Dict ]]:
261
261
"""
262
- Return a dictionary of cards from the cache, or nothing.
262
+ Return the card-data from the cache, or nothing.
263
263
264
264
Example:
265
265
--------
266
266
{
267
- "abc123": {
268
- "id": 1,
269
- "hash": "abc123",
270
- "html": "htmlcontent"
271
- }
267
+ "id": 1,
268
+ "hash": "abc123",
269
+ "data": {}
272
270
}
273
271
"""
274
272
pathspec = "{flow_id}/{run_id}/{step_name}/{task_id}" .format (
@@ -277,25 +275,26 @@ async def get_cards_for_task(
277
275
step_name = task .get ("step_name" ),
278
276
task_id = task .get ("task_name" ) or task .get ("task_id" ),
279
277
)
280
- res = await cache_client .cache .GetCards ([pathspec ], invalidate_cache )
281
-
282
- if res .has_pending_request ():
283
- async for event in res .stream ():
284
- if event ["type" ] == "error" :
285
- # raise error, there was an exception during fetching.
286
- raise CardException (event ["message" ], event ["id" ], event ["traceback" ])
287
- await res .wait () # wait until results are ready
288
- data = res .get ()
289
- if data and pathspec in data :
290
- success , value , detail , trace = unpack_processed_value (data [pathspec ])
291
- if success :
292
- return value
293
- else :
294
- if value in ["card-not-present" , "cannot-fetch-card" ]:
295
- return None
296
- raise CardException (detail , value , trace )
278
+ await cache_client .cache_manager .register (pathspec )
279
+ _local_cache = cache_client .cache_manager .get_local_cache (pathspec , card_hash )
280
+ if not _local_cache .read_ready ():
281
+ # Since this is a data update call we can return a 404 and the client
282
+ # should handle calling back so we only await at registration.
283
+ return None
284
+
285
+ return _card_data_from_cache (_local_cache )
286
+
297
287
298
- return None
288
+ async def get_card_list (
289
+ cache_client , task , max_wait_time = 3
290
+ ):
291
+ pathspec = "{flow_id}/{run_id}/{step_name}/{task_id}" .format (
292
+ flow_id = task .get ("flow_id" ),
293
+ run_id = task .get ("run_id" ) or task .get ("run_number" ),
294
+ step_name = task .get ("step_name" ),
295
+ task_id = task .get ("task_name" ) or task .get ("task_id" ),
296
+ )
297
+ return await list_cards_from_cache (cache_client .cache_manager , pathspec , max_wait_time )
299
298
300
299
301
300
def get_pagination_params (request ):
0 commit comments