refactor: switch api/history to be fully async.
This commit is contained in:
parent
7d6dc7ae76
commit
fe6fe42a65
3 changed files with 924 additions and 364 deletions
|
|
@ -385,34 +385,67 @@ async def items_add(request: Request, queue: DownloadQueue, encoder: Encoder) ->
|
||||||
Returns:
|
Returns:
|
||||||
Response: The response object.
|
Response: The response object.
|
||||||
|
|
||||||
|
Query Parameters:
|
||||||
|
sync (bool): If true, wait for all items to be processed synchronously. Default: false
|
||||||
|
|
||||||
"""
|
"""
|
||||||
data = await request.json()
|
data = await request.json()
|
||||||
|
|
||||||
if isinstance(data, dict):
|
if isinstance(data, dict):
|
||||||
data = [data]
|
data = [data]
|
||||||
|
|
||||||
items = []
|
items: list[Item] = []
|
||||||
for item in data:
|
for item in data:
|
||||||
try:
|
try:
|
||||||
items.append(Item.format(item))
|
items.append(Item.format(item))
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
return web.json_response(data={"error": str(e), "data": item}, status=web.HTTPBadRequest.status_code)
|
return web.json_response(data={"error": str(e), "data": item}, status=web.HTTPBadRequest.status_code)
|
||||||
|
|
||||||
status: list[dict] = await asyncio.wait_for(
|
if "true" == request.query.get("sync", "false").lower():
|
||||||
fut=asyncio.gather(*[queue.add(item=item) for item in items]),
|
status: list[dict] = await asyncio.wait_for(
|
||||||
timeout=None,
|
fut=asyncio.gather(*[queue.add(item=item) for item in items]),
|
||||||
|
timeout=None,
|
||||||
|
)
|
||||||
|
|
||||||
|
response: list[dict[str, Any]] = []
|
||||||
|
|
||||||
|
for i, item in enumerate(items):
|
||||||
|
it = {"item": item, "status": "ok" == status[i].get("status"), "msg": status[i].get("msg")}
|
||||||
|
if status[i].get("hidden"):
|
||||||
|
it["hidden"] = True
|
||||||
|
response.append(it)
|
||||||
|
|
||||||
|
return web.json_response(data=response, status=web.HTTPOk.status_code, dumps=encoder.encode)
|
||||||
|
|
||||||
|
from app.library.downloads.utils import handle_task_exception
|
||||||
|
|
||||||
|
batch_id: str = f"batch_{asyncio.get_running_loop().time():.0f}"
|
||||||
|
|
||||||
|
for idx, item in enumerate(items):
|
||||||
|
if not item.extras:
|
||||||
|
item.extras = {}
|
||||||
|
|
||||||
|
item.extras["batch_id"] = batch_id
|
||||||
|
item.extras["batch_index"] = idx
|
||||||
|
item.extras["batch_total"] = len(items)
|
||||||
|
|
||||||
|
task = asyncio.create_task(
|
||||||
|
queue.add(item=item),
|
||||||
|
name=f"bulk_add_{batch_id}_{idx}",
|
||||||
|
)
|
||||||
|
task.add_done_callback(lambda t: handle_task_exception(t, LOG))
|
||||||
|
|
||||||
|
return web.json_response(
|
||||||
|
data={
|
||||||
|
"status": "accepted",
|
||||||
|
"message": f"Accepted {len(items)} item(s) for processing",
|
||||||
|
"batch_id": batch_id,
|
||||||
|
"count": len(items),
|
||||||
|
},
|
||||||
|
status=web.HTTPAccepted.status_code,
|
||||||
|
dumps=encoder.encode,
|
||||||
)
|
)
|
||||||
|
|
||||||
response: list[dict[str, Any]] = []
|
|
||||||
|
|
||||||
for i, item in enumerate(items):
|
|
||||||
it = {"item": item, "status": "ok" == status[i].get("status"), "msg": status[i].get("msg")}
|
|
||||||
if status[i].get("hidden"):
|
|
||||||
it["hidden"] = True
|
|
||||||
response.append(it)
|
|
||||||
|
|
||||||
return web.json_response(data=response, status=web.HTTPOk.status_code, dumps=encoder.encode)
|
|
||||||
|
|
||||||
|
|
||||||
@route("POST", "api/history/start", "items_start")
|
@route("POST", "api/history/start", "items_start")
|
||||||
async def items_start(request: Request, queue: DownloadQueue, encoder: Encoder) -> Response:
|
async def items_start(request: Request, queue: DownloadQueue, encoder: Encoder) -> Response:
|
||||||
|
|
|
||||||
|
|
@ -309,7 +309,6 @@ const form = useStorage<item_request>('local_config_v1', {
|
||||||
extras: {},
|
extras: {},
|
||||||
}) as Ref<item_request>
|
}) as Ref<item_request>
|
||||||
|
|
||||||
|
|
||||||
const is_valid_dl_field = (dl_field: string): boolean => {
|
const is_valid_dl_field = (dl_field: string): boolean => {
|
||||||
if (dlFieldsExtra.includes(dl_field)) {
|
if (dlFieldsExtra.includes(dl_field)) {
|
||||||
return true
|
return true
|
||||||
|
|
@ -471,19 +470,25 @@ const addDownload = async () => {
|
||||||
|
|
||||||
let had_errors = false
|
let had_errors = false
|
||||||
|
|
||||||
data.forEach((item: Record<string, any>) => {
|
if (200 === response.status) {
|
||||||
if (false !== item.status) {
|
data.forEach((item: Record<string, any>) => {
|
||||||
return
|
if (false !== item.status) {
|
||||||
}
|
return
|
||||||
|
}
|
||||||
|
|
||||||
had_errors = true
|
had_errors = true
|
||||||
|
|
||||||
if (item?.hidden) {
|
if (item?.hidden) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
toast.error(`Error: ${item.msg || 'Failed to add download.'}`)
|
toast.error(`Error: ${item.msg || 'Failed to add download.'}`)
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if (202 === response.status) {
|
||||||
|
toast.success(data.message,{ timeout: 2000 })
|
||||||
|
}
|
||||||
|
|
||||||
if (false === had_errors) {
|
if (false === had_errors) {
|
||||||
form.value.url = ''
|
form.value.url = ''
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue