Skip to content

Commit b3bec46

Browse files
author
Phil Varner
authored
Merge pull request #88 from stac-utils/pv/run-count-and-search-concurrently
run count and search concurrently, but don't wait for count to be done
2 parents 71e8c4f + 7b84e8d commit b3bec46

File tree

3 files changed

+30
-14
lines changed

3 files changed

+30
-14
lines changed

stac_fastapi/elasticsearch/stac_fastapi/elasticsearch/database_logic.py

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -197,24 +197,28 @@ async def execute_search(
197197
base_url: str,
198198
) -> Tuple[List[Item], Optional[int], Optional[str]]:
199199
"""Database logic to execute search with limit."""
200-
body = search.to_dict()
201-
202-
maybe_count = (
203-
await self.client.count(index=ITEMS_INDEX, body=search.to_dict(count=True))
204-
).get("count")
205-
206200
search_after = None
207201
if token:
208202
search_after = urlsafe_b64decode(token.encode()).decode().split(",")
209203

210-
es_response = await self.client.search(
211-
index=ITEMS_INDEX,
212-
query=body.get("query"),
213-
sort=sort or DEFAULT_SORT,
214-
search_after=search_after,
215-
size=limit,
204+
query = search.query.to_dict() if search.query else None
205+
206+
search_task = asyncio.create_task(
207+
self.client.search(
208+
index=ITEMS_INDEX,
209+
query=query,
210+
sort=sort or DEFAULT_SORT,
211+
search_after=search_after,
212+
size=limit,
213+
)
214+
)
215+
216+
count_task = asyncio.create_task(
217+
self.client.count(index=ITEMS_INDEX, body=search.to_dict(count=True))
216218
)
217219

220+
es_response = await search_task
221+
218222
hits = es_response["hits"]["hits"]
219223
items = [
220224
self.item_serializer.db_to_stac(hit["_source"], base_url=base_url)
@@ -227,6 +231,15 @@ async def execute_search(
227231
",".join([str(x) for x in sort_array]).encode()
228232
).decode()
229233

234+
# (1) count should not block returning results, so don't wait for it to be done
235+
# (2) don't cancel the task so that it will populate the ES cache for subsequent counts
236+
maybe_count = None
237+
if count_task.done():
238+
try:
239+
maybe_count = count_task.result().get("count")
240+
except Exception as e: # type: ignore
241+
logger.error(f"Count task failed: {e}")
242+
230243
return items, maybe_count, next_token
231244

232245
""" TRANSACTION LOGIC """

stac_fastapi/elasticsearch/tests/api/test_api.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,9 @@ async def test_app_context_extension(app_client, ctx, txn_client):
103103
resp_json = resp.json()
104104
assert len(resp_json["features"]) == 1
105105
assert "context" in resp_json
106-
assert resp_json["context"]["returned"] == resp_json["context"]["matched"] == 1
106+
assert resp_json["context"]["returned"] == 1
107+
if matched := resp_json["context"].get("matched"):
108+
assert matched == 1
107109

108110

109111
@pytest.mark.skip(reason="fields not implemented yet")

stac_fastapi/elasticsearch/tests/resources/test_item.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,8 @@ async def test_get_item_collection(app_client, ctx, txn_client):
184184
assert resp.status_code == 200
185185

186186
item_collection = resp.json()
187-
assert item_collection["context"]["matched"] == item_count + 1
187+
if matched := item_collection["context"].get("matched"):
188+
assert matched == item_count + 1
188189

189190

190191
@pytest.mark.skip(reason="Pagination extension not implemented")

0 commit comments

Comments
 (0)