and notification routing
All 15 queues previously ran through one auto-balanced supervisor.
Horizon's `balance: auto` does not honor queue array order for
priority, so despite queue names implying priority ('high' vs 'low'),
a burst on any one queue could starve any other sharing that
supervisor - e.g. a burst of mmo (image/video optimization, 23
dispatch sites, CPU/IO heavy) could delay high-queue DM/follow
delivery just as easily as it could delay low-queue background work.
Split into 4 supervisors grouped by actual job characteristics
(checked via grep across every ->onQueue() call site, not guessed):
- supervisor-priority: high, inbox, pushnotify, follow, default,
shared - user-facing federation/DM/notification delivery.
- supervisor-fanout: feed, story, groups - bursty timeline/story
fanout writes triggered by posts, likes, and follows.
- supervisor-media: mmo - image/video optimize/resize/thumbnail.
Runs a fixed worker pool (balance: false) instead of auto-scaling,
so it can't claim workers away from the other pools under load.
- supervisor-background: low, delete, adelete, move, intbg - imports,
crawling, account deletion/migration; not time-sensitive.
Moved the shared supervisor shape into `defaults` (keyed per
supervisor name, per Horizon's own merge behavior) so `environments`
only needs to override what actually differs, instead of each
environment fully redefining supervisor-1 from scratch. Existing env
vars (HORIZON_MAX_PROCESSES, HORIZON_MIN_PROCESSES,
HORIZON_BALANCE_STRATEGY, HORIZON_SUPERVISOR_*) keep governing the
priority supervisor for continuity with existing deployments; the
three new supervisors get their own HORIZON_*_MAX_PROCESSES vars
with conservative defaults.
Also:
- Added balanceCooldown: 3 explicitly (previously relied on
SupervisorOptions' own constructor default of the same value -
behavior is unchanged, just no longer implicit).
- Wired LongWaitDetected notification routing
(Horizon::routeMailNotificationsTo/routeSlackNotificationsTo) to
new optional config('horizon.notification_routing') keys, sourced
from env vars. Previously these were hardcoded, commented-out
examples with nowhere to actually alert on the `waits` thresholds
already configured below.
Verified by actually starting `php artisan horizon` and inspecting
`horizon:supervisors`: all 4 supervisors registered with exactly the
intended queues, supervisor-media correctly running fixed (non-auto)
balancing. Cross-checked every ->onQueue() call site in app/ against
the new supervisor queue lists - exact match, no queue dropped or
duplicated. Full test suite (715/715) and Larastan clean.
Remove deprecated Foundation\Support\Providers\AuthServiceProvider and
EventServiceProvider base classes. Move policy and event listener
registrations into AppServiceProvider using Gate::policy() and
Event::listen(). Behavior is unchanged (verified via event:list and
auth test suite).
Move all Eloquent models from the app/ root directory to app/Models/
for consistency with modern Laravel conventions. The project already had
54 models in App\Models; this migrates the remaining 52 legacy models.
Changes:
- Move 52 model files from app/ to app/Models/
- Update namespace declarations in each model
- Update all ~1000 import references across the codebase
- Add Relation::morphMap() in AppServiceProvider for backward
compatibility with existing polymorphic database records
- Add missing HasSnowflakePrimary imports for models that relied
on same-namespace resolution
- Enable strict mode for MySQL connection to prevent silent data
truncation, zero-date insertion, and division-by-zero errors.
- Remove Schema::defaultStringLength(191) which was a MySQL 5.7
workaround no longer needed on MySQL 8.0+ / MariaDB 10.3+.
Adds a global rate limiter (240 req/min per user or IP) to all API
routes. Previously rate limiting was only applied ad-hoc on individual
routes, leaving some endpoints unprotected.
- Remove Passport::personalAccessClientId() (removed in Passport v13, auto-discovers now)
- Remove Passport::enableImplicitGrant() (legacy grant, no clients use it)
- Flatten config instance.oauth.pat to pat_enabled (remove dead pat.id key)
- Add OAUTH_PAT_ENABLED=false to .env.example and .env.docker.example
- Show swal alert when PATs disabled instead of hidden API error
- Improve store() error handling to surface 403 messages in the UI
- Remove OAUTH_PAT_ID row from admin diagnostics blade
Convert all 273 short facade alias imports (e.g. 'use Cache;') to their
fully-qualified class names (e.g. 'use Illuminate\Support\Facades\Cache;')
across 193 files.
This resolves 643 PHPStan 'class.notFound' errors caused by the static
analyzer being unable to resolve global aliases, and aligns with modern
Laravel conventions. It also unblocks removing the aliases array from
config/app.php in a future change.
All 107 tests pass.
Replace all 'Controller@method' string references with
[Controller::class, 'method'] array syntax across all route files.
Remove the $namespace property and ->namespace() calls from
RouteServiceProvider.
This is required for Laravel 13 compatibility where string-based
controller routing and automatic namespace prefixing will be removed.
742 route references converted across 5 route files.
PHP 5.5.9 adds the new static `class` property which provides the fully qualified class name. This is preferred over using strings for class names since the `class` property references are checked by PHP.
This check resulted in the /oauth/scopes route returning nothing, meaning in development you couldn't use access tokens with scopes; It probably also affected other logic