Skip to content

Commit 85b72c0

Browse files
authored
Delete multiple records endpoints (#307)
* Delete multiple records endpoints * Test for deleting a record * Remove comments * Submodule update * Submodule update
1 parent d314536 commit 85b72c0

File tree

8 files changed

+117
-2
lines changed

8 files changed

+117
-2
lines changed

app.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
from fast_api.routes.weak_supervision import router as weak_supervision_router
3131
from fast_api.routes.labeling_tasks import router as labeling_tasks_router
3232
from fast_api.routes.task_execution import router as task_execution_router
33+
from fast_api.routes.record_internal import router as record_internal_router
3334
from fast_api.routes.playground import router as playground_router
3435
from middleware.database_session import handle_db_session
3536
from middleware.starlette_tmp_middleware import DatabaseSessionHandler
@@ -53,6 +54,7 @@
5354
PREFIX_DATA_BROWSER,
5455
PREFIX_LABELING,
5556
PREFIX_RECORD,
57+
PREFIX_RECORD_INTERNAL,
5658
PREFIX_WEAK_SUPERVISION,
5759
PREFIX_LABELING_TASKS,
5860
PREFIX_TASK_EXECUTION,
@@ -116,6 +118,11 @@
116118
task_execution_router, prefix=PREFIX_TASK_EXECUTION, tags=["task-execution"]
117119
)
118120

121+
fastapi_app_internal.include_router(
122+
record_internal_router, prefix=PREFIX_RECORD_INTERNAL, tags=["record-internal"]
123+
)
124+
125+
119126
routes = [
120127
Route("/full_config", FullConfigRest),
121128
Route("/notify/{path:path}", Notify),

controller/record/manager.py

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
tokenization,
1313
task_queue,
1414
record_label_association,
15+
comments,
1516
)
1617
from service.search import search
1718
from submodules.model import enums
@@ -22,6 +23,10 @@
2223
from controller.embedding import manager as embedding_manager
2324
from controller.tokenization import tokenization_service
2425
from util.miscellaneous_functions import chunk_list
26+
from controller.tokenization.tokenization_service import (
27+
request_reupload_docbins,
28+
)
29+
from util import notification
2530
import time
2631
import traceback
2732

@@ -307,3 +312,46 @@ def __check_and_prep_edit_records(
307312
"rla_delete_tuples": rla_delete_tuples,
308313
"embedding_rebuilds": embedding_rebuilds,
309314
}
315+
316+
317+
def delete_records(
318+
project_id: str,
319+
record_ids: List[str],
320+
as_thread: Optional[bool] = False,
321+
) -> None:
322+
if not record_ids or len(record_ids) == 0:
323+
return
324+
if as_thread:
325+
daemon.run_with_db_token(
326+
__delete_records,
327+
project_id,
328+
record_ids,
329+
)
330+
else:
331+
__delete_records(project_id, record_ids)
332+
333+
334+
def __delete_records(project_id: str, record_ids: List[str]) -> None:
335+
try:
336+
row_count = record.delete_many(project_id, record_ids)
337+
if row_count == 0:
338+
print(
339+
f"No records found to delete for {record_ids} in project {project_id}",
340+
flush=True,
341+
)
342+
return
343+
comments.delete_by_type_and_xfkey(
344+
project_id, record_ids, enums.CommentCategory.RECORD
345+
)
346+
general.commit()
347+
348+
request_reupload_docbins(project_id)
349+
350+
all_embeddings = embedding.get_all_embeddings_by_project_id(project_id)
351+
352+
for embedding_item in all_embeddings:
353+
embedding_manager.request_tensor_upload(project_id, str(embedding_item.id))
354+
notification.send_organization_update(project_id, "records_changed")
355+
356+
except Exception:
357+
print(traceback.format_exc(), flush=True)

fast_api/models.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -511,3 +511,7 @@ class InviteUsersBody(BaseModel):
511511

512512
class CheckInviteUsersBody(BaseModel):
513513
emails: List[StrictStr]
514+
515+
516+
class RecordDeletion(BaseModel):
517+
record_ids: List[str]

fast_api/routes/record.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1+
from typing import Optional
12
from fastapi import APIRouter, Depends, Request, Body
23
from controller.record import manager
34
from controller.auth import manager as auth_manager
45
from fast_api.routes.client_response import (
56
get_custom_response,
67
get_silent_success,
78
)
8-
from fast_api.models import RecordSyncBody
9+
from fast_api.models import RecordSyncBody, RecordDeletion
910
from util import notification
1011
from fastapi import status
1112
import json
@@ -33,3 +34,16 @@ def sync_records(
3334

3435
notification.send_organization_update(project_id, "records_changed")
3536
return get_silent_success()
37+
38+
39+
@router.delete(
40+
"/{project_id}/delete-records",
41+
dependencies=[Depends(auth_manager.check_project_access_dep)],
42+
)
43+
def delete_by_record_ids(
44+
project_id: str,
45+
body: RecordDeletion,
46+
as_thread: Optional[bool] = False,
47+
):
48+
manager.delete_records(project_id, body.record_ids, as_thread)
49+
return get_silent_success()

fast_api/routes/record_internal.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
from typing import Optional
2+
from fastapi import APIRouter
3+
from controller.record import manager
4+
from fast_api.routes.client_response import (
5+
get_silent_success,
6+
)
7+
from fast_api.models import RecordDeletion
8+
9+
router = APIRouter()
10+
11+
12+
@router.delete("/{project_id}/delete-records")
13+
def delete_by_record_ids(
14+
project_id: str,
15+
body: RecordDeletion,
16+
as_thread: Optional[bool] = False,
17+
):
18+
manager.delete_records(project_id, body.record_ids, as_thread)
19+
return get_silent_success()

route_prefix.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
PREFIX_DATA_BROWSER = PREFIX + "/data-browser"
1414
PREFIX_LABELING = PREFIX + "/labeling"
1515
PREFIX_RECORD = PREFIX + "/record"
16+
PREFIX_RECORD_INTERNAL = PREFIX + "/record"
1617
PREFIX_WEAK_SUPERVISION = PREFIX + "/weak-supervision"
1718
PREFIX_LABELING_TASKS = PREFIX + "/labeling-tasks"
1819
PREFIX_TASK_EXECUTION = PREFIX + "/task-execution"

tests/fast_api/routes/test_project.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,3 +149,25 @@ def test_update_records_to_project(
149149
emb = embedding_bo.get_all_embeddings_by_project_id(refinery_project.id)
150150
assert len(emb) > 0
151151
assert emb[0].current_delta_record_count > 0
152+
153+
154+
def test_delete_records_from_project(
155+
client: TestClient, refinery_project: RefineryProject
156+
):
157+
assert record_bo.count(refinery_project.id) == 2
158+
159+
record_ids = record_bo.get_all_ids(refinery_project.id)
160+
to_del = record_ids[:1] # delete one record
161+
162+
##note that .delete doesn'T seem to support bodies so we use the request directly
163+
response = client.request(
164+
"DELETE",
165+
f"/api/v1/record/{refinery_project.id}/delete-records",
166+
json={"record_ids": to_del}, # delete one record
167+
)
168+
169+
assert response.status_code == 200
170+
171+
record_ids = record_bo.get_all_ids(refinery_project.id)
172+
assert len(record_ids) == 1
173+
assert record_ids[0] != to_del[0] # the deleted record should not be present

0 commit comments

Comments
 (0)