Skip to content

Commit

Permalink
Retry pinecone 5xx errors (#2398)
Browse files Browse the repository at this point in the history
  • Loading branch information
lferran authored Aug 16, 2024
1 parent 641880e commit e2e4d34
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 8 deletions.
4 changes: 2 additions & 2 deletions nucliadb/src/nucliadb/search/search/find.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ async def _index_node_retrieval(
"query": item.model_dump_json(),
"time": search_time,
"nodes": debug_nodes_info(queried_nodes),
"durations": metrics.steps(),
},
)
elif search_time > settings.slow_find_log_threshold:
Expand All @@ -189,8 +190,7 @@ async def _index_node_retrieval(
"query": item.model_dump_json(),
"time": search_time,
"nodes": debug_nodes_info(queried_nodes),
# Include metrics in the log
**metrics.steps(),
"durations": metrics.steps(),
},
)

Expand Down
3 changes: 3 additions & 0 deletions nucliadb_utils/src/nucliadb_utils/aiopynecone/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
from nucliadb_utils.aiopynecone.exceptions import (
PineconeAPIError,
PineconeRateLimitError,
RetriablePineconeAPIError,
raise_for_status,
)
from nucliadb_utils.aiopynecone.models import (
Expand Down Expand Up @@ -93,9 +94,11 @@

RETRIABLE_EXCEPTIONS = (
PineconeRateLimitError,
RetriablePineconeAPIError,
httpx.ConnectError,
httpx.NetworkError,
httpx.WriteTimeout,
httpx.ReadTimeout,
)


Expand Down
23 changes: 20 additions & 3 deletions nucliadb_utils/src/nucliadb_utils/aiopynecone/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@

from nucliadb_telemetry.metrics import Counter

pinecone_errors_counter = Counter("pinecone_errors", labels={"type": ""})
pinecone_errors_counter = Counter("pinecone_errors", labels={"type": "", "status_code": ""})


class PineconeAPIError(Exception):
Expand Down Expand Up @@ -52,7 +52,15 @@ def __init__(
super().__init__(exc_message)


class PineconeRateLimitError(PineconeAPIError):
class RetriablePineconeAPIError(PineconeAPIError):
"""
Raised when the client can retry the operation.
"""

pass


class PineconeRateLimitError(RetriablePineconeAPIError):
"""
Raised when the client has exceeded the rate limit to be able to backoff and retry.
"""
Expand Down Expand Up @@ -80,7 +88,7 @@ def raise_for_status(operation: str, response: httpx.Response):
try:
response.raise_for_status()
except httpx.HTTPStatusError:
pinecone_errors_counter.inc(labels={"type": operation})
pinecone_errors_counter.inc(labels={"type": operation, "status_code": str(response.status_code)})
code = None
message = None
details = None
Expand All @@ -106,6 +114,15 @@ def raise_for_status(operation: str, response: httpx.Response):
message=message,
details=details,
)

if str(response.status_code).startswith("5"):
raise RetriablePineconeAPIError(
http_status_code=response.status_code,
code=code,
message=message,
details=details,
)

raise PineconeAPIError(
http_status_code=response.status_code,
code=code,
Expand Down
3 changes: 2 additions & 1 deletion nucliadb_utils/src/nucliadb_utils/aiopynecone/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
KILO_BYTE = 1024
MAX_METADATA_SIZE = 40 * KILO_BYTE
MAX_INDEX_NAME_LENGTH = 45
MAX_VECTOR_ID_LENGTH = 512


# Requests
Expand Down Expand Up @@ -64,7 +65,7 @@ class CreateIndexRequest(BaseModel):


class Vector(BaseModel):
id: str = Field(min_length=1, max_length=512)
id: str = Field(min_length=1, max_length=MAX_VECTOR_ID_LENGTH)
values: list[float]
metadata: dict[str, Any] = {}

Expand Down
17 changes: 15 additions & 2 deletions nucliadb_utils/tests/unit/aiopynecone/test_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,10 @@
batchify,
raise_for_status,
)
from nucliadb_utils.aiopynecone.exceptions import PineconeNeedsPlanUpgradeError
from nucliadb_utils.aiopynecone.exceptions import (
PineconeNeedsPlanUpgradeError,
RetriablePineconeAPIError,
)
from nucliadb_utils.aiopynecone.models import CreateIndexRequest, QueryResponse, Vector


Expand Down Expand Up @@ -312,12 +315,22 @@ async def async_iter():
assert batches == 5


def test_raise_for_status():
def test_raise_for_status_5xx():
request = unittest.mock.MagicMock()
response = unittest.mock.MagicMock(status_code=500)
response.raise_for_status.side_effect = httpx.HTTPStatusError(
"message", request=request, response=response
)
with pytest.raises(RetriablePineconeAPIError):
raise_for_status("op", response)


def test_raise_for_status_4xx():
request = unittest.mock.MagicMock()
response = unittest.mock.MagicMock(status_code=412)
response.raise_for_status.side_effect = httpx.HTTPStatusError(
"message", request=request, response=response
)
with pytest.raises(PineconeAPIError):
raise_for_status("op", response)

Expand Down

0 comments on commit e2e4d34

Please sign in to comment.