Skip to content

Commit 5fdf941

Browse files
authored
[DE-562] Index Cache Refilling (#259)
* Adding refill_index_caches parameter * Adding changelog entry * update: comments
1 parent 4bb8c6c commit 5fdf941

File tree

3 files changed

+128
-8
lines changed

3 files changed

+128
-8
lines changed

CHANGELOG.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,25 @@
11
main
22
----
33

4+
* Added new per-operation option `refillIndexCache` to write operations:
5+
6+
- single-document write operations (insert, replace, update, delete)
7+
- multi-document write operations (insert_many, replace_many, update_many, delete_many)
8+
9+
If the option is set to `True`, new entries are added to in-memory index caches if
10+
document operations affect the edge index or cache-enabled persistent indexes. Every
11+
currently running transaction will keep track of which in-memory index cache entries
12+
were invalidated by the transaction, and will try to (re-)fill them later.
13+
14+
Example:
15+
```python
16+
collection.insert({"foo": "bar"}, refillIndexCaches=True)
17+
db.aql.execute("INSERT {foo: bar} INTO collection OPTIONS { refillIndexCaches: true }")
18+
```
19+
20+
7.5.9
21+
-----
22+
423
* Added cache and primaryKeyCache parameters to the inverted index API.
524

625
* Added allow_retry query parameter, making it possible to retry fetching the latest batch from a cursor.

arango/collection.py

Lines changed: 72 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1468,6 +1468,7 @@ def insert_many(
14681468
overwrite_mode: Optional[str] = None,
14691469
keep_none: Optional[bool] = None,
14701470
merge: Optional[bool] = None,
1471+
refill_index_caches: Optional[bool] = None,
14711472
) -> Result[Union[bool, List[Union[Json, ArangoServerError]]]]:
14721473
"""Insert multiple documents.
14731474
@@ -1518,8 +1519,10 @@ def insert_many(
15181519
instead of the new one overwriting the old one. Applies only when
15191520
**overwrite_mode** is set to "update" (update-insert).
15201521
:type merge: bool | None
1521-
:return: Document metadata (e.g. document key, revision) or True if
1522-
parameter **silent** was set to True.
1522+
:param refill_index_caches: Whether to add new entries to in-memory
1523+
index caches if document insertions affect the edge index or
1524+
cache-enabled persistent indexes.
1525+
:type refill_index_caches: bool | None
15231526
:return: List of document metadata (e.g. document keys, revisions) and
15241527
any exception, or True if parameter **silent** was set to True.
15251528
:rtype: [dict | ArangoServerError] | bool
@@ -1543,6 +1546,10 @@ def insert_many(
15431546
if merge is not None:
15441547
params["mergeObjects"] = merge
15451548

1549+
# New in ArangoDB 3.9.6 and 3.10.2
1550+
if refill_index_caches is not None:
1551+
params["refillIndexCaches"] = refill_index_caches
1552+
15461553
request = Request(
15471554
method="post",
15481555
endpoint=f"/_api/document/{self.name}",
@@ -1582,6 +1589,7 @@ def update_many(
15821589
return_old: bool = False,
15831590
sync: Optional[bool] = None,
15841591
silent: bool = False,
1592+
refill_index_caches: Optional[bool] = None,
15851593
) -> Result[Union[bool, List[Union[Json, ArangoServerError]]]]:
15861594
"""Update multiple documents.
15871595
@@ -1624,6 +1632,10 @@ def update_many(
16241632
:param silent: If set to True, no document metadata is returned. This
16251633
can be used to save resources.
16261634
:type silent: bool
1635+
:param refill_index_caches: Whether to add new entries to in-memory
1636+
index caches if document operations affect the edge index or
1637+
cache-enabled persistent indexes.
1638+
:type refill_index_caches: bool | None
16271639
:return: List of document metadata (e.g. document keys, revisions) and
16281640
any exceptions, or True if parameter **silent** was set to True.
16291641
:rtype: [dict | ArangoError] | bool
@@ -1641,6 +1653,10 @@ def update_many(
16411653
if sync is not None:
16421654
params["waitForSync"] = sync
16431655

1656+
# New in ArangoDB 3.9.6 and 3.10.2
1657+
if refill_index_caches is not None:
1658+
params["refillIndexCaches"] = refill_index_caches
1659+
16441660
documents = [self._ensure_key_in_body(doc) for doc in documents]
16451661

16461662
request = Request(
@@ -1753,6 +1769,7 @@ def replace_many(
17531769
return_old: bool = False,
17541770
sync: Optional[bool] = None,
17551771
silent: bool = False,
1772+
refill_index_caches: Optional[bool] = None,
17561773
) -> Result[Union[bool, List[Union[Json, ArangoServerError]]]]:
17571774
"""Replace multiple documents.
17581775
@@ -1790,6 +1807,10 @@ def replace_many(
17901807
:param silent: If set to True, no document metadata is returned. This
17911808
can be used to save resources.
17921809
:type silent: bool
1810+
:param refill_index_caches: Whether to add new entries to in-memory
1811+
index caches if document operations affect the edge index or
1812+
cache-enabled persistent indexes.
1813+
:type refill_index_caches: bool | None
17931814
:return: List of document metadata (e.g. document keys, revisions) and
17941815
any exceptions, or True if parameter **silent** was set to True.
17951816
:rtype: [dict | ArangoServerError] | bool
@@ -1805,6 +1826,10 @@ def replace_many(
18051826
if sync is not None:
18061827
params["waitForSync"] = sync
18071828

1829+
# New in ArangoDB 3.9.6 and 3.10.2
1830+
if refill_index_caches is not None:
1831+
params["refillIndexCaches"] = refill_index_caches
1832+
18081833
documents = [self._ensure_key_in_body(doc) for doc in documents]
18091834

18101835
request = Request(
@@ -1901,6 +1926,7 @@ def delete_many(
19011926
check_rev: bool = True,
19021927
sync: Optional[bool] = None,
19031928
silent: bool = False,
1929+
refill_index_caches: Optional[bool] = None,
19041930
) -> Result[Union[bool, List[Union[Json, ArangoServerError]]]]:
19051931
"""Delete multiple documents.
19061932
@@ -1933,6 +1959,10 @@ def delete_many(
19331959
:param silent: If set to True, no document metadata is returned. This
19341960
can be used to save resources.
19351961
:type silent: bool
1962+
:param refill_index_caches: Whether to add new entries to in-memory
1963+
index caches if document operations affect the edge index or
1964+
cache-enabled persistent indexes.
1965+
:type refill_index_caches: bool | None
19361966
:return: List of document metadata (e.g. document keys, revisions) and
19371967
any exceptions, or True if parameter **silent** was set to True.
19381968
:rtype: [dict | ArangoServerError] | bool
@@ -1947,6 +1977,10 @@ def delete_many(
19471977
if sync is not None:
19481978
params["waitForSync"] = sync
19491979

1980+
# New in ArangoDB 3.9.6 and 3.10.2
1981+
if refill_index_caches is not None:
1982+
params["refillCaches"] = refill_index_caches
1983+
19501984
documents = [
19511985
self._ensure_key_in_body(doc) if isinstance(doc, dict) else doc
19521986
for doc in documents
@@ -2229,6 +2263,7 @@ def insert(
22292263
overwrite_mode: Optional[str] = None,
22302264
keep_none: Optional[bool] = None,
22312265
merge: Optional[bool] = None,
2266+
refill_index_caches: Optional[bool] = None,
22322267
) -> Result[Union[bool, Json]]:
22332268
"""Insert a new document.
22342269
@@ -2263,6 +2298,10 @@ def insert(
22632298
instead of the new one overwriting the old one. Applies only when
22642299
**overwrite_mode** is set to "update" (update-insert).
22652300
:type merge: bool | None
2301+
:param refill_index_caches: Whether to add new entries to in-memory
2302+
index caches if document insertions affect the edge index or
2303+
cache-enabled persistent indexes.
2304+
:type refill_index_caches: bool | None
22662305
:return: Document metadata (e.g. document key, revision) or True if
22672306
parameter **silent** was set to True.
22682307
:rtype: bool | dict
@@ -2285,6 +2324,10 @@ def insert(
22852324
if merge is not None:
22862325
params["mergeObjects"] = merge
22872326

2327+
# New in ArangoDB 3.9.6 and 3.10.2
2328+
if refill_index_caches is not None:
2329+
params["refillIndexCaches"] = refill_index_caches
2330+
22882331
request = Request(
22892332
method="post",
22902333
endpoint=f"/_api/document/{self.name}",
@@ -2317,6 +2360,7 @@ def update(
23172360
return_old: bool = False,
23182361
sync: Optional[bool] = None,
23192362
silent: bool = False,
2363+
refill_index_caches: Optional[bool] = None,
23202364
) -> Result[Union[bool, Json]]:
23212365
"""Update a document.
23222366
@@ -2343,6 +2387,10 @@ def update(
23432387
:param silent: If set to True, no document metadata is returned. This
23442388
can be used to save resources.
23452389
:type silent: bool
2390+
:param refill_index_caches: Whether to add new entries to in-memory
2391+
index caches if document insertions affect the edge index or
2392+
cache-enabled persistent indexes.
2393+
:type refill_index_caches: bool | None
23462394
:return: Document metadata (e.g. document key, revision) or True if
23472395
parameter **silent** was set to True.
23482396
:rtype: bool | dict
@@ -2361,6 +2409,10 @@ def update(
23612409
if sync is not None:
23622410
params["waitForSync"] = sync
23632411

2412+
# New in ArangoDB 3.9.6 and 3.10.2
2413+
if refill_index_caches is not None:
2414+
params["refillIndexCaches"] = refill_index_caches
2415+
23642416
request = Request(
23652417
method="patch",
23662418
endpoint=f"/_api/document/{self._extract_id(document)}",
@@ -2391,6 +2443,7 @@ def replace(
23912443
return_old: bool = False,
23922444
sync: Optional[bool] = None,
23932445
silent: bool = False,
2446+
refill_index_caches: Optional[bool] = None,
23942447
) -> Result[Union[bool, Json]]:
23952448
"""Replace a document.
23962449
@@ -2412,6 +2465,10 @@ def replace(
24122465
:param silent: If set to True, no document metadata is returned. This
24132466
can be used to save resources.
24142467
:type silent: bool
2468+
:param refill_index_caches: Whether to add new entries to in-memory
2469+
index caches if document insertions affect the edge index or
2470+
cache-enabled persistent indexes.
2471+
:type refill_index_caches: bool | None
24152472
:return: Document metadata (e.g. document key, revision) or True if
24162473
parameter **silent** was set to True.
24172474
:rtype: bool | dict
@@ -2428,6 +2485,10 @@ def replace(
24282485
if sync is not None:
24292486
params["waitForSync"] = sync
24302487

2488+
# New in ArangoDB 3.9.6 and 3.10.2
2489+
if refill_index_caches is not None:
2490+
params["refillIndexCaches"] = refill_index_caches
2491+
24312492
request = Request(
24322493
method="put",
24332494
endpoint=f"/_api/document/{self._extract_id(document)}",
@@ -2461,6 +2522,7 @@ def delete(
24612522
return_old: bool = False,
24622523
sync: Optional[bool] = None,
24632524
silent: bool = False,
2525+
refill_index_caches: Optional[bool] = None,
24642526
) -> Result[Union[bool, Json]]:
24652527
"""Delete a document.
24662528
@@ -2485,6 +2547,10 @@ def delete(
24852547
:param silent: If set to True, no document metadata is returned. This
24862548
can be used to save resources.
24872549
:type silent: bool
2550+
:param refill_index_caches: Whether to add new entries to in-memory
2551+
index caches if document operations affect the edge index or
2552+
cache-enabled persistent indexes.
2553+
:type refill_index_caches: bool | None
24882554
:return: Document metadata (e.g. document key, revision), or True if
24892555
parameter **silent** was set to True, or False if document was not
24902556
found and **ignore_missing** was set to True (does not apply in
@@ -2504,6 +2570,10 @@ def delete(
25042570
if sync is not None:
25052571
params["waitForSync"] = sync
25062572

2573+
# New in ArangoDB 3.9.6 and 3.10.2
2574+
if refill_index_caches is not None:
2575+
params["refillIndexCaches"] = refill_index_caches
2576+
25072577
request = Request(
25082578
method="delete",
25092579
endpoint=f"/_api/document/{handle}",

tests/test_document.py

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,13 @@ def test_document_insert(col, docs):
140140
)
141141
assert err.value.error_code == 1210
142142

143+
# Test insert with cache refilling
144+
empty_collection(col)
145+
doc = docs[0]
146+
assert col.insert(doc, refill_index_caches=True)
147+
assert col[doc["_key"]]["_key"] == doc["_key"]
148+
assert col[doc["_key"]]["val"] == doc["val"]
149+
143150

144151
def test_document_insert_many(col, bad_col, docs):
145152
# Test insert_many with default options
@@ -291,6 +298,13 @@ def test_document_insert_many(col, bad_col, docs):
291298
assert results[0].error_code == 1210
292299
assert "new" in results[1]
293300

301+
# Test insert with cache refilling
302+
empty_collection(col)
303+
assert col.insert_many(docs, refill_index_caches=True)
304+
for doc in docs:
305+
assert col[doc["_key"]]["_key"] == doc["_key"]
306+
assert col[doc["_key"]]["val"] == doc["val"]
307+
294308

295309
def test_document_update(col, docs):
296310
doc = docs[0]
@@ -422,6 +436,11 @@ def test_document_update(col, docs):
422436
assert col.update(doc, silent=True) is True
423437
assert col[doc["_key"]]["val"] == 8
424438

439+
# Test update with cache refilling
440+
doc["val"] = 9
441+
assert col.update(doc, refill_index_caches=True, check_rev=False)
442+
assert col[doc["_key"]]["val"] == 9
443+
425444

426445
def test_document_update_many(col, bad_col, docs):
427446
col.insert_many(docs)
@@ -600,6 +619,13 @@ def test_document_update_many(col, bad_col, docs):
600619
for doc in docs:
601620
assert col[doc["_key"]]["val"] == 8
602621

622+
# Test update_many with cache refilling
623+
for doc in docs:
624+
doc["val"] = 9
625+
assert col.update_many(docs, refill_index_caches=True, check_rev=False)
626+
for doc in docs:
627+
assert col[doc["_key"]]["val"] == 9
628+
603629
# Test update_many with bad documents
604630
with assert_raises(DocumentParseError) as err:
605631
bad_col.update_many([{}])
@@ -734,6 +760,11 @@ def test_document_replace(col, docs):
734760
assert col.replace(doc, silent=True) is True
735761
assert col[doc["_key"]]["val"] == 8
736762

763+
# Test replace with cache refilling
764+
doc["val"] = 9
765+
assert col.replace(doc, refill_index_caches=True, check_rev=False)
766+
assert col[doc["_key"]]["val"] == 9
767+
737768

738769
def test_document_replace_many(col, bad_col, docs):
739770
col.insert_many(docs)
@@ -817,8 +848,8 @@ def test_document_replace_many(col, bad_col, docs):
817848
assert "foo" not in doc
818849
assert doc["baz"] == 4
819850

820-
# Test replace_many with check_rev set to False
821-
results = col.replace_many(docs, check_rev=False)
851+
# Test replace_many with check_rev set to False and cache refilling
852+
results = col.replace_many(docs, check_rev=False, refill_index_caches=True)
822853
for result, doc in zip(results, docs):
823854
doc_key = doc["_key"]
824855
assert result["_id"] == f"{col.name}/{doc_key}"
@@ -965,9 +996,9 @@ def test_document_delete(col, docs):
965996
if col.context != "transaction":
966997
assert col.delete(bad_key, ignore_missing=True) is False
967998

968-
# Test delete (document) with silent set to True
999+
# Test delete (document) with silent set to True and cache refilling
9691000
doc = docs[5]
970-
assert col.delete(doc, silent=True) is True
1001+
assert col.delete(doc, silent=True, refill_index_caches=True) is True
9711002
assert doc["_key"] not in col
9721003
assert len(col) == 1
9731004

@@ -1029,9 +1060,9 @@ def test_document_delete_many(col, bad_col, docs):
10291060
old_revs[doc_key] = result["_rev"]
10301061
assert len(col) == 0
10311062

1032-
# Test delete_many with silent set to True
1063+
# Test delete_many with silent set to True and cache refilling
10331064
col.import_bulk(docs)
1034-
assert col.delete_many(docs, silent=True) is True
1065+
assert col.delete_many(docs, silent=True, refill_index_caches=True) is True
10351066
assert len(col) == 0
10361067

10371068
# Test delete_many (documents) with check_rev set to True

0 commit comments

Comments
 (0)