Skip to content

Fix broken Heroku Scheduler rake tasks #6923

@compwron

Description

@compwron

Context

Running each project rake task in this repo (bundle exec rake <name>) surfaces a cluster of bugs in the tasks driven by Heroku Scheduler. Three tasks crash on every invocation; two more crash latently when production data shape triggers them.

This issue covers the "broken in production" bugs only. Maintainability cleanup (auto_annotate noise, factory_bot:lint debt, deployment/ pruning, in-task schedule-guard anti-pattern) and moving controller specs to request specs are tracked separately.

Bugs that crash on every run

1. send_case_contact_types_reminderNoMethodError: undefined method 'every' for main

lib/tasks/send_case_contact_types_reminder.rake:4 and lib/tasks/send_no_contact_made_reminder.rake:4 both wrap their work in:

every 1.weeks do
  CaseContactTypesReminder.new.send!
end

every is from the whenever gem (intended for config/schedule.rb), not a Rake primitive. The block raises immediately when the task runs — meaning the case-contact-types SMS reminder has not actually executed since that block was added.

2. send_no_contact_made_reminder — task name doesn't exist

lib/tasks/send_no_contact_made_reminder.rake declares task send_case_contact_types_reminder: :environment do … — the same task name used by the other file. rake -T confirms only one task is registered, with both descriptions concatenated:

rake send_case_contact_types_reminder    # Send an SMS … past 60 or more days / Send an SMS … two weeks have passed …

So Heroku Scheduler invocations of send_no_contact_made_reminder fail with "Don't know how to build task", and the no-contact-made SMS reminder has never run. The file also require_relatives the wrong service file and instantiates CaseContactTypesReminder instead of NoContactMadeReminder.

3. recurring:initNameError: uninitialized constant ExampleRecurringTask

lib/tasks/recurring_jobs.rake:3 calls ExampleRecurringTask.schedule!, but ExampleRecurringTask is defined in lib/tasks/example_recurring_task.rb which Rails does not autoload. The class is also dead example code:

def perform
  Bugsnag.notify("This is just ExampleRecurringTask saying hi in #{Rails.env}")
end

— likely safe to delete entirely.

Latent bugs that crash when data triggers them

4. youth_birthday_reminderNoMethodError: undefined method 'volunteer_id' for nil

lib/tasks/youth_birthday_reminder.rake:6:

.deliver(Volunteer.find_by(id: casa_case.case_assignments.first.volunteer_id))

When a CasaCase.birthday_next_month case has no case_assignments, .first is nil. Confirmed via isolated repro against dev DB:

$ rails runner 'cc = CasaCase.birthday_next_month.first; cc.case_assignments.destroy_all; cc.case_assignments.first.volunteer_id'
RAISED: NoMethodError: undefined method 'volunteer_id' for nil

Seed data happens to have ≥1 assignment per case, so the bug never fires in test/dev — but it will fire in production whenever a case is briefly without an active assignment.

.first also ignores active vs. inactive — should be case_assignments.active.

5. emancipation_checklist_reminder_notifier (in development/notifications.rake) — same bug as #4

lib/tasks/development/notifications.rake:6 has the identical casa_case.case_assignments.first.volunteer_id shape and will crash the same way. The whole development/notifications.rake file is also missing an if Rails.env.development? guard — so the dev tasks followup_notifier (Followup.all.first) and reimbursement_complete_notifier (CaseContact.all.first) could be triggered against prod data.

Proposed PR scope

Single PR titled "Fix broken Heroku Scheduler rake tasks":

  • Drop the every 1.weeks do … end and every 1.days do … end blocks in both reminder rake files (test issue #1)
  • Rename the task in send_no_contact_made_reminder.rake to send_no_contact_made_reminder and wire it to NoContactMadeReminder (to do: make the app #2)
  • Move lib/tasks/case_contact_types_reminder.rb, no_contact_made_reminder.rb, supervisor_weekly_digest.rb to app/services/; drop the require_relative lines from their rake files and specs so Rails autoload picks them up (cleanup tied to test issue #1 / to do: make the app #2)
  • Delete lib/tasks/recurring_jobs.rake and lib/tasks/example_recurring_task.rb (or move the class to app/jobs/ and gut the Bugsnag noise) (Volunteer #3)
  • Add nil-safety + switch to case_assignments.active.find_each in youth_birthday_reminder.rake (Admin #4)
  • Wrap lib/tasks/development/notifications.rake in if Rails.env.development? and apply the same nil-safety to the emancipation notifier (Admin view/edit individual volunteer #5)

How verified

Ran every project-defined rake task against current dev DB (35 cases, 7 volunteers, 2 birthday-next-month cases, 0 followups; today is Saturday May 2 so monday? / day == 1 guards short-circuit the digest tasks):

Task Result
send_case_contact_types_reminder exit 1 — NoMethodError: undefined method 'every'
recurring:init exit 1 — NameError: uninitialized constant ExampleRecurringTask
youth_birthday_reminder (with case_assignments empty) confirmed NoMethodError via isolated repro
send_no_contact_made_reminder task name not registered (collides with send_case_contact_types_reminder)
clear_passed_dates, court_report_due_reminder, volunteer_birthday_reminder, send_learning_hour_reports, factory_bot:lint, test_checker exit 0, no crash

post_gc_stat_to_discord was skipped during verification because it HTTP-fetches the production URL — that's a separate concern (P3).

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type: BugDefect or regressionrubyTouches Ruby code

    Type

    No type

    Projects

    Status

    Todo

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions