diff --git a/run.py b/run.py index ef5f7d4..051f863 100644 --- a/run.py +++ b/run.py @@ -525,6 +525,12 @@ def clean_websocket(function): return _wrap +def chunks(l, n): + """Yield successive n-sized chunks from l.""" + for i in range(0, len(l), n): + yield l[i:i + n] + + @app.websocket('/index-ws') @clean_websocket async def ws_index(request, websocket): @@ -549,13 +555,22 @@ async def ws_index(request, websocket): .join(subquery, on=(Job.id == subquery.c.min_id))\ .order_by(-Job.id) + # chunks initial data by batch of 30 to avoid killing firefox + data = chunks(list(itertools.chain(map(model_to_dict, next_scheduled_jobs), + map(model_to_dict, Job.select().where(Job.state == "running")), + map(model_to_dict, latest_done_jobs))), 30) + await websocket.send(ujson.dumps({ "action": "init_jobs", - "data": itertools.chain(map(model_to_dict, next_scheduled_jobs), - map(model_to_dict, Job.select().where(Job.state == "running")), - map(model_to_dict, latest_done_jobs)), + "data": next(data), # send first chunk })) + for chunk in data: + await websocket.send(ujson.dumps({ + "action": "init_jobs_stream", + "data": chunk, + })) + await websocket.wait_closed() diff --git a/templates/index.html b/templates/index.html index e1f101e..a2084a6 100644 --- a/templates/index.html +++ b/templates/index.html @@ -64,6 +64,10 @@ if (action == "init_jobs") { app.jobs = data; Vue.set(app, 'inited', true); + // when there is too much initial data, it's streamed to avoid a + // bug in firefox that make the whole browser crash + } else if (action == "init_jobs_stream") { + Vue.set(app, 'jobs', app.jobs.concat(data)) } else if (action == "update_job") { for (var i = 0; i < app.jobs.length; ++i) { if (app.jobs[i].id == data.id) {