From 1f27c6b3241e98e338025e90b85fb2825f2b34a9 Mon Sep 17 00:00:00 2001 From: sabersolooki Date: Mon, 31 Mar 2025 14:31:11 +0200 Subject: [PATCH 1/5] Fix(Arq): pass job_id to JobDef in new version --- arq_admin/compat.py | 4 ++++ arq_admin/queue.py | 22 ++++++++++++++-------- 2 files changed, 18 insertions(+), 8 deletions(-) create mode 100644 arq_admin/compat.py diff --git a/arq_admin/compat.py b/arq_admin/compat.py new file mode 100644 index 0000000..5ec19c5 --- /dev/null +++ b/arq_admin/compat.py @@ -0,0 +1,4 @@ +from arq import VERSION as ARQ_VERSION + + +ARQ_VERSION_TUPLE = tuple(int(x) for x in ARQ_VERSION.split(".")) \ No newline at end of file diff --git a/arq_admin/queue.py b/arq_admin/queue.py index 39cf2c5..c807253 100644 --- a/arq_admin/queue.py +++ b/arq_admin/queue.py @@ -11,6 +11,7 @@ from django.utils import timezone from arq_admin import settings +from arq_admin.compat import ARQ_VERSION_TUPLE from arq_admin.job import JobInfo ARQ_PREFIX = 'arq:' @@ -106,14 +107,19 @@ async def get_job_by_id(self, job_id: str) -> JobInfo: unknown_function_msg = "Unknown, can't deserialize" if not base_info: - base_info = JobDef( - function=unknown_function_msg, - args=(), - kwargs={}, - job_try=-1, - enqueue_time=timezone.now().replace(year=2077), - score=420, - ) + parameters = { + 'function': unknown_function_msg, + 'args': (), + 'kwargs': {}, + 'job_try': -1, + 'enqueue_time': timezone.now().replace(year=2077), + 'score': 420, + } + if ARQ_VERSION_TUPLE < (0, 26, 0): + base_info = JobDef(**parameters) + else: + parameters['job_id'] = job_id + base_info = JobDef(**parameters) job_info = JobInfo.from_base(base_info, job_id) job_info.status = await self._get_job_status(job_id) From d258f78ebdbd2ca359ce6863d2a19403e8f9a676 Mon Sep 17 00:00:00 2001 From: Slava Skvortsov <29122694+SlavaSkvortsov@users.noreply.github.com> Date: Mon, 31 Mar 2025 14:38:30 +0200 Subject: [PATCH 2/5] Update arq_admin/compat.py --- arq_admin/compat.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arq_admin/compat.py b/arq_admin/compat.py index 5ec19c5..dd6f6b7 100644 --- a/arq_admin/compat.py +++ b/arq_admin/compat.py @@ -1,4 +1,4 @@ from arq import VERSION as ARQ_VERSION -ARQ_VERSION_TUPLE = tuple(int(x) for x in ARQ_VERSION.split(".")) \ No newline at end of file +ARQ_VERSION_TUPLE = tuple(int(x) for x in ARQ_VERSION.split(".")) From 863904489aec7f5252af15677cbbacff2607805d Mon Sep 17 00:00:00 2001 From: Slava Skvortsov <29122694+SlavaSkvortsov@users.noreply.github.com> Date: Mon, 31 Mar 2025 14:41:03 +0200 Subject: [PATCH 3/5] Update arq_admin/compat.py --- arq_admin/compat.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arq_admin/compat.py b/arq_admin/compat.py index dd6f6b7..d8c1cd5 100644 --- a/arq_admin/compat.py +++ b/arq_admin/compat.py @@ -1,4 +1,4 @@ from arq import VERSION as ARQ_VERSION -ARQ_VERSION_TUPLE = tuple(int(x) for x in ARQ_VERSION.split(".")) +ARQ_VERSION_TUPLE = tuple(int(x) for x in ARQ_VERSION.split('.')) From c07cf204da9542161b1f01bd2a6df200f498e897 Mon Sep 17 00:00:00 2001 From: sabersolooki Date: Mon, 31 Mar 2025 15:09:15 +0200 Subject: [PATCH 4/5] ignore DeprecationWarning --- setup.cfg | 1 + 1 file changed, 1 insertion(+) diff --git a/setup.cfg b/setup.cfg index 80f49a2..9fbea77 100644 --- a/setup.cfg +++ b/setup.cfg @@ -67,6 +67,7 @@ filterwarnings = error ignore::UserWarning:pytest.*: ignore::ResourceWarning:redis.*: + ignore:.*Call to deprecated close.*:DeprecationWarning junit_family = xunit1 [coverage:run] From d378ea705524e214c4af90dd83d257cfd939db4c Mon Sep 17 00:00:00 2001 From: sabersolooki Date: Mon, 31 Mar 2025 15:43:47 +0200 Subject: [PATCH 5/5] add coverage test --- tests/test_queue.py | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/tests/test_queue.py b/tests/test_queue.py index 7b80095..d09b740 100644 --- a/tests/test_queue.py +++ b/tests/test_queue.py @@ -1,12 +1,13 @@ import asyncio -from typing import AsyncGenerator +from dataclasses import dataclass +from typing import AsyncGenerator, Optional from unittest.mock import AsyncMock, MagicMock, patch import pytest import pytest_asyncio from arq import ArqRedis from arq.constants import default_queue_name -from arq.jobs import DeserializationError, Job, JobStatus +from arq.jobs import DeserializationError, Job, JobStatus, JobDef from django.conf import settings from arq_admin.queue import Queue, QueueStats @@ -104,6 +105,22 @@ async def test_deserialize_error(mocked_job_info: MagicMock, jobs_creator: JobsC assert job_info.function == "Unknown, can't deserialize" +@dataclass +class NewArqJobDef(JobDef): + job_id: Optional[str] + + +@pytest.mark.asyncio() +@patch('arq_admin.queue.JobDef', NewArqJobDef) +@patch('arq_admin.queue.ARQ_VERSION_TUPLE', (0, 26, 0)) +@patch.object(Job, 'info') +async def test_deserialize_error_in_arq_26(mocked_job_info: MagicMock, jobs_creator: JobsCreator, queue: Queue) -> None: + job = await jobs_creator.create_queued() + mocked_job_info.side_effect = DeserializationError() + job_info = await queue.get_job_by_id(job.job_id) + assert job_info.function == "Unknown, can't deserialize" + + @pytest.mark.asyncio() @patch.object(Job, 'abort') @pytest.mark.parametrize('success', [True, False])