Skip to content

Commit 5410a27

Browse files
committed
feat: Use HEAD HTTP method to check if a document exists
1 parent 77cbc68 commit 5410a27

File tree

4 files changed

+51
-9
lines changed

4 files changed

+51
-9
lines changed

arango/collection.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -508,7 +508,7 @@ def has(
508508
handle, body, headers = self._prep_from_doc(document, rev, check_rev)
509509

510510
request = Request(
511-
method="get",
511+
method="head",
512512
endpoint=f"/_api/document/{handle}",
513513
headers=headers,
514514
read=self.name,
@@ -519,9 +519,11 @@ def response_handler(resp: Response) -> bool:
519519
return False
520520
if resp.status_code == 412:
521521
raise DocumentRevisionError(resp, request)
522+
if resp.status_code == 404:
523+
return False
522524
if not resp.is_success:
523525
raise DocumentInError(resp, request)
524-
return bool(resp.body)
526+
return True
525527

526528
return self._execute(request, response_handler)
527529

arango/executor.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
TransactionInitError,
2222
TransactionStatusError,
2323
)
24-
from arango.job import AsyncJob, BatchJob
24+
from arango.job import AsyncJob, BatchJob, DummyAsyncJob
2525
from arango.request import Request
2626
from arango.response import Response
2727
from arango.typings import Fields, Json
@@ -99,6 +99,11 @@ def execute(
9999
False during initialization.
100100
:rtype: arango.job.AsyncJob | None
101101
"""
102+
if request.method == "head":
103+
# As of now ArangoDB doesn't support non-blocking HEAD requests,
104+
# instead we get the real response and wrap it into a fake async job
105+
resp = self._conn.send_request(request)
106+
return DummyAsyncJob(self._conn, resp, response_handler)
102107
if self._return_result:
103108
request.headers["x-arango-async"] = "store"
104109
else:

arango/job.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,3 +204,38 @@ def result(self) -> T:
204204
raise BatchJobResultError("result not available yet")
205205

206206
return self._response_handler(self._response)
207+
208+
209+
class DummyAsyncJob(AsyncJob):
210+
"""Job for tracking and retrieving result of an async API execution.
211+
212+
:param connection: HTTP connection.
213+
:param response: The response.
214+
:type response: Response
215+
:param response_handler: HTTP response handler.
216+
:type response_handler: callable
217+
"""
218+
219+
__slots__ = ["_response", "_id", "_response_handler"]
220+
221+
def __init__(
222+
self,
223+
connection: Connection,
224+
response: Response,
225+
response_handler: Callable[[Response], T],
226+
) -> None:
227+
self._response = response
228+
job_id = uuid4().hex
229+
super(DummyAsyncJob, self).__init__(connection, job_id, response_handler)
230+
231+
def status(self) -> str:
232+
return "done"
233+
234+
def result(self) -> T:
235+
return self._response_handler(self._response)
236+
237+
def cancel(self, ignore_missing: bool = False) -> bool:
238+
return True
239+
240+
def clear(self, ignore_missing: bool = False) -> bool:
241+
return True

tests/test_document.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1390,7 +1390,7 @@ def test_document_has(col, bad_col, docs):
13901390

13911391
with assert_raises(DocumentRevisionError) as err:
13921392
col.has(doc_input, rev=bad_rev, check_rev=True)
1393-
assert err.value.error_code == 1200
1393+
assert err.value.error_code in {412, 1200}
13941394

13951395
# Test existing documents with bad revision
13961396
for doc_input in [
@@ -1400,15 +1400,15 @@ def test_document_has(col, bad_col, docs):
14001400
]:
14011401
with assert_raises(DocumentRevisionError) as err:
14021402
col.has(doc_input)
1403-
assert err.value.error_code == 1200
1403+
assert err.value.error_code in {412, 1200}
14041404

14051405
with assert_raises(DocumentRevisionError) as err:
14061406
col.has(doc_input, rev=bad_rev)
1407-
assert err.value.error_code == 1200
1407+
assert err.value.error_code in {412, 1200}
14081408

14091409
with assert_raises(DocumentRevisionError) as err:
14101410
col.has(doc_input, rev=bad_rev, check_rev=True)
1411-
assert err.value.error_code == 1200
1411+
assert err.value.error_code in {412, 1200}
14121412

14131413
assert doc_input in col
14141414
assert col.has(doc_input, rev=rev, check_rev=True) is True
@@ -1487,12 +1487,12 @@ def test_document_has(col, bad_col, docs):
14871487
# Test get with bad database
14881488
with assert_raises(DocumentInError) as err:
14891489
bad_col.has(doc_key)
1490-
assert err.value.error_code in {11, 1228}
1490+
assert err.value.error_code in {11, 401}
14911491

14921492
# Test contains with bad database
14931493
with assert_raises(DocumentInError) as err:
14941494
assert doc_key in bad_col
1495-
assert err.value.error_code in {11, 1228}
1495+
assert err.value.error_code in {11, 401}
14961496

14971497

14981498
def test_document_get(col, bad_col, docs):

0 commit comments

Comments
 (0)