Skip to content

Commit 1ce340a

Browse files
committed
MB-51403 Handle etmpfail in CRUD endpoints
Rather than crash with a Server Error when memcached returns etmpfail to a CRUD endpoint request we'll now bubble up the error and return http error 503. Change-Id: Ib3420d20c33cb9c190fabef89b3ead681dcebf0b Reviewed-on: https://review.couchbase.org/c/ns_server/+/172224 Well-Formed: Build Bot <[email protected]> Tested-by: Steve Watanabe <[email protected]> Reviewed-by: Artem Stemkovski <[email protected]>
1 parent 1b5cd2e commit 1ce340a

File tree

2 files changed

+16
-1
lines changed

2 files changed

+16
-1
lines changed

src/capi_crud.erl

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
construct_error_context(Context) ->
2525
mochijson2:encode({[{error, [{"context", Context}]}]}).
2626

27-
%% TODO: handle tmp failures here. E.g. during warmup
2827
handle_mutation_rv(#mc_header{status = ?SUCCESS} = _Header, _Entry) ->
2928
ok;
3029
handle_mutation_rv(#mc_header{status = ?KEY_ENOENT} = _Header, _Entry) ->
@@ -33,6 +32,8 @@ handle_mutation_rv(#mc_header{status = ?EINVAL} = _Header, Entry) ->
3332
{error, Entry#mc_entry.data};
3433
handle_mutation_rv(#mc_header{status = ?UNKNOWN_COLLECTION}, Entry) ->
3534
{error, Entry#mc_entry.data};
35+
handle_mutation_rv(#mc_header{status = ?ETMPFAIL}, _Entry) ->
36+
{retry_needed, etmpfail};
3637
handle_mutation_rv(#mc_header{status = ?NOT_MY_VBUCKET} = _Header, _Entry) ->
3738
throw(not_my_vbucket).
3839

@@ -126,6 +127,8 @@ get_inner(Bucket, DocId, CollectionUid, VBucket, Options, Identity,
126127
throw(not_my_vbucket);
127128
?UNKNOWN_COLLECTION ->
128129
{error, Entry#mc_entry.data};
130+
?ETMPFAIL ->
131+
{retry_needed, etmpfail};
129132
?EINVAL ->
130133
{error, Entry#mc_entry.data}
131134
end.

src/menelaus_web_crud.erl

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,10 @@ construct_error_reply(Msg) ->
255255
end,
256256
{struct, [{error, <<"bad_request">>}, {reason, Reason}]}.
257257

258+
construct_etmpfail_error_reply() ->
259+
{struct, [{error, <<"retry_needed">>},
260+
{reason, <<"etmpfail returned from memcached">>}]}.
261+
258262
handle_get(BucketId, DocId, Req) ->
259263
CollectionUid = assert_default_collection_uid(BucketId),
260264
XAttrPerm = get_xattrs_permissions(BucketId, "_default", "_default", Req),
@@ -267,6 +271,8 @@ do_handle_get(BucketId, DocId, CollectionUid, XAttrPermissions, Req) ->
267271
menelaus_util:reply(Req, 404);
268272
{error, Msg} ->
269273
menelaus_util:reply_json(Req, construct_error_reply(Msg), 400);
274+
{retry_needed, etmpfail} ->
275+
menelaus_util:reply_json(Req,construct_etmpfail_error_reply(), 503);
270276
{ok, EJSON, {XAttrs}} ->
271277
{Json} = capi_utils:couch_doc_to_json(EJSON, unparsed),
272278
ns_audit:read_doc(Req, BucketId, DocId),
@@ -334,6 +340,9 @@ handle_post(BucketId, DocId, CollectionUid, Req) ->
334340
case mutate(Req, set, BucketId, DocId, CollectionUid, Value, Flags) of
335341
ok ->
336342
menelaus_util:reply_json(Req, []);
343+
{retry_needed, etmpfail} ->
344+
menelaus_util:reply_json(Req, construct_etmpfail_error_reply(),
345+
503);
337346
{error, Msg} ->
338347
menelaus_util:reply_json(Req, construct_error_reply(Msg), 400)
339348
end.
@@ -347,6 +356,9 @@ handle_delete(BucketId, DocId, CollectionUid, Req) ->
347356
undefined, undefined) of
348357
ok ->
349358
menelaus_util:reply_json(Req, []);
359+
{retry_needed, etmpfail} ->
360+
menelaus_util:reply_json(Req, construct_etmpfail_error_reply(),
361+
503);
350362
{error, Msg} ->
351363
menelaus_util:reply_json(Req, construct_error_reply(Msg), 400)
352364
end.

0 commit comments

Comments
 (0)