Skip to content

Backfill PATs seven_days_notification_sent_at column

What does this MR do and why?

Backfill PATs seven_days_notification_sent_at column. Part 2 of a multi-MR database change.

Includes a batched background migration to backfill the column using the expired_at dates. Also creates a temporary index for the BBM.

Changes PersonalAccessTokens::ExpiringWorker to dual-write to both the legacy expire_notification_delivered boolean column and the replacement seven_days_notification_sent_at column.

MR acceptance checklist

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

Database Review

Migration test results comment quick-link

Two existing update_all queries are updated to write to two columns instead of one:

Update personal_access_tokens expire_notification_delivered and seven_days_notification_sent_at
UPDATE "personal_access_tokens" SET "expire_notification_delivered" = TRUE, "seven_days_notification_sent_at" = '2024-09-11 04:57:01.960750' WHERE "personal_access_tokens"."id" IN (SELECT "personal_access_tokens"."id" FROM "personal_access_tokens" LEFT OUTER JOIN "users" ON "users"."id" = "personal_access_tokens"."user_id" WHERE 1=1 AND ((revoked = false AND expire_notification_delivered = false AND expires_at >= CURRENT_DATE AND expires_at <= '2024-09-18') and impersonation = false) AND "users"."user_type" = 6 AND 1=1 LIMIT 100)

The batched background migration uses a scope and temporary index to backfill seven_days_notification_sent_at for personal_access_token rows where expire_notification_delivered is true :

Update personal_access_tokens seven_days_notification_sent_at
UPDATE "personal_access_tokens" SET seven_days_notification_sent_at = (expires_at - interval '7 days') WHERE "personal_access_tokens"."expire_notification_delivered" = TRUE AND "personal_access_tokens"."seven_days_notification_sent_at" IS NULL AND "personal_access_tokens"."expires_at" IS NOT NULL AND "personal_access_tokens"."id" BETWEEN 1 AND 31

How to set up and validate locally

  1. Run migrations; ensure background migration completes
  2. Check for seven_days_notification_sent_at values in PersonalAccessToken in the rails console:
    # should show a record with expiry notification sent
    PersonalAccessToken.where.not(seven_days_notification_sent_at: nil).first
    
    # should return 0
    PersonalAccessToken.where(expire_notification_delivered: true, seven_days_notification_sent_at: nil).count
  3. Create a new personal, group, or project access token that expires tomorrow
  4. Run the ExpiringWorker -
    PersonalAccessTokens::ExpiringWorker.new.perform
  5. Ensure the new token has both expire_notification_delivered and seven_days_notification_sent_at set

Related to #464040 (closed)

Edited by Andrew Evans

Merge request reports

Loading