Scheduler
File:app/Console/Kernel.php
The Laravel scheduler runs via cron inside the Docker container (configured in laravel-cron file). All times are UTC.
Scheduled jobs
Every 15 minutes
CheckLessonStatus
CheckLessonStatus
File:
app/Jobs/CheckLessonStatus.phpFinds rescheduled lessons where the suggested time has passed and auto-cancels them. Uses PaymentService for refund processing and LessonService for state transitions.SendLessonReminderPushNotification
SendLessonReminderPushNotification
File:
app/Jobs/SendLessonReminderPushNotification.phpSends push notifications to users with lessons starting in approximately:- 24 hours
- 2 hours
LessonService::notifyLessonReminder().SendPendingPayouts
SendPendingPayouts
File:
app/Jobs/SendPendingPayouts.phpProcesses tutor payouts for completed bookings:- Finds bookings in
PAYEDstate with notransfer_idon the receipt, older than 2 days - Creates Stripe Connect transfers to tutor accounts via
StripeService::createPayout() - Sends
SendPendingPayoutStatusemail to internal team (success or failure) - Handles exceptions gracefully — one failed payout doesn’t block others
Daily at 01:00 UTC
UpdateHoursTaught
UpdateHoursTaught
File:
app/Jobs/UpdateHoursTaught.phpUpdates the hours-taught statistics for all tutors. Iterates through tutors with active Teach records and calls Teach::caculateHoursTaught() on each.Daily at 02:00 UTC
CleanUpStaleFiles
CleanUpStaleFiles
File:
app/Jobs/CleanUpStaleFiles.phpDeletes orphaned files older than 100 days:- Queries the
filestable for records not referenced in thefileablespolymorphic table - Deletes files from storage (S3)
- Deletes database records
Daily at 08:30 UTC
ValidateZoomTokens
ValidateZoomTokens
File:
app/Jobs/ValidateZoomTokens.phpProduction only. Validates Zoom OAuth tokens for all connected tutors:- Fetches all Zoom
OAuthServiceTokenrecords - Calls
ZoomServiceto validate each token - If invalid: sends
ReconnectZoomemail to the tutor - Tracks reconnection attempts on the token record
- If max attempts reached: deletes the token
- Includes 1-second sleep between validations (rate limiting)
Daily at 10:00 UTC
SendReviewTutorNotification
SendReviewTutorNotification
File:
app/Jobs/SendReviewTutorNotification.phpSends review requests to students/parents for lessons completed yesterday:- Finds active lessons that ended yesterday
- Determines the reviewer — student directly, or parent if the learner is a child
- Checks related lessons count before sending
- Avoids duplicates: one email per tutor-reviewer pair per day
- Sends
ReviewTutoremail with review submission link
SendSummaryNoteNotification
SendSummaryNoteNotification
File:
app/Jobs/SendSummaryNoteNotification.phpReminds tutors to add lesson summary notes:- Finds completed lessons from yesterday that don’t have notes yet
- Calls
LessonService::notifyLessonSummaryNoteReminder()for each
SendTutorProfileCompletionNotification
SendTutorProfileCompletionNotification
File:
app/Jobs/SendTutorProfileCompletionNotification.phpNudges tutors with incomplete profiles:- Targets tutors created exactly 3 days ago
- Checks if profile is still incomplete
- Sends push notification with app launch link
- Uses
RemotePushNotifiabletrait for push delivery
Non-scheduled jobs
These job classes exist but aren’t in the scheduler (run manually or triggered by events):| Job | Purpose |
|---|---|
SendClaimUsernameEmail | One-time campaign: emails verified tutors without usernames (date range 2020-04-09 to 2022-02-01) |
SendClaimUsernameEmailTest | Test version of above (doesn’t actually send) |
SendClaimUsernameReminderEmail | Follow-up reminder for username claiming |
UpdateStripeAccountCapability | Updates transfers capability on all Stripe Connect accounts |
CheckVerificationStatusOfPendingApplicants exists but is entirely commented out/disabled.Queue configuration
All jobs implementShouldQueue. Queue driver is configured via QUEUE_DRIVER env var.
| Driver | Config |
|---|---|
sync | Default — runs jobs synchronously (no queue) |
redis | Uses default Redis connection, 90s retry_after |
database | Uses jobs table, 90s retry_after |
config/queue.php
Failed jobs are stored in the failed_jobs table.