Skip to content

fix(invitations): remove overly restrictive unique constraint on invitation log entries#2560

Merged
mroderick merged 2 commits intocodebar:masterfrom
mroderick:fix/invitation-log-entry-unique-constraint
Apr 10, 2026
Merged

fix(invitations): remove overly restrictive unique constraint on invitation log entries#2560
mroderick merged 2 commits intocodebar:masterfrom
mroderick:fix/invitation-log-entry-unique-constraint

Conversation

@mroderick
Copy link
Copy Markdown
Collaborator

@mroderick mroderick commented Apr 10, 2026

Problem

Invitation batch #28 for Berlin chapter students is stuck in running status with only 5 of 431 students processed. The batch crashed with:

ActiveRecord::RecordInvalid: Validation failed: Entries is invalid
InvitationLogger#fail_batch(/app/app/services/invitation_logger.rb:71)

Root Cause

The database has a global unique constraint on invitation_log_entries(invitation_type, invitation_id) that prevents the same invitation from being logged in multiple batches. This constraint is more restrictive than the model validation.

When a batch tries to create a log entry for an invitation that already has an entry from a previous batch, the INSERT fails. The unsaved entry remains in @log.entries. When fail_batch tries to save the log, Rails validates all entries including the invalid one.

Why the Constraint Was Wrong

  1. Multiple audiences: Different batches (students, coaches, everyone) may process overlapping member lists
  2. Retry scenarios: Failed batches can be retried, requiring re-logging of entries
  3. Within-batch uniqueness: Already handled by find_or_create_by(member: member, invitation: invitation) + processed_at check

Changes

  • Remove global unique index on invitation_log_entries
  • Remove model validation that enforced the same constraint

Note: The non-unique index on invitation_log_entries(invitation_type, invitation_id) remains for queries by invitation.

Testing

All tests pass:

  • spec/services/invitation_logger_spec.rb (13 examples)
  • spec/models/invitation_log_entry_spec.rb (4 examples)

Deployment Notes

After deploying:

  1. Clear stuck batches: UPDATE invitation_logs SET status = 'failed' WHERE id IN (22, 28);
  2. Trigger new invitation batch for Berlin students

Fixes #2561

@mroderick
Copy link
Copy Markdown
Collaborator Author

Fixes #2561

@mroderick mroderick force-pushed the fix/invitation-log-entry-unique-constraint branch from 5187740 to 7b4b96f Compare April 10, 2026 19:28
db/schema.rb Outdated
t.datetime "processed_at"
t.string "status", default: "success", null: false
t.datetime "updated_at", null: false
t.index ["invitation_log_id", "invitation_type", "invitation_id"], name: "index_invitation_log_entries_on_batch_and_invitation"
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I think this should not be here anymore. We are investigating.

The batch_and_invitation index was manually added to schema.rb without
a corresponding migration. Running rails db:drop db:create db:migrate
confirmed this index is not created by any migration.
@mroderick mroderick requested a review from till April 10, 2026 20:13
@mroderick mroderick merged commit aea3b53 into codebar:master Apr 10, 2026
13 of 14 checks passed
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.

Invitation log entry global unique constraint causes batch failures

2 participants