중복된 투표가 있는 사용자 병합 오류

오류의 관련 부분

rake aborted!
ActiveRecord::RecordNotUnique: PG::UniqueViolation: ERROR:  duplicate key value violates unique constraint "index_poll_votes_on_poll_id_and_poll_option_id_and_user_id"
DETAIL:  Key (poll_id, poll_option_id, user_id)=(129, 559, 582) already exists.

poll_votes 테이블을 확인해 보니 대상 사용자와 소스 사용자가 동일한 옵션으로 투표한 것으로 나타났습니다.
충돌하는 투표 중 하나를 삭제한 후 병합이 정상적으로 수행되었습니다.

전체 오류

요약
** Invoke users:merge (first_time)
** Invoke environment (first_time)
** Execute environment
** Execute users:merge
rake aborted!
ActiveRecord::RecordNotUnique: PG::UniqueViolation: ERROR:  duplicate key value violates unique constraint "index_poll_votes_on_poll_id_and_poll_option_id_and_user_id"
DETAIL:  Key (poll_id, poll_option_id, user_id)=(129, 559, 582) already exists.
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rack-mini-profiler-2.0.2/lib/patches/db/pg.rb:69:in `exec_params'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rack-mini-profiler-2.0.2/lib/patches/db/pg.rb:69:in `exec_params'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-6.0.3.1/lib/active_record/connection_adapters/postgresql_adapter.rb:675:in `block (2 levels) in exec_no_cache'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activesupport-6.0.3.1/lib/active_support/dependencies/interlock.rb:48:in `block in permit_concurrent_loads'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activesupport-6.0.3.1/lib/active_support/concurrency/share_lock.rb:187:in `yield_shares'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activesupport-6.0.3.1/lib/active_support/dependencies/interlock.rb:47:in `permit_concurrent_loads'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-6.0.3.1/lib/active_record/connection_adapters/postgresql_adapter.rb:674:in `block in exec_no_cache'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-6.0.3.1/lib/active_record/connection_adapters/abstract_adapter.rb:722:in `block (2 levels) in log'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activesupport-6.0.3.1/lib/active_support/concurrency/load_interlock_aware_monitor.rb:26:in `block (2 levels) in synchronize'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activesupport-6.0.3.1/lib/active_support/concurrency/load_interlock_aware_monitor.rb:25:in `handle_interrupt'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activesupport-6.0.3.1/lib/active_support/concurrency/load_interlock_aware_monitor.rb:25:in `block in synchronize'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activesupport-6.0.3.1/lib/active_support/concurrency/load_interlock_aware_monitor.rb:21:in `handle_interrupt'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activesupport-6.0.3.1/lib/active_support/concurrency/load_interlock_aware_monitor.rb:21:in `synchronize'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-6.0.3.1/lib/active_record/connection_adapters/abstract_adapter.rb:721:in `block in log'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activesupport-6.0.3.1/lib/active_support/notifications/instrumenter.rb:24:in `instrument'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-6.0.3.1/lib/active_record/connection_adapters/abstract_adapter.rb:712:in `log'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-6.0.3.1/lib/active_record/connection_adapters/postgresql_adapter.rb:673:in `exec_no_cache'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-6.0.3.1/lib/active_record/connection_adapters/postgresql_adapter.rb:654:in `execute_and_clear'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-6.0.3.1/lib/active_record/connection_adapters/postgresql/database_statements.rb:111:in `exec_delete'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-6.0.3.1/lib/active_record/connection_adapters/abstract/database_statements.rb:174:in `update'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-6.0.3.1/lib/active_record/connection_adapters/abstract/query_cache.rb:22:in `update'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-6.0.3.1/lib/active_record/relation.rb:469:in `update_all'
/var/www/discourse/plugins/poll/plugin.rb:560:in `block (2 levels) in activate!'
/var/www/discourse/lib/plugin/instance.rb:348:in `block in on'
/var/www/discourse/lib/discourse_event.rb:14:in `block in trigger'
/usr/local/lib/ruby/2.6.0/set.rb:338:in `each_key'
/usr/local/lib/ruby/2.6.0/set.rb:338:in `each'
/var/www/discourse/lib/discourse_event.rb:13:in `trigger'
/var/www/discourse/app/services/user_merger.rb:21:in `merge!'
/var/www/discourse/lib/tasks/users.rake:50:in `block in <top (required)>'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rake-13.0.1/lib/rake/task.rb:279:in `block in execute'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rake-13.0.1/lib/rake/task.rb:279:in `each'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rake-13.0.1/lib/rake/task.rb:279:in `execute'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rake-13.0.1/lib/rake/task.rb:219:in `block in invoke_with_call_chain'
/usr/local/lib/ruby/2.6.0/monitor.rb:235:in `mon_synchronize'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rake-13.0.1/lib/rake/task.rb:199:in `invoke_with_call_chain'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rake-13.0.1/lib/rake/task.rb:188:in `invoke'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rake-13.0.1/lib/rake/application.rb:160:in `invoke_task'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rake-13.0.1/lib/rake/application.rb:116:in `block (2 levels) in top_level'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rake-13.0.1/lib/rake/application.rb:116:in `each'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rake-13.0.1/lib/rake/application.rb:116:in `block in top_level'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rake-13.0.1/lib/rake/application.rb:125:in `run_with_threads'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rake-13.0.1/lib/rake/application.rb:110:in `top_level'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rake-13.0.1/lib/rake/application.rb:83:in `block in run'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rake-13.0.1/lib/rake/application.rb:186:in `standard_exception_handling'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rake-13.0.1/lib/rake/application.rb:80:in `run'
bin/rake:13:in `<top (required)>'
/usr/local/lib/ruby/gems/2.6.0/gems/bundler-2.1.4/lib/bundler/cli/exec.rb:63:in `load'
/usr/local/lib/ruby/gems/2.6.0/gems/bundler-2.1.4/lib/bundler/cli/exec.rb:63:in `kernel_load'
/usr/local/lib/ruby/gems/2.6.0/gems/bundler-2.1.4/lib/bundler/cli/exec.rb:28:in `run'
/usr/local/lib/ruby/gems/2.6.0/gems/bundler-2.1.4/lib/bundler/cli.rb:476:in `exec'
/usr/local/lib/ruby/gems/2.6.0/gems/bundler-2.1.4/lib/bundler/vendor/thor/lib/thor/command.rb:27:in `run'
/usr/local/lib/ruby/gems/2.6.0/gems/bundler-2.1.4/lib/bundler/vendor/thor/lib/thor/invocation.rb:127:in `invoke_command'
/usr/local/lib/ruby/gems/2.6.0/gems/bundler-2.1.4/lib/bundler/vendor/thor/lib/thor.rb:399:in `dispatch'
/usr/local/lib/ruby/gems/2.6.0/gems/bundler-2.1.4/lib/bundler/cli.rb:30:in `dispatch'
/usr/local/lib/ruby/gems/2.6.0/gems/bundler-2.1.4/lib/bundler/vendor/thor/lib/thor/base.rb:476:in `start'
/usr/local/lib/ruby/gems/2.6.0/gems/bundler-2.1.4/lib/bundler/cli.rb:24:in `start'
/usr/local/lib/ruby/gems/2.6.0/gems/bundler-2.1.4/exe/bundle:46:in `block in <top (required)>'
/usr/local/lib/ruby/gems/2.6.0/gems/bundler-2.1.4/lib/bundler/friendly_errors.rb:123:in `with_friendly_errors'
/usr/local/lib/ruby/gems/2.6.0/gems/bundler-2.1.4/exe/bundle:34:in `<top (required)>'
/usr/local/bin/bundle:23:in `load'
/usr/local/bin/bundle:23:in `<main>'

Caused by:
PG::UniqueViolation: ERROR:  duplicate key value violates unique constraint "index_poll_votes_on_poll_id_and_poll_option_id_and_user_id"
DETAIL:  Key (poll_id, poll_option_id, user_id)=(129, 559, 582) already exists.
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rack-mini-profiler-2.0.2/lib/patches/db/pg.rb:69:in `exec_params'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rack-mini-profiler-2.0.2/lib/patches/db/pg.rb:69:in `exec_params'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-6.0.3.1/lib/active_record/connection_adapters/postgresql_adapter.rb:675:in `block (2 levels) in exec_no_cache'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activesupport-6.0.3.1/lib/active_support/dependencies/interlock.rb:48:in `block in permit_concurrent_loads'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activesupport-6.0.3.1/lib/active_support/concurrency/share_lock.rb:187:in `yield_shares'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activesupport-6.0.3.1/lib/active_support/dependencies/interlock.rb:47:in `permit_concurrent_loads'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-6.0.3.1/lib/active_record/connection_adapters/postgresql_adapter.rb:674:in `block in exec_no_cache'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-6.0.3.1/lib/active_record/connection_adapters/abstract_adapter.rb:722:in `block (2 levels) in log'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activesupport-6.0.3.1/lib/active_support/concurrency/load_interlock_aware_monitor.rb:26:in `block (2 levels) in synchronize'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activesupport-6.0.3.1/lib/active_support/concurrency/load_interlock_aware_monitor.rb:25:in `handle_interrupt'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activesupport-6.0.3.1/lib/active_support/concurrency/load_interlock_aware_monitor.rb:25:in `block in synchronize'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activesupport-6.0.3.1/lib/active_support/concurrency/load_interlock_aware_monitor.rb:21:in `handle_interrupt'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activesupport-6.0.3.1/lib/active_support/concurrency/load_interlock_aware_monitor.rb:21:in `synchronize'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-6.0.3.1/lib/active_record/connection_adapters/abstract_adapter.rb:721:in `block in log'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activesupport-6.0.3.1/lib/active_support/notifications/instrumenter.rb:24:in `instrument'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-6.0.3.1/lib/active_record/connection_adapters/abstract_adapter.rb:712:in `log'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-6.0.3.1/lib/active_record/connection_adapters/postgresql_adapter.rb:673:in `exec_no_cache'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-6.0.3.1/lib/active_record/connection_adapters/postgresql_adapter.rb:654:in `execute_and_clear'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-6.0.3.1/lib/active_record/connection_adapters/postgresql/database_statements.rb:111:in `exec_delete'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-6.0.3.1/lib/active_record/connection_adapters/abstract/database_statements.rb:174:in `update'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-6.0.3.1/lib/active_record/connection_adapters/abstract/query_cache.rb:22:in `update'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-6.0.3.1/lib/active_record/relation.rb:469:in `update_all'
/var/www/discourse/plugins/poll/plugin.rb:560:in `block (2 levels) in activate!'
/var/www/discourse/lib/plugin/instance.rb:348:in `block in on'
/var/www/discourse/lib/discourse_event.rb:14:in `block in trigger'
/usr/local/lib/ruby/2.6.0/set.rb:338:in `each_key'
/usr/local/lib/ruby/2.6.0/set.rb:338:in `each'
/var/www/discourse/lib/discourse_event.rb:13:in `trigger'
/var/www/discourse/app/services/user_merger.rb:21:in `merge!'
/var/www/discourse/lib/tasks/users.rake:50:in `block in <top (required)>'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rake-13.0.1/lib/rake/task.rb:279:in `block in execute'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rake-13.0.1/lib/rake/task.rb:279:in `each'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rake-13.0.1/lib/rake/task.rb:279:in `execute'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rake-13.0.1/lib/rake/task.rb:219:in `block in invoke_with_call_chain'
/usr/local/lib/ruby/2.6.0/monitor.rb:235:in `mon_synchronize'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rake-13.0.1/lib/rake/task.rb:199:in `invoke_with_call_chain'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rake-13.0.1/lib/rake/task.rb:188:in `invoke'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rake-13.0.1/lib/rake/application.rb:160:in `invoke_task'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rake-13.0.1/lib/rake/application.rb:116:in `block (2 levels) in top_level'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rake-13.0.1/lib/rake/application.rb:116:in `each'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rake-13.0.1/lib/rake/application.rb:116:in `block in top_level'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rake-13.0.1/lib/rake/application.rb:125:in `run_with_threads'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rake-13.0.1/lib/rake/application.rb:110:in `top_level'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rake-13.0.1/lib/rake/application.rb:83:in `block in run'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rake-13.0.1/lib/rake/application.rb:186:in `standard_exception_handling'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rake-13.0.1/lib/rake/application.rb:80:in `run'
bin/rake:13:in `<top (required)>'
/usr/local/lib/ruby/gems/2.6.0/gems/bundler-2.1.4/lib/bundler/cli/exec.rb:63:in `load'
/usr/local/lib/ruby/gems/2.6.0/gems/bundler-2.1.4/lib/bundler/cli/exec.rb:63:in `kernel_load'
/usr/local/lib/ruby/gems/2.6.0/gems/bundler-2.1.4/lib/bundler/cli/exec.rb:28:in `run'
/usr/local/lib/ruby/gems/2.6.0/gems/bundler-2.1.4/lib/bundler/cli.rb:476:in `exec'
/usr/local/lib/ruby/gems/2.6.0/gems/bundler-2.1.4/lib/bundler/vendor/thor/lib/thor/command.rb:27:in `run'
/usr/local/lib/ruby/gems/2.6.0/gems/bundler-2.1.4/lib/bundler/vendor/thor/lib/thor/invocation.rb:127:in `invoke_command'
/usr/local/lib/ruby/gems/2.6.0/gems/bundler-2.1.4/lib/bundler/vendor/thor/lib/thor.rb:399:in `dispatch'
/usr/local/lib/ruby/gems/2.6.0/gems/bundler-2.1.4/lib/bundler/cli.rb:30:in `dispatch'
/usr/local/lib/ruby/gems/2.6.0/gems/bundler-2.1.4/lib/bundler/vendor/thor/lib/thor/base.rb:476:in `start'
/usr/local/lib/ruby/gems/2.6.0/gems/bundler-2.1.4/lib/bundler/cli.rb:24:in `start'
/usr/local/lib/ruby/gems/2.6.0/gems/bundler-2.1.4/exe/bundle:46:in `block in <top (required)>'
/usr/local/lib/ruby/gems/2.6.0/gems/bundler-2.1.4/lib/bundler/friendly_errors.rb:123:in `with_friendly_errors'
/usr/local/lib/ruby/gems/2.6.0/gems/bundler-2.1.4/exe/bundle:34:in `<top (required)>'
/usr/local/bin/bundle:23:in `load'
/usr/local/bin/bundle:23:in `<main>'
Tasks: TOP => users:merge
4개의 좋아요

저도 방금 이 문제를 겪었습니다. 최신 버전에서도 여전히 문제가 남아 있습니다.

1개의 좋아요

테스트 사이트에서 이를 재현할 수 있습니다. (107239a442)

  • 투표 생성
  • Test_User_One과 Test_User_Two가 동일한 투표 옵션에 투표
  • Test_User_Two를 Test_User_One에 병합
  • 처리가 ‘병합 진행’ 모달에서 멈춤

다만, 멈춘 모달에서 벗어나면 Test_User_Two가 사라진 것처럼 보입니다. 병합이 실제로 완료되었는지 확인하기 위해 몇 개의 게시물을 생성해 두었어야 했는데, 잠시 돌아오겠습니다. :slightly_smiling_face:


매우 흥미롭게도, Test_User_Two는 관리자의 ‘활성 사용자’ 목록에 표시되지 않지만, 여전히 로그인하고 게시물을 작성할 수 있습니다.


업데이트: 이제 조금씩 업데이트된 것 같고, Test_Two의 게시물이 Test_One에게 할당되었습니다. 하지만 저는 여전히 Test_Two로 로그인되어 있으며, Test_Two 요약 페이지 등이 표시되고 있습니다. 심지어 로그아웃했다가 Test_Two의 자격 증명으로 다시 로그인해 보기도 했습니다.

죄송합니다, 이러한 특이한 현상들이 매우 흥미로워서 그랬습니다. 아마도 유용하지 않을 수도 있겠네요. :slightly_smiling_face:

4개의 좋아요

간단한 업데이트입니다. 이 문제를 해결하기 위해 목록에 올려 두었으며, 몇 주 내에 해결할 수 있기를 바랍니다.

4개의 좋아요

이건 꽤 재밌는 버그입니다.

투표 결과가 제대로 병합되지 않는 문제 때문에, Lancelot(id 383) → Galahad(id 120)로 병합할 경우 Lancelot은 실제로 존재하게 되지만 기본 이메일이 없게 됩니다. /admin/users/383/lancelot은 익명화 검사로 인해 http 500 오류가 발생했습니다.

어쨌든 수정 작업이 진행 중입니다. 중복되는 경우 이 경우에는 Galahad(대상 사용자)의 투표를 유지하는 쪽으로 결정했습니다.

4개의 좋아요

이 주제는 44시간 후 자동으로 닫혔습니다. 더 이상 새로운 답변을 작성할 수 없습니다.