feat: redis & laravel horizon
This commit is contained in:
parent
e9bc15163c
commit
a48b6ae4ab
|
|
@ -0,0 +1,36 @@
|
|||
<?php
|
||||
|
||||
namespace App\Providers;
|
||||
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
use Laravel\Horizon\Horizon;
|
||||
use Laravel\Horizon\HorizonApplicationServiceProvider;
|
||||
|
||||
class HorizonServiceProvider extends HorizonApplicationServiceProvider
|
||||
{
|
||||
/**
|
||||
* Bootstrap any application services.
|
||||
*/
|
||||
public function boot(): void
|
||||
{
|
||||
parent::boot();
|
||||
|
||||
// Horizon::routeSmsNotificationsTo('15556667777');
|
||||
// Horizon::routeMailNotificationsTo('example@example.com');
|
||||
// Horizon::routeSlackNotificationsTo('slack-webhook-url', '#channel');
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the Horizon gate.
|
||||
*
|
||||
* This gate determines who can access Horizon in non-local environments.
|
||||
*/
|
||||
protected function gate(): void
|
||||
{
|
||||
Gate::define('viewHorizon', function ($user = null) {
|
||||
return in_array(optional($user)->email, [
|
||||
//
|
||||
]);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -3,4 +3,5 @@
|
|||
return [
|
||||
App\Providers\AppServiceProvider::class,
|
||||
App\Providers\Filament\DashboardPanelProvider::class,
|
||||
App\Providers\HorizonServiceProvider::class,
|
||||
];
|
||||
|
|
|
|||
40
compose.yaml
40
compose.yaml
|
|
@ -22,6 +22,7 @@ services:
|
|||
- sail
|
||||
depends_on:
|
||||
- pgsql
|
||||
- redis
|
||||
- meilisearch
|
||||
pgsql:
|
||||
image: 'postgres:18-alpine'
|
||||
|
|
@ -48,6 +49,21 @@ services:
|
|||
- '${DB_USERNAME}'
|
||||
retries: 3
|
||||
timeout: 5s
|
||||
redis:
|
||||
image: 'redis:alpine'
|
||||
ports:
|
||||
- '${FORWARD_REDIS_PORT:-6378}:6379'
|
||||
volumes:
|
||||
- 'sail-redis:/data'
|
||||
networks:
|
||||
- sail
|
||||
healthcheck:
|
||||
test:
|
||||
- CMD
|
||||
- redis-cli
|
||||
- ping
|
||||
retries: 3
|
||||
timeout: 5s
|
||||
meilisearch:
|
||||
image: 'getmeili/meilisearch:latest'
|
||||
ports:
|
||||
|
|
@ -67,11 +83,35 @@ services:
|
|||
- 'http://127.0.0.1:7700/health'
|
||||
retries: 3
|
||||
timeout: 5s
|
||||
horizon:
|
||||
build:
|
||||
context: ./vendor/laravel/sail/runtimes/8.5
|
||||
dockerfile: Dockerfile
|
||||
args:
|
||||
WWWGROUP: '${WWWGROUP}'
|
||||
image: sail-worker/app
|
||||
extra_hosts:
|
||||
- 'host.docker.internal:host-gateway'
|
||||
environment:
|
||||
WWWUSER: '${WWWUSER}'
|
||||
LARAVEL_SAIL: 1
|
||||
XDEBUG_MODE: '${SAIL_XDEBUG_MODE:-off}'
|
||||
XDEBUG_CONFIG: '${SAIL_XDEBUG_CONFIG:-client_host=host.docker.internal}'
|
||||
IGNITION_LOCAL_SITES_PATH: '${PWD}'
|
||||
volumes:
|
||||
- '.:/var/www/html'
|
||||
networks:
|
||||
- sail
|
||||
depends_on:
|
||||
- redis
|
||||
command: 'php artisan horizon'
|
||||
networks:
|
||||
sail:
|
||||
driver: bridge
|
||||
volumes:
|
||||
sail-pgsql:
|
||||
driver: local
|
||||
sail-redis:
|
||||
driver: local
|
||||
sail-meilisearch:
|
||||
driver: local
|
||||
|
|
|
|||
|
|
@ -12,10 +12,12 @@
|
|||
"filament/widgets": "^5.3",
|
||||
"http-interop/http-factory-guzzle": "^1.2",
|
||||
"laravel/framework": "^12.0",
|
||||
"laravel/horizon": "^5.45",
|
||||
"laravel/sanctum": "^4.0",
|
||||
"laravel/scout": "^11.0",
|
||||
"laravel/tinker": "^2.10.1",
|
||||
"meilisearch/meilisearch-php": "^1.16",
|
||||
"predis/predis": "^3.4",
|
||||
"scalar/laravel": "^0.2.0"
|
||||
},
|
||||
"require-dev": {
|
||||
|
|
|
|||
|
|
@ -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": "1b77e11c702fcc38f202aa5a9dbfef5a",
|
||||
"content-hash": "2a710ddb9f9c83cf6e70df03723922cc",
|
||||
"packages": [
|
||||
{
|
||||
"name": "anourvalar/eloquent-serialize",
|
||||
|
|
@ -2442,6 +2442,86 @@
|
|||
},
|
||||
"time": "2026-02-24T14:35:15+00:00"
|
||||
},
|
||||
{
|
||||
"name": "laravel/horizon",
|
||||
"version": "v5.45.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/laravel/horizon.git",
|
||||
"reference": "80c4de73c56227c625e5a3c6bfaddff760ab0962"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/laravel/horizon/zipball/80c4de73c56227c625e5a3c6bfaddff760ab0962",
|
||||
"reference": "80c4de73c56227c625e5a3c6bfaddff760ab0962",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-json": "*",
|
||||
"ext-pcntl": "*",
|
||||
"ext-posix": "*",
|
||||
"illuminate/contracts": "^9.21|^10.0|^11.0|^12.0|^13.0",
|
||||
"illuminate/queue": "^9.21|^10.0|^11.0|^12.0|^13.0",
|
||||
"illuminate/support": "^9.21|^10.0|^11.0|^12.0|^13.0",
|
||||
"laravel/sentinel": "^1.0",
|
||||
"nesbot/carbon": "^2.17|^3.0",
|
||||
"php": "^8.0",
|
||||
"ramsey/uuid": "^4.0",
|
||||
"symfony/console": "^6.0|^7.0|^8.0",
|
||||
"symfony/error-handler": "^6.0|^7.0|^8.0",
|
||||
"symfony/polyfill-php83": "^1.28",
|
||||
"symfony/process": "^6.0|^7.0|^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"mockery/mockery": "^1.0",
|
||||
"orchestra/testbench": "^7.56|^8.37|^9.16|^10.9|^11.0",
|
||||
"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.45.3"
|
||||
},
|
||||
"time": "2026-03-11T14:28:04+00:00"
|
||||
},
|
||||
{
|
||||
"name": "laravel/prompts",
|
||||
"version": "v0.3.13",
|
||||
|
|
@ -2644,6 +2724,65 @@
|
|||
},
|
||||
"time": "2026-03-10T19:16:37+00:00"
|
||||
},
|
||||
{
|
||||
"name": "laravel/sentinel",
|
||||
"version": "v1.0.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/laravel/sentinel.git",
|
||||
"reference": "7a98db53e0d9d6f61387f3141c07477f97425603"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/laravel/sentinel/zipball/7a98db53e0d9d6f61387f3141c07477f97425603",
|
||||
"reference": "7a98db53e0d9d6f61387f3141c07477f97425603",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-json": "*",
|
||||
"illuminate/container": "^8.37|^9.0|^10.0|^11.0|^12.0|^13.0",
|
||||
"php": "^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"laravel/pint": "^1.27",
|
||||
"orchestra/testbench": "^6.47.1|^7.56|^8.37|^9.16|^10.9|^11.0",
|
||||
"phpstan/phpstan": "^2.1.33"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"laravel": {
|
||||
"providers": [
|
||||
"Laravel\\Sentinel\\SentinelServiceProvider"
|
||||
]
|
||||
},
|
||||
"branch-alias": {
|
||||
"dev-main": "1.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Laravel\\Sentinel\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Taylor Otwell",
|
||||
"email": "taylor@laravel.com"
|
||||
},
|
||||
{
|
||||
"name": "Mior Muhammad Zaki",
|
||||
"email": "mior@laravel.com"
|
||||
}
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/laravel/sentinel/tree/v1.0.1"
|
||||
},
|
||||
"time": "2026-02-12T13:32:54+00:00"
|
||||
},
|
||||
{
|
||||
"name": "laravel/serializable-closure",
|
||||
"version": "v2.0.10",
|
||||
|
|
@ -4855,6 +4994,69 @@
|
|||
},
|
||||
"time": "2021-08-15T12:53:48+00:00"
|
||||
},
|
||||
{
|
||||
"name": "predis/predis",
|
||||
"version": "v3.4.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/predis/predis.git",
|
||||
"reference": "2033429520d8997a7815a2485f56abe6d2d0e075"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/predis/predis/zipball/2033429520d8997a7815a2485f56abe6d2d0e075",
|
||||
"reference": "2033429520d8997a7815a2485f56abe6d2d0e075",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.2 || ^8.0",
|
||||
"psr/http-message": "^1.0|^2.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"friendsofphp/php-cs-fixer": "^3.3",
|
||||
"phpstan/phpstan": "^1.9",
|
||||
"phpunit/phpcov": "^6.0 || ^8.0",
|
||||
"phpunit/phpunit": "^8.0 || ~9.4.4"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-relay": "Faster connection with in-memory caching (>=0.6.2)"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Predis\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Till Krüss",
|
||||
"homepage": "https://till.im",
|
||||
"role": "Maintainer"
|
||||
}
|
||||
],
|
||||
"description": "A flexible and feature-complete Redis/Valkey client for PHP.",
|
||||
"homepage": "http://github.com/predis/predis",
|
||||
"keywords": [
|
||||
"nosql",
|
||||
"predis",
|
||||
"redis"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/predis/predis/issues",
|
||||
"source": "https://github.com/predis/predis/tree/v3.4.2"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://github.com/sponsors/tillkruss",
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2026-03-09T20:33:04+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/clock",
|
||||
"version": "1.0.0",
|
||||
|
|
|
|||
|
|
@ -0,0 +1,254 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Horizon Name
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This name appears in notifications and in the Horizon UI. Unique names
|
||||
| can be useful while running multiple instances of Horizon within an
|
||||
| application, allowing you to identify the Horizon you're viewing.
|
||||
|
|
||||
*/
|
||||
|
||||
'name' => 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'],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| 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-1' => [
|
||||
'connection' => 'redis',
|
||||
'queue' => ['default'],
|
||||
'balance' => 'auto',
|
||||
'autoScalingStrategy' => 'time',
|
||||
'maxProcesses' => 1,
|
||||
'maxTime' => 0,
|
||||
'maxJobs' => 0,
|
||||
'memory' => 128,
|
||||
'tries' => 1,
|
||||
'timeout' => 60,
|
||||
'nice' => 0,
|
||||
],
|
||||
],
|
||||
|
||||
'environments' => [
|
||||
'production' => [
|
||||
'supervisor-1' => [
|
||||
'maxProcesses' => 10,
|
||||
'balanceMaxShift' => 1,
|
||||
'balanceCooldown' => 3,
|
||||
],
|
||||
],
|
||||
|
||||
'local' => [
|
||||
'supervisor-1' => [
|
||||
'maxProcesses' => 3,
|
||||
],
|
||||
],
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| File Watcher Configuration
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The following list of directories and files will be watched when using
|
||||
| the `horizon:listen` command. Whenever any directories or files are
|
||||
| changed, Horizon will automatically restart to apply all changes.
|
||||
|
|
||||
*/
|
||||
|
||||
'watch' => [
|
||||
'app',
|
||||
'bootstrap',
|
||||
'config/**/*.php',
|
||||
'database/**/*.php',
|
||||
'public/**/*.php',
|
||||
'resources/**/*.php',
|
||||
'routes',
|
||||
'composer.lock',
|
||||
'composer.json',
|
||||
'.env',
|
||||
],
|
||||
];
|
||||
|
|
@ -2,7 +2,10 @@
|
|||
|
||||
use Illuminate\Foundation\Inspiring;
|
||||
use Illuminate\Support\Facades\Artisan;
|
||||
use Illuminate\Support\Facades\Schedule;
|
||||
|
||||
Artisan::command('inspire', function () {
|
||||
$this->comment(Inspiring::quote());
|
||||
})->purpose('Display an inspiring quote');
|
||||
|
||||
Schedule::command('horizon:snapshot')->everyFiveMinutes();
|
||||
|
|
|
|||
Loading…
Reference in New Issue