Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Couch index fixes #4491

Merged
merged 4 commits into from
Mar 22, 2023
Merged

Couch index fixes #4491

merged 4 commits into from
Mar 22, 2023

Conversation

rnewson
Copy link
Member

@rnewson rnewson commented Mar 22, 2023

couch_index_server can crash if;

  1. an index, opened with new_index, crashes while doing so
  2. the db event listener pid crashes

This PR improves behaviour as follows;

  1. log original stack in couch_event_listener_mfa:db_event (but still throw)
  2. prevent couch_index_server:handle_db_event from crashing
  3. track the opener pids in couch_index_server, don't crash couch_index_server if they terminate abnormally

@rnewson rnewson requested review from davisp and nickva March 22, 2023 14:34
@rnewson rnewson assigned janl and unassigned janl Mar 22, 2023
@rnewson rnewson requested a review from janl March 22, 2023 14:35
@rnewson rnewson force-pushed the couch_index_fixes branch 3 times, most recently from a4f9267 to 8bf45ad Compare March 22, 2023 18:45
Comment on lines +355 to +380
fun(DbShard) ->
lists:foreach(
fun({_DbShard, {_DDocId, Sig}}) ->
% check if there are other ddocs with the same Sig for the same db
SigDDocs = ets:match_object(St#st.by_db, {DbShard, {'$1', Sig}}),
if
length(SigDDocs) > 1 ->
% remove records from by_db for this DDoc
Args = [DbShard, DDocId, Sig],
gen_server:cast(St#st.server_name, {rem_from_ets, Args});
true ->
% single DDoc with this Sig - close couch_index processes
case ets:lookup(St#st.by_sig, {DbShard, Sig}) of
[{_, IndexPid}] ->
(catch gen_server:cast(
IndexPid, {ddoc_updated, DDocResult}
));
[] ->
[]
end
end
end,
ets:match_object(St#st.by_db, {DbShard, {DDocId, '$1'}})
)
end,
DbShards
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To avoid deep nesting a utility function might work better shard_ddoc_updated(DbShard, St)?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is existing code, I'd rather not alter beyond what's essential.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1, nesting is a bit deep and a helper would help.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your diff will be smaller if you don't indent silly goose.

Copy link
Member

@davisp davisp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Few minor changes, mostly biggest around checking the wrong pids in the openers table.

src/couch_index/src/couch_index_server.erl Outdated Show resolved Hide resolved
src/couch_index/src/couch_index_server.erl Outdated Show resolved Hide resolved
src/couch_index/src/couch_index_server.erl Outdated Show resolved Hide resolved
src/couch_index/src/couch_index_server.erl Show resolved Hide resolved
Comment on lines +355 to +380
fun(DbShard) ->
lists:foreach(
fun({_DbShard, {_DDocId, Sig}}) ->
% check if there are other ddocs with the same Sig for the same db
SigDDocs = ets:match_object(St#st.by_db, {DbShard, {'$1', Sig}}),
if
length(SigDDocs) > 1 ->
% remove records from by_db for this DDoc
Args = [DbShard, DDocId, Sig],
gen_server:cast(St#st.server_name, {rem_from_ets, Args});
true ->
% single DDoc with this Sig - close couch_index processes
case ets:lookup(St#st.by_sig, {DbShard, Sig}) of
[{_, IndexPid}] ->
(catch gen_server:cast(
IndexPid, {ddoc_updated, DDocResult}
));
[] ->
[]
end
end
end,
ets:match_object(St#st.by_db, {DbShard, {DDocId, '$1'}})
)
end,
DbShards
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1, nesting is a bit deep and a helper would help.

Copy link
Member

@davisp davisp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1

@rnewson rnewson force-pushed the couch_index_fixes branch 2 times, most recently from 813cae1 to 4526b17 Compare March 22, 2023 20:58
Copy link
Contributor

@nickva nickva left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few eunit tests are failing

module 'couch_index_ddoc_updated_tests'
  Check ddoc update actions
    couch_index_ddoc_updated_tests:54: check_all_indexers_exit_on_ddoc_change...*failed*
in function couch_index_server:handle_db_event/3 (src/couch_index_server.erl, line 388)
in call from lists:foreach/2 (lists.erl, line 1342)
in call from couch_index_ddoc_updated_tests:'-check_all_indexers_exit_on_ddoc_change/1-fun-7-'/1 (test/eunit/couch_index_ddoc_updated_tests.erl, line 106)
in call from eunit_test:run_testfun/1 (eunit_test.erl, line 71)
in call from eunit_proc:run_test/1 (eunit_proc.erl, line 531)
in call from eunit_proc:with_timeout/3 (eunit_proc.erl, line 356)
in call from eunit_proc:handle_test/2 (eunit_proc.erl, line 514)
in call from eunit_proc:tests_inorder/3 (eunit_proc.erl, line 456)
**error:{badrecord,st}
  output:<<"">>

Would probably be good to have eunit tests exercising some of the new code. One approach there could be to mock couch_index_server and intercept the async opener logic to force it crash.

@rnewson rnewson merged commit 0073e76 into main Mar 22, 2023
@rnewson rnewson deleted the couch_index_fixes branch March 22, 2023 22:00
@nickva
Copy link
Contributor

nickva commented Mar 22, 2023

@rnewson forgot to add unit tests #4491 (review)

nickva added a commit that referenced this pull request Dec 14, 2023
Previously we didin't always reply to waiting `get_index` calls as sometimes we
clobbered or deleted waiters in by_sig ets table.

Ref: #4491
nickva added a commit that referenced this pull request Dec 14, 2023
Previously we didin't always reply to waiting `get_index` calls as sometimes we
clobbered or deleted waiters in by_sig ets table.

Ref: #4491
nickva added a commit that referenced this pull request Dec 14, 2023
Previously we didin't always reply to waiting `get_index` calls as sometimes we
clobbered or deleted waiters in by_sig ets table.

Ref: #4491
nickva added a commit that referenced this pull request Dec 14, 2023
Previously we didin't always reply to waiting `get_index` calls as sometimes we
clobbered or deleted waiters in by_sig ets table.

Ref: #4491
nickva added a commit that referenced this pull request Dec 15, 2023
Previously we didin't always reply to waiting `get_index` calls as sometimes we
clobbered or deleted waiters in by_sig ets table.

Ref: #4491
nickva added a commit that referenced this pull request Dec 15, 2023
Previously we didin't always reply to waiting `get_index` calls as sometimes we
clobbered or deleted waiters in by_sig ets table.

Ref: #4491
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants