-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* ci: added codecov * feat: init search index
- Loading branch information
1 parent
8f82e24
commit 8bd948b
Showing
15 changed files
with
368 additions
and
25 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
from unittest import TestCase | ||
from unittest.mock import patch | ||
|
||
from api.generated.server.v1.observability_pb2 import Error as ProtoError | ||
from api.generated.server.v1.search_pb2 import DocStatus, UpdateDocumentResponse | ||
from tests import StubRpcError | ||
from tigrisdb.errors import TigrisServerError | ||
from tigrisdb.search_index import SearchIndex | ||
from tigrisdb.types import ClientConfig, Document | ||
from tigrisdb.utils import bytes_to_dict | ||
|
||
|
||
@patch("api.generated.server.v1.search_pb2_grpc.SearchStub") | ||
class SearchIndexTest(TestCase): | ||
def setUp(self) -> None: | ||
self.client_config = ClientConfig( | ||
server_url="localhost:5000", project_name="db1" | ||
) | ||
self.index_name = "catalog" | ||
|
||
def test_create_one(self, grpc_search): | ||
doc: Document = {"item_id": 1, "name": "shoe", "brand": "adidas"} | ||
with patch.object( | ||
SearchIndex, "create_many", return_value="some_str" | ||
) as mock_create_many: | ||
search_index = SearchIndex( | ||
self.index_name, grpc_search(), self.client_config | ||
) | ||
search_index.create_one(doc) | ||
|
||
mock_create_many.assert_called_once_with([doc]) | ||
|
||
def test_update_many(self, grpc_search): | ||
docs = [{"id": 1, "name": "shoe"}, {"id": 2, "name": "jacket"}] | ||
search_index = SearchIndex(self.index_name, grpc_search(), self.client_config) | ||
mock_grpc = grpc_search() | ||
mock_grpc.Update.return_value = UpdateDocumentResponse( | ||
status=[ | ||
DocStatus(id="1"), | ||
DocStatus(id="2", error=ProtoError(message="conflict")), | ||
] | ||
) | ||
|
||
resp = search_index.update_many(docs) | ||
self.assertEqual(resp[0].id, "1") | ||
self.assertIsNone(resp[0].error) | ||
self.assertEqual(resp[1].id, "2") | ||
self.assertRegex(resp[1].error.msg, "conflict") | ||
|
||
mock_grpc.Update.assert_called_once() | ||
called_with = mock_grpc.Update.call_args.args[0] | ||
self.assertEqual(called_with.project, search_index.project) | ||
self.assertEqual(called_with.index, search_index.name) | ||
self.assertEqual(list(map(bytes_to_dict, called_with.documents)), docs) | ||
|
||
def test_update_many_with_error(self, grpc_search): | ||
docs = [{"id": 1, "name": "shoe"}, {"id": 2, "name": "jacket"}] | ||
search_index = SearchIndex(self.index_name, grpc_search(), self.client_config) | ||
mock_grpc = grpc_search() | ||
mock_grpc.Update.side_effect = StubRpcError( | ||
code="Unavailable", details="operational failure" | ||
) | ||
|
||
with self.assertRaisesRegex(TigrisServerError, "operational failure") as e: | ||
search_index.update_many(docs) | ||
self.assertIsNotNone(e) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
import grpc | ||
|
||
from api.generated.server.v1.search_pb2 import ( | ||
CreateOrUpdateIndexRequest, | ||
CreateOrUpdateIndexResponse, | ||
DeleteIndexRequest, | ||
DeleteIndexResponse, | ||
) | ||
from api.generated.server.v1.search_pb2_grpc import SearchStub | ||
from tigrisdb.errors import TigrisException, TigrisServerError | ||
from tigrisdb.search_index import SearchIndex | ||
from tigrisdb.types import ClientConfig | ||
from tigrisdb.utils import schema_to_bytes | ||
|
||
|
||
class Search: | ||
__client: SearchStub | ||
__config: ClientConfig | ||
|
||
def __init__(self, client: SearchStub, config: ClientConfig): | ||
self.__client = client | ||
self.__config = config | ||
|
||
@property | ||
def project(self): | ||
return self.__config.project_name | ||
|
||
def create_or_update_index(self, name: str, schema: dict) -> SearchIndex: | ||
req = CreateOrUpdateIndexRequest( | ||
project=self.project, name=name, schema=schema_to_bytes(schema) | ||
) | ||
try: | ||
resp: CreateOrUpdateIndexResponse = self.__client.CreateOrUpdateIndex(req) | ||
except grpc.RpcError as e: | ||
raise TigrisServerError("failed to create search index", e) | ||
|
||
if resp.status == "created": | ||
return SearchIndex( | ||
index_name=name, client=self.__client, config=self.__config | ||
) | ||
|
||
raise TigrisException(f"Invalid response to create search index: {resp.status}") | ||
|
||
def delete_index(self, name: str) -> bool: | ||
req = DeleteIndexRequest(name=name, project=self.project) | ||
try: | ||
resp: DeleteIndexResponse = self.__client.DeleteIndex(req) | ||
except grpc.RpcError as e: | ||
raise TigrisServerError("failed to delete search index", e) | ||
|
||
return resp.status == "deleted" |
Oops, something went wrong.