Skip to content
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

convert erlfdb_error 2101 to transaction_too_large #3215

Merged
merged 1 commit into from
Oct 20, 2020

Conversation

jiangphcn
Copy link
Contributor

@jiangphcn jiangphcn commented Oct 13, 2020

Overview

If transaction exceeds byte limit using the _bulk_docs endpoint, the {u'reason': u'2101', u'ref': 3853288219, u'error': u'erlfdb_error'} with 500 error code was returned. This is user-friendly. Using this PR is to provide meaningful error message to users.

Testing recommendations

The test python code:

import requests, json, random, string, os
print(requests.post(
    "http:https://127.0.0.1:15984/foo/_bulk_docs"
    , json={
        "docs":
            [
                {"foo": "".join(random.choice(string.ascii_lowercase) for x in range(16000000))}
            ]}
    , auth=('foo', 'bar')
).json())

Original response:

{u'reason': u'2101', u'ref': 3853288219, u'error': u'erlfdb_error'}

New response:

{u'reason': u'The request transaction is larger than 10MB', u'error': u'transaction_too_large'}

make elixir tests=test/elixir/test/bulk_docs_test.exs
make exunit tests=src/couchdb/test/elixir/test/bulk_docs_test.exs

BulkDocsTest
  * test bulk docs raises error for invlaid `docs` parameter (75.5ms)
  * test bulk docs supplies `id` if not provided in doc (38.9ms)
  * test bulk docs can detect conflicts (64.4ms)
  * test bulk docs raises error for invlaid `new_edits` parameter (13.3ms)
  * test bulk docs raises error for missing `docs` parameter (13.0ms)
  * test bulk docs raises transaction_too_large error for transaction larger than 10MB (1384.9ms)
  * test bulk docs raises error for `all_or_nothing` option (13.6ms)
  * test bulk docs raises conflict error for combined update & delete (40.6ms)
  * test bulk docs emits conflict error for duplicate doc `_id`s (23.2ms)
  * test bulk docs can create, update, & delete many docs per request (78.3ms)


Finished in 2.0 seconds
10 tests, 0 failures

Randomized with seed 913112

Related Issues or Pull Requests

Checklist

Copy link
Member

@bessbd bessbd left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The change looks good to me, +1! (non-binding)
I wonder if it's easy to add a test case for this.

@@ -362,6 +362,8 @@ catch_error(HttpReq, error, decryption_failed) ->
send_error(HttpReq, decryption_failed);
catch_error(HttpReq, error, not_ciphertext) ->
send_error(HttpReq, not_ciphertext);
catch_error(HttpReq, error, {erlfdb_error,2101}) ->
send_error(HttpReq, {request_transcation_too_large, 2101});
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit:

Suggested change
send_error(HttpReq, {request_transcation_too_large, 2101});
send_error(HttpReq, {request_transaction_too_large, 2101});

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could probably just use the transaction_too_large atom instead of the tuple {request_transaction_too_large, 2101} since the tag explains the error pretty well.

And we'd want to stay somewhat consistent with https://apple.github.io/foundationdb/api-error-codes.html

transaction_too_large | 2101 | Transaction exceeds byte limit

@@ -362,6 +362,8 @@ catch_error(HttpReq, error, decryption_failed) ->
send_error(HttpReq, decryption_failed);
catch_error(HttpReq, error, not_ciphertext) ->
send_error(HttpReq, not_ciphertext);
catch_error(HttpReq, error, {erlfdb_error,2101}) ->
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's leave a space after , and 2101

error_info({request_transcation_too_large, Code}) ->
CodeBin = integer_to_binary(Code),
{413, <<"request_transcation_too_large">>,
<<"The request transcation is too large. (", CodeBin/binary, ")" >>};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Users might confuse 2101 with the transaction size limit. Since we know the limit as 10MB we can just include in the message perhaps something like {413, <<"transaction_too_large">>, <<"The request transaction is larger than 10MB">>}

Copy link
Contributor

@nickva nickva left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great improvement!

Made a few suggestions about simplifying the error names.

Good idea by @bessbd to add tests. Maybe in fabric2_update_docs_tests or if you can find a better place. Just make sure to generate random data so compression doesn't undo your large data generation.

Then it should be good to go.

As an extra aside to this PR, and mainly for discussion, it is interesting that max doc size doesn't take effect here. We should double check why does max_document_size limit of 8MB from default.ini not work? Is it because the check there is approximate (json "size") or, there is a bug somewhere with _bulk_docs. What if we lowered the max doc size limit to 4MB would we start getting a max doc size error then...?

@jiangphcn
Copy link
Contributor Author

thanks @nickva and @bessbd. Good suggestions. Looks that I am in the right way, and I will refine message and add test.

Copy link
Member

@davisp davisp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1

@jiangphcn
Copy link
Contributor Author

jiangphcn commented Oct 16, 2020

thanks @davisp's review.

@nickva @bessbd I used d4557f2 to address your comments. Could you please take another look?

@bessbd
Copy link
Member

bessbd commented Oct 16, 2020

LGTM. Thank you for the test case, @jiangphcn

@@ -362,6 +362,8 @@ catch_error(HttpReq, error, decryption_failed) ->
send_error(HttpReq, decryption_failed);
catch_error(HttpReq, error, not_ciphertext) ->
send_error(HttpReq, not_ciphertext);
catch_error(HttpReq, error, {erlfdb_error, 2101}) ->
send_error(HttpReq, transcation_too_large);
Copy link
Member

@bessbd bessbd Oct 16, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, just realized there's a typo here (and on line 1014):

Suggested change
send_error(HttpReq, transcation_too_large);
send_error(HttpReq, transaction_too_large);

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch, and fixed in 4f7caf7

test "bulk docs raises transaction_too_large error for transaction larger than 10MB", ctx do
docs = [%{_id: "0", a: random_string(16_000_000)}]
resp = Couch.post("/#{ctx[:db_name]}/_bulk_docs", body: %{docs: docs})
assert resp.status_code == 413
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's match on the error message ("transaction_too_large") since we're testing for it.

Wondering if with 16MB we would hit transaction_too_large or the document size limit of 8MB. If we don't hit 8MB we may have another bug to fix about why that doesn't work.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are different settings on CouchDB and Cloudant for Transaction Engine for max_document_size.

max_document_size = 8000000 ; bytes  (CouchDB)
max_document_size = 67108864 ; 64 MB (Cloudant for Transaction Engine)

So by default, we will get document_too_large in CouchDB while we will get transaction_too_large if we pass 16MB document.

I added codes to adjust max_document_size in this test to support 64MB documents to get transaction_too_large in any cases.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jiangphcn

Good find!

TxE is technically Cloudant's problem and shouldn't have any relevance for CouchDB. Though looking at the code there, is that the /dev/run instance may have 65Mb however the instance used in production has 1Mb.

Also maybe in a separate commit, we could probably switch to using the code default (in Erlang) to be 8Mb instead of keeping in the default.ini. Then default.ini can be a commented out line with the default value in it like we usually do it.

@jiangphcn jiangphcn force-pushed the transaction_too_large branch 2 times, most recently from a0ba69a to 7e97a04 Compare October 19, 2020 03:02
@tag :with_db
test "bulk docs raises transaction_too_large error for transaction larger than 10MB", ctx do
docs = [%{_id: "0", a: random_string(16_000_000)}]
set_config_raw("couchdb", "max_document_size", "67108864")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will this automatically reset if the test ends (either ok or fails)? We wouldn't want to alter the max doc size for other tests here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, the setting on [couchdb][max_document_size] will not be reverted after one test or test suite ends. I added codes to revert them. I believe that currently we are fine with this test.

Copy link
Contributor

@nickva nickva left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 After double-checking that the config changes are reverted after the test finishes

@jiangphcn jiangphcn force-pushed the transaction_too_large branch 7 times, most recently from 9f3fb54 to e275669 Compare October 20, 2020 04:51
@jiangphcn jiangphcn merged commit 7bdb432 into prototype/fdb-layer Oct 20, 2020
@jiangphcn jiangphcn deleted the transaction_too_large branch October 20, 2020 12:49
@nickva
Copy link
Contributor

nickva commented Oct 20, 2020

@jiangphcn One more thing is we'd have to merge this to main since we use main as the 4.x branch

@jiangphcn
Copy link
Contributor Author

Good reminder, @nickva. I will do soon.

@wohali
Copy link
Member

wohali commented Oct 20, 2020

Yeah, we should be careful, prototype/fdb-layer is slated to be removed this week.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants