Draft: Add model-level validation for events sharding key

What does this MR do and why?

Adds a model-level validation to the Event model to enforce that exactly one of group_id, project_id, or personal_namespace_id is non-null per row.

This is step 3 of the proposed work in #598786 ("Tighten sharding key NOT NULL constraint for events table").

Changes

  • Move ensure_sharding_key callback from before_save to before_validation: This ensures the sharding key is populated before validation runs. The callback sets personal_namespace_id from the author's namespace when all three sharding keys are nil.
  • Add ExactlyOnePresentValidator: Validates that exactly one of group_id, project_id, or personal_namespace_id is present, preventing new rows from being created with multiple sharding keys set (e.g. both group_id and personal_namespace_id).

This prevents the code path that produced the ~14,788 violating WikiPage::Meta event rows from creating new violations.

References

Screenshots or screen recordings

N/A - backend-only change

How to set up and validate locally

  1. In rails console, try creating an event with multiple sharding keys:

    user = User.first
    group = Group.first
    event = Event.new(author: user, action: :joined, group: group)
    event.personal_namespace_id = user.namespace_id
    event.valid? # => false
    event.errors[:base] # => ["must have exactly one of group_id, project_id, or personal_namespace_id"]
  2. Verify that normal event creation still works:

    event = Event.new(author: user, action: :joined, project: Project.first)
    event.valid? # => true

MR acceptance checklist

Evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.

Merge request reports

Loading
Loading