Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 49 additions & 17 deletions app/jobs/gpo_expiration_job.rb
Original file line number Diff line number Diff line change
@@ -1,32 +1,39 @@
class GpoExpirationJob < ApplicationJob
queue_as :low

def initialize(analytics: nil)
def initialize(analytics: nil, on_profile_expired: nil)
@analytics = analytics
@on_profile_expired = on_profile_expired
end

def expire_profile(profile:)
gpo_verification_pending_at = profile.gpo_verification_pending_at

profile.deactivate_due_to_gpo_expiration

analytics.idv_gpo_expired(
user_id: profile.user.uuid,
user_has_active_profile: profile.user.active_profile.present?,
letters_sent: profile.gpo_confirmation_codes.count,
gpo_verification_pending_at: gpo_verification_pending_at,
)
end

def perform(now: Time.zone.now, limit: nil, min_profile_age: nil)
def perform(
dry_run: false,
limit: nil,
min_profile_age: nil,
now: Time.zone.now,
statement_timeout: 10.minutes
)
profiles = gpo_profiles_that_should_be_expired(as_of: now, min_profile_age: min_profile_age)

if limit.present?
profiles = profiles.limit(limit)
end

profiles.find_each do |profile|
expire_profile(profile: profile)
with_statement_timeout(statement_timeout) do
profiles.find_each do |profile|
gpo_verification_pending_at = profile.gpo_verification_pending_at

if gpo_verification_pending_at.blank?
raise "Profile #{profile.id} does not have gpo_verification_pending_at"
end

expire_profile(profile: profile) unless dry_run

on_profile_expired&.call(
profile: profile,
gpo_verification_pending_at: gpo_verification_pending_at,
)
end
end
end

Expand All @@ -40,6 +47,31 @@ def gpo_profiles_that_should_be_expired(as_of:, min_profile_age: nil)

private

attr_reader :on_profile_expired

def expire_profile(profile:)
gpo_verification_pending_at = profile.gpo_verification_pending_at

profile.deactivate_due_to_gpo_expiration

analytics.idv_gpo_expired(
user_id: profile.user.uuid,
user_has_active_profile: profile.user.active_profile.present?,
letters_sent: profile.gpo_confirmation_codes.count,
gpo_verification_pending_at: gpo_verification_pending_at,
)
end

def with_statement_timeout(timeout)
ActiveRecord::Base.transaction do
quoted_timeout = ActiveRecord::Base.connection.quote("#{timeout.seconds}s")
ActiveRecord::Base.connection.execute(
"SET LOCAL statement_timeout = #{quoted_timeout}",
)
yield
end
end

def analytics
@analytics ||= Analytics.new(user: AnonymousUser.new, request: nil, session: {}, sp: nil)
end
Expand Down
36 changes: 18 additions & 18 deletions lib/tasks/backfill_gpo_expiration.rake
Original file line number Diff line number Diff line change
Expand Up @@ -13,34 +13,34 @@ namespace :profiles do
task backfill_gpo_expiration: :environment do |_task, _args|
min_profile_age = (ENV['MIN_PROFILE_AGE_IN_DAYS'].to_i || 100).days
update_profiles = ENV['UPDATE_PROFILES'] == 'true'

job = GpoExpirationJob.new

profiles = job.gpo_profiles_that_should_be_expired(
as_of: Time.zone.now,
min_profile_age: min_profile_age,
)
statement_timeout = ENV['STATEMENT_TIMEOUT_IN_SECONDS'].to_i.seconds || 10.minutes

count = 0
earliest = nil
latest = nil

profiles.find_each do |profile|
on_profile_expired = ->(profile:, gpo_verification_pending_at:) do
count += 1

gpo_verification_pending_at = profile.gpo_verification_pending_at

if gpo_verification_pending_at.blank?
raise "Profile #{profile.id} does not have gpo_verification_pending_at"
end
earliest = [earliest, gpo_verification_pending_at].compact.min
latest = [latest, gpo_verification_pending_at].compact.max

puts "#{profile.id},#{gpo_verification_pending_at.iso8601}"

if update_profiles
warn "Expired #{count} profiles" if count % 100 == 0
job.expire_profile(profile: profile)
elsif count % 100 == 0
warn "Found #{count} profiles"
if count % 100 == 0
verb = update_profiles ? 'Expired' : 'Found'
warn "#{verb} #{count} profiles (earliest: #{earliest}, latest: #{latest})"
end
end

job = GpoExpirationJob.new(on_profile_expired: on_profile_expired)

job.perform(
now: Time.zone.now,
min_profile_age: min_profile_age,
dry_run: !update_profiles,
statement_timeout: statement_timeout,
)
end

##
Expand Down
24 changes: 24 additions & 0 deletions spec/jobs/gpo_expiration_job_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,30 @@
)
end

context 'when a callback is provided' do
it 'calls it for expired profiles' do
profile = users[:user_with_one_expired_gpo_profile].reload.gpo_verification_pending_profile
gpo_verification_pending_at = profile.gpo_verification_pending_at

on_profile_expired = spy
expect(on_profile_expired).to receive(:call).with(
profile: profile,
gpo_verification_pending_at: gpo_verification_pending_at,
)

job = described_class.new(analytics: analytics, on_profile_expired: on_profile_expired)
job.perform
end
end

context('when dry_run is specified') do
it 'does not write changes' do
job.perform(dry_run: true)
profile = users[:user_with_one_expired_gpo_profile].reload.gpo_verification_pending_profile
expect(profile.gpo_verification_expired_at).to eql(nil)
end
end

context 'when the user has an active profile' do
let!(:active_profile) do
create(:profile, :active, user: users[:user_with_one_expired_gpo_profile])
Expand Down