-
Notifications
You must be signed in to change notification settings - Fork 1.8k
feat(firestore): configure gRPC message length limits for large documents #18220
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -3708,3 +3708,39 @@ async def in_transaction(transaction): | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| await in_transaction(transaction) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # make sure we didn't skip assertions in inner function | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert inner_fn_ran is True | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @pytest.mark.parametrize("database", [FIRESTORE_ENTERPRISE_DB], indirect=True) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| async def test_large_document_standard_writes_async(client, cleanup, database): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """Test standard write and read operations for large document on Enterprise DB (async).""" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| collection_id = "large_docs_async_" + UNIQUE_RESOURCE_ID | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| doc_ref = client.collection(collection_id).document("large_doc") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| cleanup(doc_ref.delete) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| large_payload = "c" * (900 * 1024) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| await doc_ref.set({"payload": large_payload}) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| snapshot = await doc_ref.get() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert snapshot.exists | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert snapshot.to_dict() == {"payload": large_payload} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @pytest.mark.parametrize("method", ["execute", "stream"]) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @pytest.mark.parametrize("database", [FIRESTORE_ENTERPRISE_DB], indirect=True) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| async def test_large_document_pipeline_async(client, cleanup, database, method): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """Test async pipeline execution over large document on Enterprise DB.""" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| collection_id = "large_pipeline_async_" + UNIQUE_RESOURCE_ID | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| col_ref = client.collection(collection_id) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| doc_ref = col_ref.document("large_doc") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| cleanup(doc_ref.delete) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| large_payload = "d" * (900 * 1024) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| await doc_ref.set({"payload": large_payload}) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pipeline = client.pipeline().collection(collection_id) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if method == "execute": | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| results = await pipeline.execute() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| else: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| results = [doc async for doc in pipeline.stream()] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert [doc.data() for doc in results] == [{"payload": large_payload}] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+3730
to
+3746
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Similar to the standard writes test,
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -110,9 +110,13 @@ def test_baseclient__firestore_api_helper_wo_emulator(): | |
|
|
||
| assert api is client_class.return_value | ||
| assert client._firestore_api_internal is api | ||
| channel_options = {"grpc.keepalive_time_ms": 30000} | ||
| channel_options = [ | ||
| ("grpc.keepalive_time_ms", 30000), | ||
| ("grpc.max_send_message_length", -1), | ||
| ("grpc.max_receive_message_length", -1), | ||
| ] | ||
| transport_class.create_channel.assert_called_once_with( | ||
| target, credentials=client._credentials, options=channel_options.items() | ||
| target, credentials=client._credentials, options=channel_options | ||
| ) | ||
| transport_class.assert_called_once_with( | ||
| host=target, | ||
|
|
@@ -236,7 +240,12 @@ def test_baseclient__emulator_channel(): | |
| with mock.patch("grpc.insecure_channel") as insecure_channel: | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we also need to test I would expect something like |
||
| channel = client._emulator_channel(FirestoreGrpcTransport) | ||
| insecure_channel.assert_called_once_with( | ||
| emulator_host, options=[("Authorization", "Bearer test")] | ||
| emulator_host, | ||
| options=[ | ||
| ("Authorization", "Bearer test"), | ||
| ("grpc.max_send_message_length", -1), | ||
| ("grpc.max_receive_message_length", -1), | ||
| ], | ||
| ) | ||
|
|
||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In async tests,
doc_ref.deleteis an asynchronous coroutine function. Passing it directly to a synchronouscleanupfixture will result in the coroutine being called but never awaited, which triggers aRuntimeWarning: coroutine 'AsyncDocumentReference.delete' was never awaitedand fails to clean up the document in the database. Instead, use atry...finallyblock to explicitly await the deletion of the document.