summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Newson <rnewson@apache.org>2013-12-03 11:15:59 +0000
committerRobert Newson <rnewson@apache.org>2013-12-03 13:10:49 +0000
commit08cac68b26d95b90dedadbb5d162d082226ec5ca (patch)
tree01c0b1f359edc5149f872a6f50c7368e97dcef21
parent352e7315462618bf21ac447d3ae30a8881c8bacb (diff)
downloadcouchdb-08cac68b26d95b90dedadbb5d162d082226ec5ca.tar.gz
Include reason for replication failure in _replicator doc
closes COUCHDB-1647
-rw-r--r--share/doc/src/replication/replicator.rst8
-rw-r--r--share/www/script/test/replicator_db_invalid_filter.js4
-rw-r--r--src/couch_replicator/src/couch_replicator_manager.erl10
-rw-r--r--src/couchdb/couch_doc.erl3
4 files changed, 21 insertions, 4 deletions
diff --git a/share/doc/src/replication/replicator.rst b/share/doc/src/replication/replicator.rst
index b4427faf6..05171db4d 100644
--- a/share/doc/src/replication/replicator.rst
+++ b/share/doc/src/replication/replicator.rst
@@ -86,6 +86,10 @@ Special fields set by the replicator start with the prefix
when the current replication state (marked in ``_replication_state``)
was set.
+- ``_replication_state_reason``
+
+ If ``replication_state`` is ``error``, this field contains the reason.
+
When the replication finishes, it will update the ``_replication_state``
field (and ``_replication_state_time``) with the value ``completed``, so
the document will look like:
@@ -103,8 +107,8 @@ the document will look like:
}
When an error happens during replication, the ``_replication_state``
-field is set to ``error`` (and ``_replication_state_time`` gets updated of
-course).
+field is set to ``error`` (and ``_replication_state_reason`` and
+``_replication_state_time`` are updated).
When you PUT/POST a document to the ``_replicator`` database, CouchDB
will attempt to start the replication up to 10 times (configurable under
diff --git a/share/www/script/test/replicator_db_invalid_filter.js b/share/www/script/test/replicator_db_invalid_filter.js
index 6438d4356..7b6df8296 100644
--- a/share/www/script/test/replicator_db_invalid_filter.js
+++ b/share/www/script/test/replicator_db_invalid_filter.js
@@ -41,6 +41,8 @@ couchTests.replicator_db_invalid_filter = function(debug) {
repDoc1 = repDb.open(repDoc1._id);
TEquals("undefined", typeof repDoc1._replication_id);
TEquals("error", repDoc1._replication_state);
+ TEquals("Could not open source database `couch_foo_test_db`: {db_not_found,<<\"couch_foo_test_db\">>}",
+ repDoc1._replication_state_reason);
populate_db(dbA, docs1);
populate_db(dbB, []);
@@ -58,6 +60,8 @@ couchTests.replicator_db_invalid_filter = function(debug) {
repDoc2 = repDb.open(repDoc2._id);
TEquals("undefined", typeof repDoc2._replication_id);
TEquals("error", repDoc2._replication_state);
+ TEquals("Couldn't open document `_design/test` from source database `test_suite_rep_db_a`: {error,<<\"not_found\">>}",
+ repDoc2._replication_state_reason);
var ddoc = {
_id: "_design/mydesign",
diff --git a/src/couch_replicator/src/couch_replicator_manager.erl b/src/couch_replicator/src/couch_replicator_manager.erl
index bbb0e1176..4891c4c4c 100644
--- a/src/couch_replicator/src/couch_replicator_manager.erl
+++ b/src/couch_replicator/src/couch_replicator_manager.erl
@@ -68,6 +68,7 @@ replication_started(#rep{id = {BaseId, _} = RepId}) ->
#rep_state{rep = #rep{doc_id = DocId}} ->
update_rep_doc(DocId, [
{<<"_replication_state">>, <<"triggered">>},
+ {<<"_replication_state_reason">>, undefined},
{<<"_replication_id">>, ?l2b(BaseId)},
{<<"_replication_stats">>, undefined}]),
ok = gen_server:call(?MODULE, {rep_started, RepId}, infinity),
@@ -83,6 +84,7 @@ replication_completed(#rep{id = RepId}, Stats) ->
#rep_state{rep = #rep{doc_id = DocId}} ->
update_rep_doc(DocId, [
{<<"_replication_state">>, <<"completed">>},
+ {<<"_replication_state_reason">>, undefined},
{<<"_replication_stats">>, {Stats}}]),
ok = gen_server:call(?MODULE, {rep_complete, RepId}, infinity),
?LOG_INFO("Replication `~s` finished (triggered by document `~s`)",
@@ -95,9 +97,9 @@ replication_error(#rep{id = {BaseId, _} = RepId}, Error) ->
nil ->
ok;
#rep_state{rep = #rep{doc_id = DocId}} ->
- % TODO: maybe add error reason to replication document
update_rep_doc(DocId, [
{<<"_replication_state">>, <<"error">>},
+ {<<"_replication_state_reason">>, to_binary(error_reason(Error))},
{<<"_replication_id">>, ?l2b(BaseId)}]),
ok = gen_server:call(?MODULE, {rep_error, RepId, Error}, infinity)
end.
@@ -344,7 +346,8 @@ rep_db_update_error(Error, DocId) ->
end,
?LOG_ERROR("Replication manager, error processing document `~s`: ~s",
[DocId, Reason]),
- update_rep_doc(DocId, [{<<"_replication_state">>, <<"error">>}]).
+ update_rep_doc(DocId, [{<<"_replication_state">>, <<"error">>},
+ {<<"_replication_state_reason">>, Reason}]).
rep_user_ctx({RepDoc}) ->
@@ -619,6 +622,9 @@ rep_state(RepId) ->
end.
+error_reason({error, {Error, Reason}})
+ when is_atom(Error), is_binary(Reason) ->
+ io_lib:format("~s: ~s", [Error, Reason]);
error_reason({error, Reason}) ->
Reason;
error_reason(Reason) ->
diff --git a/src/couchdb/couch_doc.erl b/src/couchdb/couch_doc.erl
index 39e235484..40473702f 100644
--- a/src/couchdb/couch_doc.erl
+++ b/src/couchdb/couch_doc.erl
@@ -295,6 +295,9 @@ transfer_fields([{<<"_replication_state">>, _} = Field | Rest],
transfer_fields([{<<"_replication_state_time">>, _} = Field | Rest],
#doc{body=Fields} = Doc) ->
transfer_fields(Rest, Doc#doc{body=[Field|Fields]});
+transfer_fields([{<<"_replication_state_reason">>, _} = Field | Rest],
+ #doc{body=Fields} = Doc) ->
+ transfer_fields(Rest, Doc#doc{body=[Field|Fields]});
transfer_fields([{<<"_replication_id">>, _} = Field | Rest],
#doc{body=Fields} = Doc) ->
transfer_fields(Rest, Doc#doc{body=[Field|Fields]});