Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Drop support for the GET /api/tasks/<id>/status API #9076

Open
wants to merge 6 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions changelog.d/20250207_202124_maria_drop_task_status_api.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
### Removed

- Support for the GET `/api/tasks/id/status` API endpoint
in favor of GET `/api/requests/<rq_id>`
(<https://github.com/cvat-ai/cvat/pull/9076>)
11 changes: 0 additions & 11 deletions cvat/apps/engine/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
import shutil
import string
import textwrap
import warnings
from collections import OrderedDict
from collections.abc import Iterable, Sequence
from contextlib import closing
Expand Down Expand Up @@ -1806,16 +1805,6 @@ def to_internal_value(self, data):
def to_representation(self, instance):
return instance.file if instance else instance

class RqStatusSerializer(serializers.Serializer):
state = serializers.ChoiceField(choices=[
"Queued", "Started", "Finished", "Failed"])
message = serializers.CharField(allow_blank=True, default="")
progress = serializers.FloatField(max_value=100, default=0)

def __init__(self, instance=None, data=..., **kwargs):
warnings.warn("RqStatusSerializer is deprecated, "
"use cvat.apps.engine.serializers.RequestSerializer instead", DeprecationWarning)
super().__init__(instance, data, **kwargs)

class RqIdSerializer(serializers.Serializer):
rq_id = serializers.CharField(help_text="Request id")
Expand Down
51 changes: 24 additions & 27 deletions cvat/apps/engine/tests/test_rest_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -3519,9 +3519,9 @@ def _run_api_v2_tasks_id_data_post(self, tid, user, data, *, headers=None):

return response

def _get_task_creation_status(self, tid, user, *, headers=None):
def _get_request(self, rq_id: str, user: str, *, headers: dict | None = None):
with ForceLogin(user, self.client):
response = self.client.get('/api/tasks/{}/status'.format(tid),
response = self.client.get('/api/requests/{}'.format(rq_id),
**{'HTTP_' + k: v for k, v in (headers or {}).items()})

return response
Expand Down Expand Up @@ -3601,18 +3601,14 @@ def _test_api_v2_tasks_id_data_spec(self, user, spec, data,
expected_storage_method=None,
expected_uploaded_data_location=StorageChoice.LOCAL,
dimension=DimensionType.DIM_2D,
expected_task_creation_status_state='Finished',
expected_task_creation_status_reason=None,
expected_task_creation_request_state='finished',
expected_task_creation_request_message=None,
*,
send_data_callback=None,
get_status_callback=None,
):
if send_data_callback is None:
send_data_callback = self._run_api_v2_tasks_id_data_post

if get_status_callback is None:
get_status_callback = self._get_task_creation_status

if expected_storage_method is None:
if settings.MEDIA_CACHE_ALLOW_STATIC_CACHE:
expected_storage_method = StorageMethodChoice.FILE_SYSTEM
Expand All @@ -3628,20 +3624,21 @@ def _test_api_v2_tasks_id_data_spec(self, user, spec, data,
# post data for the task
response = send_data_callback(task_id, user, data)
self.assertEqual(response.status_code, status.HTTP_202_ACCEPTED, response.reason_phrase)
rq_id = response.data['rq_id']

for _ in range(100):
response = self._get_request(rq_id, user)
task_creation_request_state = response.data['status']
if task_creation_request_state in ("failed", "finished"):
break
sleep(0.1)
else:
assert False, "Too much time to create a task"

if get_status_callback:
max_number_of_attempt = 100
state = None
while state not in ('Failed', 'Finished'):
assert max_number_of_attempt, "Too much time to create a task"
response = get_status_callback(task_id, user)
state = response.data['state']
sleep(0.1)
max_number_of_attempt -= 1
self.assertEqual(state, expected_task_creation_status_state)
if expected_task_creation_status_state == 'Failed':
self.assertIn(expected_task_creation_status_reason, response.data['message'])
return
self.assertEqual(task_creation_request_state, expected_task_creation_request_state)
if expected_task_creation_request_state == 'failed':
self.assertIn(expected_task_creation_request_message, response.data['message'])
return

response = self._get_task(user, task_id)

Expand Down Expand Up @@ -4311,8 +4308,8 @@ def _test_api_v2_tasks_id_data_create_can_use_server_images_and_manifest(self, u
self.ChunkType.IMAGESET, self.ChunkType.IMAGESET,
image_sizes,
expected_uploaded_data_location=StorageChoice.SHARE,
expected_task_creation_status_state='Failed',
expected_task_creation_status_reason='Incorrect file mapping to manifest content')
expected_task_creation_request_state='failed',
expected_task_creation_request_message='Incorrect file mapping to manifest content')

def _test_api_v2_tasks_id_data_create_can_use_server_images_with_predefined_sorting(self, user):
task_spec = {
Expand Down Expand Up @@ -4480,8 +4477,8 @@ def _test_api_v2_tasks_id_data_create_can_use_server_archive_with_predefined_sor
task_data["server_files[1]"] = manifest_name
else:
kwargs.update({
'expected_task_creation_status_state': 'Failed',
'expected_task_creation_status_reason': "Can't find upload manifest file",
'expected_task_creation_request_state': 'failed',
'expected_task_creation_request_message': "Can't find upload manifest file",
})

self._test_api_v2_tasks_id_data_spec(user, task_spec, task_data,
Expand Down Expand Up @@ -4549,8 +4546,8 @@ def _test_api_v2_tasks_id_data_create_can_use_local_archive_with_predefined_sort
task_data[f"client_files[1]"] = es.enter_context(open(manifest_path))
else:
kwargs.update({
'expected_task_creation_status_state': 'Failed',
'expected_task_creation_status_reason': "Can't find upload manifest file",
'expected_task_creation_request_state': 'failed',
'expected_task_creation_request_message': "Can't find upload manifest file",
})
self._test_api_v2_tasks_id_data_spec(user, task_spec, task_data,
self.ChunkType.IMAGESET, self.ChunkType.IMAGESET,
Expand Down
50 changes: 0 additions & 50 deletions cvat/apps/engine/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,6 @@
ProjectWriteSerializer,
RequestSerializer,
RqIdSerializer,
RqStatusSerializer,
TaskFileSerializer,
TaskReadSerializer,
TaskValidationLayoutReadSerializer,
Expand All @@ -170,7 +169,6 @@
get_rq_lock_by_user,
get_rq_lock_for_job,
import_resource_with_clean_up_after,
parse_exception_message,
process_failed_job,
sendfile,
)
Expand Down Expand Up @@ -1576,54 +1574,6 @@ def append_annotations_chunk(self, request: ExtendedRequest, pk: int, file_id: s
self._object = self.get_object()
return self.append_tus_chunk(request, file_id)

### --- DEPRECATED METHOD --- ###
@extend_schema(
summary='Get the creation status of a task',
responses={
'200': RqStatusSerializer,
},
deprecated=True,
description="This method is deprecated and will be removed in one of the next releases. "
"To check status of task creation, use new common API "
"for managing background operations: GET /api/requests/?action=create&task_id=<task_id>",
)
@action(detail=True, methods=['GET'], serializer_class=RqStatusSerializer)
def status(self, request, pk):
task = self.get_object() # force call of check_object_permissions()
response = self._get_rq_response(
queue=settings.CVAT_QUEUES.IMPORT_DATA.value,
job_id=RQId(RequestAction.CREATE, RequestTarget.TASK, task.id).render()
)
serializer = RqStatusSerializer(data=response)

serializer.is_valid(raise_exception=True)
return Response(serializer.data, headers={'Deprecation': 'true'})

### --- DEPRECATED METHOD--- ###
@staticmethod
def _get_rq_response(queue, job_id):
queue = django_rq.get_queue(queue)
job = queue.fetch_job(job_id)
rq_job_meta = ImportRQMeta.for_job(job)
response = {}
if job is None or job.is_finished:
response = { "state": "Finished" }
elif job.is_queued or job.is_deferred:
response = { "state": "Queued" }
elif job.is_failed:
# FIXME: It seems that in some cases exc_info can be None.
# It's not really clear how it is possible, but it can
# lead to an error in serializing the response
# https://github.com/cvat-ai/cvat/issues/5215
response = { "state": "Failed", "message": parse_exception_message(job.exc_info or "Unknown error") }
else:
response = { "state": "Started" }
if rq_job_meta.status:
response['message'] = rq_job_meta.status
response['progress'] = rq_job_meta.progress or 0.

return response

@extend_schema(methods=['GET'], summary='Get metainformation for media files in a task',
responses={
'200': DataMetaReadSerializer,
Expand Down
57 changes: 0 additions & 57 deletions cvat/schema.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5755,36 +5755,6 @@ paths:
description: Task image preview
'404':
description: Task image preview not found
/api/tasks/{id}/status:
get:
operationId: tasks_retrieve_status
description: 'This method is deprecated and will be removed in one of the next
releases. To check status of task creation, use new common API for managing
background operations: GET /api/requests/?action=create&task_id=<task_id>'
summary: Get the creation status of a task
parameters:
- in: path
name: id
schema:
type: integer
description: A unique integer value identifying this task.
required: true
tags:
- tasks
security:
- sessionAuth: []
csrfAuth: []
tokenAuth: []
- signatureAuth: []
- basicAuth: []
deprecated: true
responses:
'200':
content:
application/vnd.cvat+json:
schema:
$ref: '#/components/schemas/RqStatus'
description: ''
/api/tasks/{id}/validation_layout:
get:
operationId: tasks_retrieve_validation_layout
Expand Down Expand Up @@ -10165,33 +10135,6 @@ components:
description: Request id
required:
- rq_id
RqStatus:
type: object
properties:
state:
$ref: '#/components/schemas/RqStatusStateEnum'
message:
type: string
default: ''
progress:
type: number
format: double
maximum: 100
default: 0.0
required:
- state
RqStatusStateEnum:
enum:
- Queued
- Started
- Finished
- Failed
type: string
description: |-
* `Queued` - Queued
* `Started` - Started
* `Finished` - Finished
* `Failed` - Failed
SeverityEnum:
enum:
- warning
Expand Down
Loading