summaryrefslogtreecommitdiff
path: root/src/couch_views/src/couch_views_indexer.erl
diff options
context:
space:
mode:
Diffstat (limited to 'src/couch_views/src/couch_views_indexer.erl')
-rw-r--r--src/couch_views/src/couch_views_indexer.erl54
1 files changed, 52 insertions, 2 deletions
diff --git a/src/couch_views/src/couch_views_indexer.erl b/src/couch_views/src/couch_views_indexer.erl
index 0a57a70ee..83f7e2851 100644
--- a/src/couch_views/src/couch_views_indexer.erl
+++ b/src/couch_views/src/couch_views_indexer.erl
@@ -29,6 +29,8 @@
% TODO:
% * Handle timeouts of transaction and other errors
+-define(KEY_SIZE_LIMIT, 8000).
+-define(VALUE_SIZE_LIMIT, 64000).
spawn_link() ->
proc_lib:spawn_link(?MODULE, init, []).
@@ -297,8 +299,13 @@ write_docs(TxDb, Mrst, Docs, State) ->
last_seq := LastSeq
} = State,
- lists:foreach(fun(Doc) ->
- couch_views_fdb:write_doc(TxDb, Sig, Views, Doc)
+ ViewIds = [View#mrview.id_num || View <- Views],
+ KeyLimit = key_size_limit(),
+ ValLimit = value_size_limit(),
+
+ lists:foreach(fun(Doc0) ->
+ Doc1 = calculate_kv_sizes(Mrst, Doc0, KeyLimit, ValLimit),
+ couch_views_fdb:write_doc(TxDb, Sig, ViewIds, Doc1)
end, Docs),
couch_views_fdb:set_update_seq(TxDb, Sig, LastSeq).
@@ -368,6 +375,41 @@ start_query_server(#mrst{} = Mrst) ->
Mrst.
+calculate_kv_sizes(Mrst, Doc, KeyLimit, ValLimit) ->
+ #mrst{
+ db_name = DbName,
+ idx_name = IdxName
+ } = Mrst,
+ #{
+ results := Results
+ } = Doc,
+ try
+ KVSizes = lists:map(fun(ViewRows) ->
+ lists:foldl(fun({K, V}, Acc) ->
+ KeySize = erlang:external_size(K),
+ ValSize = erlang:external_size(V),
+
+ if KeySize =< KeyLimit -> ok; true ->
+ throw({size_error, key})
+ end,
+
+ if ValSize =< ValLimit -> ok; true ->
+ throw({size_error, value})
+ end,
+
+ Acc + KeySize + ValSize
+ end, 0, ViewRows)
+ end, Results),
+ Doc#{kv_sizes => KVSizes}
+ catch throw:{size_error, Type} ->
+ #{id := DocId} = Doc,
+ Fmt = "View ~s size error for docid `~s`, excluded from indexing "
+ "in db `~s` for design doc `~s`",
+ couch_log:error(Fmt, [Type, DocId, DbName, IdxName]),
+ Doc#{deleted := true, results := [], kv_sizes => []}
+ end.
+
+
report_progress(State, UpdateType) ->
#{
tx_db := TxDb,
@@ -419,3 +461,11 @@ num_changes() ->
retry_limit() ->
config:get_integer("couch_views", "retry_limit", 3).
+
+
+key_size_limit() ->
+ config:get_integer("couch_views", "key_size_limit", ?KEY_SIZE_LIMIT).
+
+
+value_size_limit() ->
+ config:get_integer("couch_views", "value_size_limit", ?VALUE_SIZE_LIMIT).