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

Fix: ActiveRecord::RecordInvalid (MAYBE-RAILS-DM) #1801

Closed
wants to merge 1 commit into from

Conversation

revise-dev[bot]
Copy link

@revise-dev revise-dev bot commented Feb 4, 2025

The error occurs because the system is attempting to create duplicate Transfer records where transactions are already associated with existing transfers. The root cause is in the transfer_match_candidates method in Account model, which wasn't properly excluding transactions that are already part of transfers.

The original code's intent was to match transactions between accounts that could represent transfers (same amount but opposite signs, within 4 days of each other, different accounts). However, the LEFT JOIN conditions weren't comprehensive enough to exclude all cases where transactions were already associated with transfers.

Key changes made:

  1. Modified the existing_transfers JOIN condition to check both transactions against both inflow and outflow fields. This ensures we catch cases where either transaction is already part of any transfer, regardless of its role.

  2. Enhanced the rejected_transfers JOIN to check for rejected transfers in both directions (A->B and B->A). This prevents re-matching previously rejected transfer pairs.

  3. Added a new test auto_match_transfers_respects_existing_transfers to verify that transactions already in transfers aren't re-matched.

The updated query is more thorough in excluding existing transfers while maintaining the original matching logic for legitimate transfer candidates.

Error Details

Summary:

ActiveRecord::RecordInvalid: Validation failed: Inflow transaction has already been taken, Outflow transaction has already been taken (ActiveRecord::RecordInvalid)

Stacktrace:

active_record/validations.rb:87
active_record/validations.rb:54
active_record/transactions.rb:366
active_record/transactions.rb:418
active_record/connection_adapters/abstract/database_statements.rb:359
active_record/transactions.rb:414
active_record/connection_adapters/abstract/connection_pool.rb:415
active_record/connection_handling.rb:296
active_record/transactions.rb:410
active_record/transactions.rb:366
active_record/suppressor.rb:56
active_record/persistence.rb:55
app/models/account.rb:210
active_record/relation/delegation.rb:98
active_record/relation/delegation.rb:98
app/models/account.rb:206
active_record/connection_adapters/abstract/transaction.rb:616
active_support/concurrency/null_lock.rb:9
active_record/connection_adapters/abstract/transaction.rb:613
active_record/connection_adapters/abstract/database_statements.rb:361
active_record/transactions.rb:234
active_record/connection_adapters/abstract/connection_pool.rb:415
active_record/connection_handling.rb:296
active_record/transactions.rb:233
app/models/account.rb:205
app/models/account/syncer.rb:8
app/models/account.rb:95
app/models/sync.rb:12
app/jobs/sync_job.rb:5
active_job/execution.rb:68
active_support/callbacks.rb:121
i18n.rb:353
active_job/translation.rb:9
active_support/callbacks.rb:130
active_support/callbacks.rb:130
active_support/core_ext/time/zones.rb:65
active_job/timezones.rb:9
active_support/callbacks.rb:130
active_support/callbacks.rb:130
active_support/callbacks.rb:141
active_job/execution.rb:67
active_job/instrumentation.rb:32
active_job/execution.rb:51
active_job/instrumentation.rb:26
active_record/railties/job_runtime.rb:13
active_job/instrumentation.rb:40
active_support/notifications.rb:210
active_support/notifications/instrumenter.rb:58
sentry/rails/tracing.rb:56
active_support/notifications.rb:210
active_job/instrumentation.rb:39
active_record/railties/job_runtime.rb:11
active_job/instrumentation.rb:26
active_job/logging.rb:32
active_support/tagged_logging.rb:138
active_support/tagged_logging.rb:38
active_support/tagged_logging.rb:138
active_job/logging.rb:39
active_job/logging.rb:32
sentry/rails/active_job.rb:11
sentry/rails/active_job.rb:43
sentry/hub.rb:59
sentry-ruby.rb:399
sentry/rails/active_job.rb:26
sentry/rails/active_job.rb:10
active_job/execution.rb:29
active_support/callbacks.rb:121
active_job/railtie.rb:79
active_support/reloader.rb:77
active_support/execution_wrapper.rb:87
active_support/reloader.rb:74
active_job/railtie.rb:78
active_support/callbacks.rb:130
active_support/callbacks.rb:130
active_support/callbacks.rb:141
active_job/execution.rb:27
/home/deploy/maybe-production/shared/bundle/ruby/3.4.0/gems/good_job-4.8.2/app/models/good_job/job.rb:629
active_support/notifications.rb:210
active_support/notifications/instrumenter.rb:58
sentry/rails/tracing.rb:56
active_support/notifications.rb:210
/home/deploy/maybe-production/shared/bundle/ruby/3.4.0/gems/good_job-4.8.2/app/models/good_job/job.rb:628
good_job/current_thread.rb:113
/home/deploy/maybe-production/shared/bundle/ruby/3.4.0/gems/good_job-4.8.2/app/models/good_job/job.rb:586
active_support/callbacks.rb:121
/home/deploy/maybe-production/shared/bundle/ruby/3.4.0/gems/good_job-4.8.2/app/models/good_job/batch.rb:80
/home/deploy/maybe-production/shared/bundle/ruby/3.4.0/gems/good_job-4.8.2/app/models/good_job/job.rb:771
active_support/callbacks.rb:130
active_support/callbacks.rb:141
/home/deploy/maybe-production/shared/bundle/ruby/3.4.0/gems/good_job-4.8.2/app/models/good_job/job.rb:580
/home/deploy/maybe-production/shared/bundle/ruby/3.4.0/gems/good_job-4.8.2/app/models/good_job/job.rb:322
/home/deploy/maybe-production/shared/bundle/ruby/3.4.0/gems/good_job-4.8.2/app/models/concerns/good_job/advisory_lockable.rb:180
active_record/relation.rb:1355
active_record/relation.rb:541
active_record/scoping/default.rb:51
/home/deploy/maybe-production/shared/bundle/ruby/3.4.0/gems/good_job-4.8.2/app/models/concerns/good_job/advisory_lockable.rb:180
active_record/relation/delegation.rb:78
active_record/relation.rb:1355
active_record/relation.rb:541
active_record/relation/delegation.rb:78
/home/deploy/maybe-production/shared/bundle/ruby/3.4.0/gems/good_job-4.8.2/app/models/good_job/job.rb:316
active_record/relation/delegation.rb:78
active_record/relation.rb:1355
active_record/relation.rb:541
active_record/relation/delegation.rb:78
good_job/job_performer.rb:35
good_job/capsule_tracker.rb:94
good_job/job_performer.rb:34
good_job/scheduler.rb:289
active_support/reloader.rb:77
active_support/execution_wrapper.rb:91
active_support/reloader.rb:74
good_job/scheduler.rb:288
concurrent/executor/safe_task_executor.rb:24
concurrent/synchronization/mutex_lockable_object.rb:48
concurrent/synchronization/mutex_lockable_object.rb:48
concurrent/synchronization/mutex_lockable_object.rb:48
concurrent/executor/safe_task_executor.rb:22
concurrent/ivar.rb:170
concurrent/scheduled_task.rb:298
concurrent/executor/timer_set.rb:98
concurrent/executor/ruby_thread_pool_executor.rb:359
concurrent/executor/ruby_thread_pool_executor.rb:350
:168
concurrent/executor/ruby_thread_pool_executor.rb:341
concurrent/executor/ruby_thread_pool_executor.rb:340
concurrent/executor/ruby_thread_pool_executor.rb:340

Tip

You can make revisions or ask questions of Revise.dev by using /revise in any comment or review!

  • /revise Add a comment above the method to explain why we're making this change.
  • /revise Why did you choose to make this change specifically?

Important

If something doesn’t look right, click to retry this interaction.

Quick links: View in SentryView in Revise

@zachgoll zachgoll closed this Feb 4, 2025
@Shpigford Shpigford deleted the revise/fix-maybe-rails-dm-1738699269 branch February 5, 2025 17:53
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.

1 participant