blob: 0bb2f53fadd733ebc0dc0640908a8bbaba67a2d6 [file] [log] [blame]
% 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(couch_views_updater).
-export([
index/6
]).
-include_lib("couch/include/couch_db.hrl").
-include_lib("couch_views/include/couch_views.hrl").
-include_lib("kernel/include/logger.hrl").
% If the doc revision doesn't not match the NewRevId passed here we can ignore
% the document since it is then a conflict document and it doesn't need
% to be indexed.
index(
Db,
#doc{id = Id, revs = Revs} = Doc,
_NewWinner,
_OldWinner,
NewRevId,
Seq
) ->
try
{Depth, [FirstRev | _]} = Revs,
DocRev = {Depth, FirstRev},
if
DocRev /= NewRevId -> ok;
true -> index_int(Db, Doc, Seq)
end
catch
error:{erlfdb_error, ErrCode}:Stack when is_integer(ErrCode) ->
DbName = fabric2_db:name(Db),
?LOG_ERROR(#{
what => mango_index_update,
status => erlfdb_error,
details => ErrCode,
db => DbName,
docid => Id
}),
couch_log:error(
"Mango index erlfdb error Db ~s Doc ~p ~p",
[DbName, Id, ErrCode]
),
erlang:raise(error, {erlfdb_error, ErrCode}, Stack);
Error:Reason ->
DbName = fabric2_db:name(Db),
?LOG_ERROR(#{
what => mango_index_update,
status => Error,
details => Reason,
db => DbName,
docid => Id
}),
couch_log:error(
"Mango index error for Db ~s Doc ~p ~p ~p",
[DbName, Id, Error, Reason]
)
end.
% Check if design doc is an interactive index and kick off background worker
% to build the new index up to the creation_vs
index_int(
Db,
#doc{
id = <<?DESIGN_DOC_PREFIX, _/binary>>,
deleted = false
} = DDoc,
Seq
) ->
DbName = fabric2_db:name(Db),
case couch_views_ddoc:is_interactive(DDoc) of
true ->
{ok, Mrst} = couch_views_util:ddoc_to_mrst(DbName, DDoc),
case couch_views_fdb:get_creation_vs(Db, Mrst) of
not_found ->
couch_views_fdb:new_interactive_index(Db, Mrst, Seq),
{ok, _} = couch_views_jobs:build_view_async(Db, Mrst);
_ ->
ok
end;
false ->
ok
end,
write_doc(Db, DDoc);
index_int(Db, #doc{} = Doc, _Seq) ->
write_doc(Db, Doc).
write_doc(Db, #doc{deleted = Deleted} = Doc) ->
DbName = fabric2_db:name(Db),
DDocs = couch_views_ddoc:get_interactive_list(Db),
Result0 = [
#{
id => Doc#doc.id,
results => [],
deleted => Deleted,
doc => Doc
}
],
%% Interactive updates do not update the views update_seq
State = #{
last_seq => false
},
lists:foreach(
fun(DDoc) ->
{ok, Mrst0} = couch_views_util:ddoc_to_mrst(DbName, DDoc),
Mrst1 = couch_views_trees:open(Db, Mrst0),
case should_index_doc(Doc, Mrst1) of
true ->
{Mrst2, Result1} = couch_views_indexer:map_docs(Mrst1, Result0),
DocNumber = couch_views_indexer:write_docs(
Db,
Mrst2,
Result1,
State
),
couch_views_plugin:after_interactive_write(
Db,
Mrst2,
Result1,
DocNumber
),
couch_eval:release_map_context(Mrst2#mrst.qserver);
false ->
ok
end
end,
DDocs
).
should_index_doc(<<?DESIGN_DOC_PREFIX, _/binary>>, Mrst) ->
lists:keymember(<<"include_design">>, 1, Mrst#mrst.design_opts);
should_index_doc(_, _) ->
true.