diff --git a/.env.example b/.env.example index 1cbfb4b2..93f186c2 100644 --- a/.env.example +++ b/.env.example @@ -77,6 +77,3 @@ STRIPE_WEBHOOK_SECRET= SUBSCRIPTIONS_ENABLED=false STRIPE_PRO_MONTHLY_PRICE_ID= STRIPE_PRO_YEARLY_PRICE_ID= - -# Horizon Allowed Emails (comma-separated list of emails allowed to access Horizon in production) -HORIZON_ALLOWED_EMAILS= diff --git a/app/Providers/HorizonServiceProvider.php b/app/Providers/HorizonServiceProvider.php deleted file mode 100644 index 1e777fdc..00000000 --- a/app/Providers/HorizonServiceProvider.php +++ /dev/null @@ -1,41 +0,0 @@ -email, $allowedEmails); - }); - } -} diff --git a/bootstrap/providers.php b/bootstrap/providers.php index 63da17d7..0ad9c573 100644 --- a/bootstrap/providers.php +++ b/bootstrap/providers.php @@ -3,5 +3,4 @@ return [ App\Providers\AppServiceProvider::class, App\Providers\FortifyServiceProvider::class, - App\Providers\HorizonServiceProvider::class, ]; diff --git a/composer.json b/composer.json index 75ab9a00..d9871fc5 100644 --- a/composer.json +++ b/composer.json @@ -14,7 +14,6 @@ "laravel/cashier": "^16.1", "laravel/fortify": "^1.30", "laravel/framework": "^12.0", - "laravel/horizon": "^5.40", "laravel/tinker": "^2.10.1", "laravel/wayfinder": "^0.1.9", "resend/resend-php": "^1.1" diff --git a/composer.lock b/composer.lock index 17851d4b..5d456f88 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "c0e2b34e60716f64e9ffb87ec573f103", + "content-hash": "40779ce6890f5022e5e7c7c569bd328c", "packages": [ { "name": "bacon/bacon-qr-code", @@ -1598,85 +1598,6 @@ }, "time": "2025-11-04T15:39:33+00:00" }, - { - "name": "laravel/horizon", - "version": "v5.40.2", - "source": { - "type": "git", - "url": "https://github.com/laravel/horizon.git", - "reference": "005e5638478db9e25f7ae5cfb30c56846fbad793" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/laravel/horizon/zipball/005e5638478db9e25f7ae5cfb30c56846fbad793", - "reference": "005e5638478db9e25f7ae5cfb30c56846fbad793", - "shasum": "" - }, - "require": { - "ext-json": "*", - "ext-pcntl": "*", - "ext-posix": "*", - "illuminate/contracts": "^9.21|^10.0|^11.0|^12.0", - "illuminate/queue": "^9.21|^10.0|^11.0|^12.0", - "illuminate/support": "^9.21|^10.0|^11.0|^12.0", - "nesbot/carbon": "^2.17|^3.0", - "php": "^8.0", - "ramsey/uuid": "^4.0", - "symfony/console": "^6.0|^7.0", - "symfony/error-handler": "^6.0|^7.0", - "symfony/polyfill-php83": "^1.28", - "symfony/process": "^6.0|^7.0" - }, - "require-dev": { - "mockery/mockery": "^1.0", - "orchestra/testbench": "^7.55|^8.36|^9.15|^10.8", - "phpstan/phpstan": "^1.10|^2.0", - "predis/predis": "^1.1|^2.0|^3.0" - }, - "suggest": { - "ext-redis": "Required to use the Redis PHP driver.", - "predis/predis": "Required when not using the Redis PHP driver (^1.1|^2.0|^3.0)." - }, - "type": "library", - "extra": { - "laravel": { - "aliases": { - "Horizon": "Laravel\\Horizon\\Horizon" - }, - "providers": [ - "Laravel\\Horizon\\HorizonServiceProvider" - ] - }, - "branch-alias": { - "dev-master": "6.x-dev" - } - }, - "autoload": { - "psr-4": { - "Laravel\\Horizon\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Taylor Otwell", - "email": "taylor@laravel.com" - } - ], - "description": "Dashboard and code-driven configuration for Laravel queues.", - "keywords": [ - "laravel", - "queue" - ], - "support": { - "issues": "https://github.com/laravel/horizon/issues", - "source": "https://github.com/laravel/horizon/tree/v5.40.2" - }, - "time": "2025-11-28T20:12:12+00:00" - }, { "name": "laravel/prompts", "version": "v0.3.7", diff --git a/config/horizon.php b/config/horizon.php deleted file mode 100644 index 0f272708..00000000 --- a/config/horizon.php +++ /dev/null @@ -1,262 +0,0 @@ - env('HORIZON_NAME'), - - /* - |-------------------------------------------------------------------------- - | Horizon Domain - |-------------------------------------------------------------------------- - | - | This is the subdomain where Horizon will be accessible from. If this - | setting is null, Horizon will reside under the same domain as the - | application. Otherwise, this value will serve as the subdomain. - | - */ - - 'domain' => env('HORIZON_DOMAIN'), - - /* - |-------------------------------------------------------------------------- - | Horizon Path - |-------------------------------------------------------------------------- - | - | This is the URI path where Horizon will be accessible from. Feel free - | to change this path to anything you like. Note that the URI will not - | affect the paths of its internal API that aren't exposed to users. - | - */ - - 'path' => env('HORIZON_PATH', 'horizon'), - - /* - |-------------------------------------------------------------------------- - | Horizon Redis Connection - |-------------------------------------------------------------------------- - | - | This is the name of the Redis connection where Horizon will store the - | meta information required for it to function. It includes the list - | of supervisors, failed jobs, job metrics, and other information. - | - */ - - 'use' => 'default', - - /* - |-------------------------------------------------------------------------- - | Horizon Redis Prefix - |-------------------------------------------------------------------------- - | - | This prefix will be used when storing all Horizon data in Redis. You - | may modify the prefix when you are running multiple installations - | of Horizon on the same server so that they don't have problems. - | - */ - - 'prefix' => env( - 'HORIZON_PREFIX', - Str::slug(env('APP_NAME', 'laravel'), '_').'_horizon:' - ), - - /* - |-------------------------------------------------------------------------- - | Horizon Route Middleware - |-------------------------------------------------------------------------- - | - | These middleware will get attached onto each Horizon route, giving you - | the chance to add your own middleware to this list or change any of - | the existing middleware. Or, you can simply stick with this list. - | - */ - - 'middleware' => ['web'], - - /* - |-------------------------------------------------------------------------- - | Horizon Basic Auth - |-------------------------------------------------------------------------- - | - | These credentials are used for HTTP Basic Authentication on the Horizon - | dashboard. If these are not set, empty, or null, the page will be - | accessible without authentication. - | - */ - - 'basic_auth_username' => env('HORIZON_BASIC_AUTH_USERNAME'), - 'basic_auth_password' => env('HORIZON_BASIC_AUTH_PASSWORD'), - - /* - |-------------------------------------------------------------------------- - | Queue Wait Time Thresholds - |-------------------------------------------------------------------------- - | - | This option allows you to configure when the LongWaitDetected event - | will be fired. Every connection / queue combination may have its - | own, unique threshold (in seconds) before this event is fired. - | - */ - - 'waits' => [ - 'redis:default' => 60, - ], - - /* - |-------------------------------------------------------------------------- - | Job Trimming Times - |-------------------------------------------------------------------------- - | - | Here you can configure for how long (in minutes) you desire Horizon to - | persist the recent and failed jobs. Typically, recent jobs are kept - | for one hour while all failed jobs are stored for an entire week. - | - */ - - 'trim' => [ - 'recent' => 60, - 'pending' => 60, - 'completed' => 60, - 'recent_failed' => 10080, - 'failed' => 10080, - 'monitored' => 10080, - ], - - /* - |-------------------------------------------------------------------------- - | Silenced Jobs - |-------------------------------------------------------------------------- - | - | Silencing a job will instruct Horizon to not place the job in the list - | of completed jobs within the Horizon dashboard. This setting may be - | used to fully remove any noisy jobs from the completed jobs list. - | - */ - - 'silenced' => [ - // App\Jobs\ExampleJob::class, - ], - - 'silenced_tags' => [ - // 'notifications', - ], - - /* - |-------------------------------------------------------------------------- - | Metrics - |-------------------------------------------------------------------------- - | - | Here you can configure how many snapshots should be kept to display in - | the metrics graph. This will get used in combination with Horizon's - | `horizon:snapshot` schedule to define how long to retain metrics. - | - */ - - 'metrics' => [ - 'trim_snapshots' => [ - 'job' => 24, - 'queue' => 24, - ], - ], - - /* - |-------------------------------------------------------------------------- - | Fast Termination - |-------------------------------------------------------------------------- - | - | When this option is enabled, Horizon's "terminate" command will not - | wait on all of the workers to terminate unless the --wait option - | is provided. Fast termination can shorten deployment delay by - | allowing a new instance of Horizon to start while the last - | instance will continue to terminate each of its workers. - | - */ - - 'fast_termination' => false, - - /* - |-------------------------------------------------------------------------- - | Memory Limit (MB) - |-------------------------------------------------------------------------- - | - | This value describes the maximum amount of memory the Horizon master - | supervisor may consume before it is terminated and restarted. For - | configuring these limits on your workers, see the next section. - | - */ - - 'memory_limit' => 64, - - /* - |-------------------------------------------------------------------------- - | Queue Worker Configuration - |-------------------------------------------------------------------------- - | - | Here you may define the queue worker settings used by your application - | in all environments. These supervisors and settings handle all your - | queued jobs and will be provisioned by Horizon during deployment. - | - */ - - 'defaults' => [ - 'supervisor-default' => [ - 'connection' => 'redis', - 'queue' => ['default'], - 'balance' => 'auto', - 'autoScalingStrategy' => 'time', - 'maxProcesses' => 1, - 'maxTime' => 0, - 'maxJobs' => 0, - 'memory' => 128, - 'tries' => 1, - 'timeout' => 60, - 'nice' => 0, - ], - 'supervisor-emails' => [ - 'connection' => 'redis', - 'queue' => ['emails'], - 'balance' => 'simple', - 'maxProcesses' => 2, - 'maxTime' => 0, - 'maxJobs' => 0, - 'memory' => 128, - 'tries' => 3, - 'timeout' => 60, - 'nice' => 0, - ], - ], - - 'environments' => [ - 'production' => [ - 'supervisor-default' => [ - 'maxProcesses' => 10, - 'balanceMaxShift' => 1, - 'balanceCooldown' => 3, - ], - 'supervisor-emails' => [ - 'maxProcesses' => 3, - ], - ], - - 'local' => [ - 'supervisor-default' => [ - 'maxProcesses' => 3, - ], - 'supervisor-emails' => [ - 'maxProcesses' => 2, - ], - ], - ], -]; diff --git a/config/queue.php b/config/queue.php index 79c2c0a2..4fe599aa 100644 --- a/config/queue.php +++ b/config/queue.php @@ -41,7 +41,7 @@ return [ 'table' => env('DB_QUEUE_TABLE', 'jobs'), 'queue' => env('DB_QUEUE', 'default'), 'retry_after' => (int) env('DB_QUEUE_RETRY_AFTER', 90), - 'after_commit' => false, + 'after_commit' => true, ], 'beanstalkd' => [ diff --git a/docker/supervisor/supervisord.conf b/docker/supervisor/supervisord.conf index c15e17d5..0c4874be 100644 --- a/docker/supervisor/supervisord.conf +++ b/docker/supervisor/supervisord.conf @@ -39,6 +39,13 @@ autorestart=true stdout_logfile=/var/log/memcached.log stderr_logfile=/var/log/memcached.log +[program:redis] +command=redis-server --bind 127.0.0.1 --port 6379 --daemonize no +autostart=true +autorestart=true +stdout_logfile=/var/log/redis.log +stderr_logfile=/var/log/redis.log + [program:inertia-ssr] process_name=%(program_name)s_%(process_num)02d command=bash -c 'exec php /app/artisan inertia:start-ssr --runtime=bun' @@ -47,11 +54,12 @@ autorestart=true stderr_logfile=/var/log/worker-inertia-ssr.log stdout_logfile=/var/log/worker-inertia-ssr.log -[program:horizon] -process_name=%(program_name)s -command=php /app/artisan horizon +[program:queue-worker] +process_name=%(program_name)s_%(process_num)02d +command=php /app/artisan queue:work database --queue=emails,default --sleep=3 --tries=3 --max-time=3600 autostart=true autorestart=true redirect_stderr=true -stdout_logfile=/var/log/horizon.log +stdout_logfile=/var/log/queue-worker.log stopwaitsecs=3600 +numprocs=2