test_cancel_during_dispatch.py 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. """A job cancelled while it is being sent stays cancelled when the send then fails."""
  2. from __future__ import annotations
  3. from unittest.mock import AsyncMock, patch
  4. import pytest
  5. from sqlalchemy import update
  6. from backend.app.models.print_queue import PrintQueueItem
  7. from backend.tests.unit.test_scheduler_busy_reasons_3018 import _scheduler, one_printer # noqa: F401
  8. pytestmark = pytest.mark.asyncio
  9. async def test_a_cancel_during_the_upload_is_not_turned_into_a_failure(one_printer): # noqa: F811
  10. item_id = await one_printer.add_item()
  11. async def upload_then_cancelled(*args, **kwargs):
  12. # The user cancels while the file is on its way; then the upload fails.
  13. async with one_printer.session_maker() as other:
  14. await other.execute(update(PrintQueueItem).where(PrintQueueItem.id == item_id).values(status="cancelled"))
  15. await other.commit()
  16. return False
  17. failed = AsyncMock()
  18. toast = AsyncMock()
  19. async with _scheduler(one_printer, idle=True) as scheduler:
  20. with (
  21. patch("backend.app.services.print_scheduler.upload_file_async", upload_then_cancelled),
  22. patch("backend.app.services.notification_service.notification_service.on_queue_job_failed", failed),
  23. patch("backend.app.services.print_scheduler.ws_manager.send_queue_item_failed", toast),
  24. ):
  25. await scheduler.check_queue()
  26. for task, _pid in list(scheduler._inflight.values()):
  27. await task
  28. async with one_printer.session_maker() as db:
  29. item = await db.get(PrintQueueItem, item_id)
  30. assert item.status == "cancelled"
  31. failed.assert_not_awaited()
  32. # The dispatch toast is closed, not left spinning.
  33. assert toast.await_args.kwargs["reason"] == "cancelled_mid_dispatch"
  34. async def test_a_failed_upload_still_fails_the_job(one_printer): # noqa: F811
  35. item_id = await one_printer.add_item()
  36. async with _scheduler(one_printer, idle=True) as scheduler:
  37. with patch("backend.app.services.print_scheduler.upload_file_async", AsyncMock(return_value=False)):
  38. await scheduler.check_queue()
  39. for task, _pid in list(scheduler._inflight.values()):
  40. await task
  41. async with one_printer.session_maker() as db:
  42. item = await db.get(PrintQueueItem, item_id)
  43. assert item.status == "failed"
  44. async def test_a_stop_while_the_printer_turns_busy_is_not_undone(db_session, printer_factory):
  45. from backend.app.services.print_scheduler import PrintScheduler
  46. printer = await printer_factory()
  47. stopped = PrintQueueItem(printer_id=printer.id, status="cancelled", position=0)
  48. printing = PrintQueueItem(printer_id=printer.id, status="printing", position=1)
  49. db_session.add_all([stopped, printing])
  50. await db_session.commit()
  51. stopped_id, printing_id = stopped.id, printing.id
  52. for item_id in (stopped_id, printing_id):
  53. await PrintScheduler._defer_until_printer_idle(db_session, await db_session.get(PrintQueueItem, item_id))
  54. db_session.expire_all()
  55. assert (await db_session.get(PrintQueueItem, stopped_id)).status == "cancelled"
  56. assert (await db_session.get(PrintQueueItem, printing_id)).status == "pending"