Skip to content

Commit 2f110e5

Browse files
authored
Fixed 500 status code that could occur when listing requests by GET /api/requests (#9236)
This PR addresses the `KeyError` by making user/request fields in the meta nullable.
1 parent ef8704c commit 2f110e5

File tree

4 files changed

+37
-18
lines changed

4 files changed

+37
-18
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
### Fixed
2+
3+
- Fixed a 500 status code that could occur when listing requests by GET /api/requests
4+
(<https://github.com/cvat-ai/cvat/pull/9236>)

cvat/apps/engine/rq.py

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ def _get_resettable_fields() -> list[str]:
163163
def get_meta_on_retry(self) -> dict[str, Any]:
164164
resettable_fields = self._get_resettable_fields()
165165

166-
return {k: v for k, v in self._job.meta.items() if k not in resettable_fields}
166+
return {k: v for k, v in self._meta.items() if k not in resettable_fields}
167167

168168

169169
class RQMetaWithFailureInfo(AbstractRQMeta):
@@ -193,14 +193,29 @@ def _get_resettable_fields() -> list[str]:
193193

194194

195195
class BaseRQMeta(RQMetaWithFailureInfo):
196-
# immutable && required fields
196+
# immutable fields
197+
# FUTURE-TODO: change to required fields when each enqueued job
198+
# regardless of queue type will have these fields
199+
# Blocked now by:
200+
# - [annotation queue] Some jobs may have no user/request info
201+
# - [chunks queue] Each job has no user/request info
202+
# - [import queue] Jobs running to cleanup uploaded files have no user/request info
203+
# - [export queue] Jobs preparing events have no user/request info.
204+
# - [export queue] Jobs running to cleanup csv files with events have no user/request info
205+
197206
@property
198207
def user(self):
199-
return UserMeta(self.meta[RQJobMetaField.USER])
208+
if user_info := self.meta.get(RQJobMetaField.USER):
209+
return UserMeta(user_info)
210+
211+
return None
200212

201213
@property
202214
def request(self):
203-
return RequestMeta(self.meta[RQJobMetaField.REQUEST])
215+
if request_info := self.meta.get(RQJobMetaField.REQUEST):
216+
return RequestMeta(request_info)
217+
218+
return None
204219

205220
# immutable && optional fields
206221
org_id: int | None = ImmutableRQMetaAttribute(RQJobMetaField.ORG_ID, optional=True)
@@ -322,7 +337,10 @@ def build_for(
322337

323338

324339
def is_rq_job_owner(rq_job: RQJob, user_id: int) -> bool:
325-
return BaseRQMeta.for_job(rq_job).user.id == user_id
340+
if user := BaseRQMeta.for_job(rq_job).user:
341+
return user.id == user_id
342+
343+
return False
326344

327345

328346
@attrs.frozen()
@@ -464,7 +482,8 @@ def define_dependent_job(
464482
job_ids = q.get_job_ids()
465483
jobs = q.job_class.fetch_many(job_ids, q.connection)
466484
jobs = filter(
467-
lambda job: job and BaseRQMeta.for_job(job).user.id == user_id and f(job), jobs
485+
lambda job: job and is_rq_job_owner(job, user_id) and f(job),
486+
jobs,
468487
)
469488
all_user_jobs.extend(jobs)
470489

cvat/apps/events/export.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717

1818
from cvat.apps.dataset_manager.views import log_exception
1919
from cvat.apps.engine.log import ServerLogManager
20-
from cvat.apps.engine.rq import RQMetaWithFailureInfo
20+
from cvat.apps.engine.rq import BaseRQMeta, RQMetaWithFailureInfo
2121
from cvat.apps.engine.utils import sendfile
2222

2323
slogger = ServerLogManager(__name__)
@@ -165,7 +165,7 @@ def export(request, filter_query, queue_name):
165165
func=_create_csv,
166166
args=(query_params, output_filename, DEFAULT_CACHE_TTL),
167167
job_id=rq_id,
168-
meta={},
168+
meta=BaseRQMeta.build(request=request, db_obj=None),
169169
result_ttl=ttl,
170170
failure_ttl=ttl,
171171
)

cvat/apps/events/handlers.py

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -99,11 +99,9 @@ def job_id(instance):
9999

100100
def get_user(instance=None) -> User | dict | None:
101101
def _get_user_from_rq_job(rq_job: rq.job.Job) -> dict | None:
102-
# RQ jobs created in the chunks|annotation queues have no user info
103-
try:
104-
return BaseRQMeta.for_job(rq_job).user.to_dict()
105-
except KeyError:
106-
return None
102+
if user := BaseRQMeta.for_job(rq_job).user:
103+
return user.to_dict()
104+
return None
107105

108106
# Try to get current user from request
109107
user = get_current_user()
@@ -126,11 +124,9 @@ def _get_user_from_rq_job(rq_job: rq.job.Job) -> dict | None:
126124

127125
def get_request(instance=None):
128126
def _get_request_from_rq_job(rq_job: rq.job.Job) -> dict | None:
129-
# RQ jobs created in the chunks|annotation queues have no request info
130-
try:
131-
return BaseRQMeta.for_job(rq_job).request.to_dict()
132-
except KeyError:
133-
return None
127+
if request := BaseRQMeta.for_job(rq_job).request:
128+
return request.to_dict()
129+
return None
134130

135131
request = get_current_request()
136132
if request is not None:

0 commit comments

Comments
 (0)