You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by da...@apache.org on 2017/03/16 15:50:48 UTC
chttpd commit: updated refs/heads/COUCHDB-3326-clustered-purge to
a6572cf [Forced Update!]
Repository: couchdb-chttpd
Updated Branches:
refs/heads/COUCHDB-3326-clustered-purge b22c5b2d4 -> a6572cfb4 (forced update)
Implement clustered purge HTTP endpoint
COUCHDB-3326
Project: http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/commit/a6572cfb
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/tree/a6572cfb
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/diff/a6572cfb
Branch: refs/heads/COUCHDB-3326-clustered-purge
Commit: a6572cfb4bedcb77484536587ae938176b224dc4
Parents: d672352
Author: Mayya Sharipova <ma...@ca.ibm.com>
Authored: Thu Nov 17 17:55:02 2016 -0500
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Thu Mar 16 10:50:41 2017 -0500
----------------------------------------------------------------------
src/chttpd_db.erl | 47 ++++++++++++----
test/chttpd_purge_tests.erl | 112 +++++++++++++++++++++++++++++++++++++++
2 files changed, 148 insertions(+), 11 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/blob/a6572cfb/src/chttpd_db.erl
----------------------------------------------------------------------
diff --git a/src/chttpd_db.erl b/src/chttpd_db.erl
index 738cfe4..0bd7b8a 100644
--- a/src/chttpd_db.erl
+++ b/src/chttpd_db.erl
@@ -496,19 +496,20 @@ db_req(#httpd{path_parts=[_, <<"_bulk_get">>]}=Req, _Db) ->
db_req(#httpd{method='POST',path_parts=[_,<<"_purge">>]}=Req, Db) ->
chttpd:validate_ctype(Req, "application/json"),
+ W = chttpd:qs_value(Req, "w", integer_to_list(mem3:quorum(Db))),
+ Options = [{user_ctx, Req#httpd.user_ctx}, {w, W}],
{IdsRevs} = chttpd:json_body_obj(Req),
IdsRevs2 = [{Id, couch_doc:parse_revs(Revs)} || {Id, Revs} <- IdsRevs],
- case fabric:purge_docs(Db, IdsRevs2) of
- {ok, PurgeSeq, PurgedIdsRevs} ->
- PurgedIdsRevs2 = [{Id, couch_doc:revs_to_strs(Revs)} || {Id, Revs}
- <- PurgedIdsRevs],
- send_json(Req, 200, {[
- {<<"purge_seq">>, PurgeSeq},
- {<<"purged">>, {PurgedIdsRevs2}}
- ]});
- Error ->
- throw(Error)
- end;
+ {Status, {PurgeSeq, Results}} = fabric:purge_docs(Db, IdsRevs2, Options),
+ Code = case Status of
+ ok -> 201;
+ accepted -> 202
+ end,
+ Purged = lists:zipwith(fun purge_result_to_json/2, IdsRevs2, Results),
+ send_json(Req, Code, {[
+ {purged, Purged},
+ {purge_seq, PurgeSeq}
+ ]});
db_req(#httpd{path_parts=[_,<<"_purge">>]}=Req, _Db) ->
send_method_not_allowed(Req, "POST");
@@ -607,6 +608,21 @@ db_req(#httpd{method='GET',path_parts=[_,<<"_revs_limit">>]}=Req, Db) ->
db_req(#httpd{path_parts=[_,<<"_revs_limit">>]}=Req, _Db) ->
send_method_not_allowed(Req, "PUT,GET");
+db_req(#httpd{method='PUT',path_parts=[_,<<"_purged_docs_limit">>]}=Req, Db) ->
+ Limit = chttpd:json_body(Req),
+ Options = [{user_ctx, Req#httpd.user_ctx}],
+ case chttpd:json_body(Req) of
+ Limit when is_integer(Limit), Limit > 0 ->
+ ok = fabric:set_purged_docs_limit(Db, Limit, Options),
+ send_json(Req, {[{<<"ok">>, true}]});
+ _->
+ throw({bad_request, "`purged_docs_limit` must be positive integer"})
+ end;
+
+db_req(#httpd{method='GET',path_parts=[_,<<"_purged_docs_limit">>]}=Req, Db) ->
+ send_json(Req, fabric:get_purged_docs_limit(Db));
+
+
% Special case to enable using an unencoded slash in the URL of design docs,
% as slashes in document IDs must otherwise be URL encoded.
db_req(#httpd{method='GET', mochi_req=MochiReq, path_parts=[_DbName, <<"_design/", _/binary>> | _]}=Req, _Db) ->
@@ -954,6 +970,15 @@ update_doc_result_to_json(DocId, Error) ->
{[{id, DocId}, {error, ErrorStr}, {reason, Reason}]}.
+purge_result_to_json({DocId, _Revs}, {ok, PRevs}) ->
+ {[{ok, true}, {id, DocId}, {revs, couch_doc:revs_to_strs(PRevs)}]};
+purge_result_to_json({DocId, _Revs}, {accepted, PRevs}) ->
+ {[{ok, true}, {id, DocId}, {revs, couch_doc:revs_to_strs(PRevs)}, {accepted, true}]};
+purge_result_to_json({DocId, _Revs}, Error) ->
+ {_Code, ErrorStr, Reason} = chttpd:error_info(Error),
+ {[{id, DocId}, {error, ErrorStr}, {reason, Reason}]}.
+
+
send_updated_doc(Req, Db, DocId, Json) ->
send_updated_doc(Req, Db, DocId, Json, []).
http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/blob/a6572cfb/test/chttpd_purge_tests.erl
----------------------------------------------------------------------
diff --git a/test/chttpd_purge_tests.erl b/test/chttpd_purge_tests.erl
new file mode 100644
index 0000000..3b18e3e
--- /dev/null
+++ b/test/chttpd_purge_tests.erl
@@ -0,0 +1,112 @@
+% Licensed under the Apache License, Version 2.0 (the "License"); you may not
+% use this file except in compliance with the License. You may obtain a copy of
+% the License at
+%
+% http://www.apache.org/licenses/LICENSE-2.0
+%
+% Unless required by applicable law or agreed to in writing, software
+% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+% License for the specific language governing permissions and limitations under
+% the License.
+
+-module(chttpd_purge_tests).
+
+
+-include_lib("couch/include/couch_eunit.hrl").
+-include_lib("couch/include/couch_db.hrl").
+
+
+-define(USER, "chttpd_db_test_admin").
+-define(PASS, "pass").
+-define(AUTH, {basic_auth, {?USER, ?PASS}}).
+-define(CONTENT_JSON, {"Content-Type", "application/json"}).
+
+
+setup() ->
+ ok = config:set("admins", ?USER, ?PASS, _Persist=false),
+ TmpDb = ?tempdb(),
+ Addr = config:get("chttpd", "bind_address", "127.0.0.1"),
+ Port = mochiweb_socket_server:get(chttpd, port),
+ Url = lists:concat(["http://", Addr, ":", Port, "/", ?b2l(TmpDb)]),
+ create_db(Url),
+ Url.
+
+
+teardown(Url) ->
+ delete_db(Url),
+ ok = config:delete("admins", ?USER, _Persist=false).
+
+
+create_db(Url) ->
+ {ok, Status, _, _} = test_request:put(Url, [?CONTENT_JSON, ?AUTH], "{}"),
+ ?assert(Status =:= 201 orelse Status =:= 202).
+
+
+create_doc(Url, Id) ->
+ test_request:put(Url ++ "/" ++ Id,
+ [?CONTENT_JSON, ?AUTH], "{\"mr\": \"rockoartischocko\"}").
+
+
+delete_db(Url) ->
+ {ok, 200, _, _} = test_request:delete(Url, [?AUTH]).
+
+
+purge_test_() ->
+ {
+ "chttpd db tests",
+ {
+ setup,
+ fun chttpd_test_util:start_couch/0,
+ fun chttpd_test_util:stop_couch/1,
+ {
+ foreach,
+ fun setup/0,
+ fun teardown/1,
+ [
+ fun test_ok_purge_request/1,
+ fun should_error_set_purged_docs_limit_to0/1
+ ]
+ }
+ }
+ }.
+
+
+test_ok_purge_request(Url) ->
+ ?_test(begin
+ {ok, _, _, Body} = create_doc(Url, "doc1"),
+ {Json} = ?JSON_DECODE(Body),
+ Rev1 = couch_util:get_value(<<"rev">>, Json, undefined),
+ {ok, _, _, Body2} = create_doc(Url, "doc2"),
+ {Json2} = ?JSON_DECODE(Body2),
+ Rev2 = couch_util:get_value(<<"rev">>, Json2, undefined),
+ {ok, _, _, Body3} = create_doc(Url, "doc3"),
+ {Json3} = ?JSON_DECODE(Body3),
+ Rev3 = couch_util:get_value(<<"rev">>, Json3, undefined),
+ IdsRevs = "{\"doc1\": [\"" ++ ?b2l(Rev1) ++ "\"], \"doc2\": [\"" ++
+ ?b2l(Rev2) ++ "\"], \"doc3\": [\"" ++ ?b2l(Rev3) ++ "\"] }",
+
+ {ok, Status, _, ResultBody} = test_request:post(Url ++ "/_purge/",
+ [?CONTENT_JSON, ?AUTH], IdsRevs),
+ ?assert(Status =:= 201 orelse Status =:= 202),
+ ResultJson = ?JSON_DECODE(ResultBody),
+ ?assertMatch(
+ {[
+ {<<"purged">>, [
+ {[{<<"ok">>,true}, {<<"id">>,<<"doc1">>}, {<<"revs">>,[Rev1]}]},
+ {[{<<"ok">>,true}, {<<"id">>,<<"doc2">>}, {<<"revs">>,[Rev2]}]},
+ {[{<<"ok">>,true}, {<<"id">>,<<"doc3">>}, {<<"revs">>,[Rev3]}]}
+ ]},
+ {<<"purge_seq">>, _}
+ ]},
+ ResultJson
+ )
+ end).
+
+
+should_error_set_purged_docs_limit_to0(Url) ->
+ ?_test(begin
+ {ok, Status, _, _} = test_request:put(Url ++ "/_purged_docs_limit/",
+ [?CONTENT_JSON, ?AUTH], "0"),
+ ?assert(Status =:= 400)
+ end).