mirror of
https://github.com/koel/koel
synced 2024-11-10 06:34:14 +00:00
feat: add Scheduler installation command (#1802)
This commit is contained in:
parent
e95ff45789
commit
7ae57e3d98
5 changed files with 145 additions and 26 deletions
|
@ -7,15 +7,15 @@ use App\Exceptions\InstallationFailedException;
|
||||||
use App\Models\Setting;
|
use App\Models\Setting;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use Illuminate\Console\Command;
|
use Illuminate\Console\Command;
|
||||||
use Illuminate\Contracts\Hashing\Hasher as Hash;
|
|
||||||
use Illuminate\Database\DatabaseManager as DB;
|
|
||||||
use Illuminate\Encryption\Encrypter;
|
use Illuminate\Encryption\Encrypter;
|
||||||
use Illuminate\Support\Facades\Artisan;
|
use Illuminate\Support\Facades\Artisan;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
use Illuminate\Support\Facades\File;
|
use Illuminate\Support\Facades\File;
|
||||||
|
use Illuminate\Support\Facades\Hash;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
use Illuminate\Support\Facades\Process;
|
use Illuminate\Support\Facades\Process;
|
||||||
use Illuminate\Support\Str;
|
use Illuminate\Support\Str;
|
||||||
use Jackiedo\DotenvEditor\DotenvEditor;
|
use Jackiedo\DotenvEditor\DotenvEditor;
|
||||||
use Psr\Log\LoggerInterface;
|
|
||||||
use Throwable;
|
use Throwable;
|
||||||
|
|
||||||
class InitCommand extends Command
|
class InitCommand extends Command
|
||||||
|
@ -32,12 +32,8 @@ class InitCommand extends Command
|
||||||
|
|
||||||
private bool $adminSeeded = false;
|
private bool $adminSeeded = false;
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(private readonly DotenvEditor $dotenvEditor)
|
||||||
private readonly Hash $hash,
|
{
|
||||||
private readonly DotenvEditor $dotenvEditor,
|
|
||||||
private readonly DB $db,
|
|
||||||
private readonly LoggerInterface $logger
|
|
||||||
) {
|
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,8 +60,9 @@ class InitCommand extends Command
|
||||||
$this->maybeSetMediaPath();
|
$this->maybeSetMediaPath();
|
||||||
$this->maybeCompileFrontEndAssets();
|
$this->maybeCompileFrontEndAssets();
|
||||||
$this->dotenvEditor->save();
|
$this->dotenvEditor->save();
|
||||||
|
$this->tryInstallingScheduler();
|
||||||
} catch (Throwable $e) {
|
} catch (Throwable $e) {
|
||||||
$this->logger->error($e);
|
Log::error($e);
|
||||||
|
|
||||||
$this->components->error("Oops! Koel installation or upgrade didn't finish successfully.");
|
$this->components->error("Oops! Koel installation or upgrade didn't finish successfully.");
|
||||||
$this->components->error('Please check the error log at storage/logs/laravel.log and try again.');
|
$this->components->error('Please check the error log at storage/logs/laravel.log and try again.');
|
||||||
|
@ -92,7 +89,7 @@ class InitCommand extends Command
|
||||||
$this->info('Again, visit 📙 ' . config('koel.misc.docs_url') . ' for more tips and tweaks.');
|
$this->info('Again, visit 📙 ' . config('koel.misc.docs_url') . ' for more tips and tweaks.');
|
||||||
|
|
||||||
$this->info(
|
$this->info(
|
||||||
"Feeling generous and want to support Koel's development? Check out "
|
"Feeling generous and want to support Koel’s development? Check out "
|
||||||
. config('koel.misc.sponsor_github_url')
|
. config('koel.misc.sponsor_github_url')
|
||||||
. ' 🤗'
|
. ' 🤗'
|
||||||
);
|
);
|
||||||
|
@ -202,7 +199,7 @@ class InitCommand extends Command
|
||||||
User::query()->create([
|
User::query()->create([
|
||||||
'name' => self::DEFAULT_ADMIN_NAME,
|
'name' => self::DEFAULT_ADMIN_NAME,
|
||||||
'email' => self::DEFAULT_ADMIN_EMAIL,
|
'email' => self::DEFAULT_ADMIN_EMAIL,
|
||||||
'password' => $this->hash->make(self::DEFAULT_ADMIN_PASSWORD),
|
'password' => Hash::make(self::DEFAULT_ADMIN_PASSWORD),
|
||||||
'is_admin' => true,
|
'is_admin' => true,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
@ -241,12 +238,12 @@ class InitCommand extends Command
|
||||||
try {
|
try {
|
||||||
// Make sure the config cache is cleared before another attempt.
|
// Make sure the config cache is cleared before another attempt.
|
||||||
Artisan::call('config:clear', ['--quiet' => true]);
|
Artisan::call('config:clear', ['--quiet' => true]);
|
||||||
$this->db->reconnect();
|
DB::reconnect();
|
||||||
$this->db->getDoctrineSchemaManager()->listTables();
|
DB::getDoctrineSchemaManager()->listTables();
|
||||||
|
|
||||||
break;
|
break;
|
||||||
} catch (Throwable $e) {
|
} catch (Throwable $e) {
|
||||||
$this->logger->error($e);
|
Log::error($e);
|
||||||
|
|
||||||
// We only try to update credentials if running in interactive mode.
|
// We only try to update credentials if running in interactive mode.
|
||||||
// Otherwise, we require admin intervention to fix them.
|
// Otherwise, we require admin intervention to fix them.
|
||||||
|
@ -347,11 +344,26 @@ class InitCommand extends Command
|
||||||
return File::isDirectory($path) && File::isReadable($path);
|
return File::isDirectory($path) && File::isReadable($path);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Generate a random key for the application.
|
|
||||||
*/
|
|
||||||
private function generateRandomKey(): string
|
private function generateRandomKey(): string
|
||||||
{
|
{
|
||||||
return 'base64:' . base64_encode(Encrypter::generateKey($this->laravel['config']['app.cipher']));
|
return 'base64:' . base64_encode(Encrypter::generateKey($this->laravel['config']['app.cipher']));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function tryInstallingScheduler(): void
|
||||||
|
{
|
||||||
|
if (PHP_OS_FAMILY === 'Windows' || PHP_OS_FAMILY === 'Unknown') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->components->info('Trying to install Koel scheduler…');
|
||||||
|
|
||||||
|
if (Artisan::call('koel:scheduler:install') !== self::SUCCESS) {
|
||||||
|
$this->components->warn(
|
||||||
|
'Failed to install scheduler. ' .
|
||||||
|
'Please install manually: https://docs.koel.dev/cli-commands#command-scheduling'
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
$this->components->info('Koel scheduler installed successfully.');
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
49
app/Console/Commands/InstallSchedulerCommand.php
Normal file
49
app/Console/Commands/InstallSchedulerCommand.php
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Console\Commands;
|
||||||
|
|
||||||
|
use Illuminate\Console\Command;
|
||||||
|
use TiBeN\CrontabManager\CrontabAdapter;
|
||||||
|
use TiBeN\CrontabManager\CrontabJob;
|
||||||
|
use TiBeN\CrontabManager\CrontabRepository;
|
||||||
|
|
||||||
|
class InstallSchedulerCommand extends Command
|
||||||
|
{
|
||||||
|
protected $signature = 'koel:scheduler:install';
|
||||||
|
protected $description = 'Install the scheduler for Koel';
|
||||||
|
|
||||||
|
public function handle(): int
|
||||||
|
{
|
||||||
|
if (PHP_OS_FAMILY === 'Windows' || PHP_OS_FAMILY === 'Unknown') {
|
||||||
|
$this->components->error('This command is only available on Linux systems.');
|
||||||
|
|
||||||
|
return self::FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
$crontab = new CrontabRepository(new CrontabAdapter());
|
||||||
|
|
||||||
|
$this->components->info('Trying to install Koel scheduler…');
|
||||||
|
|
||||||
|
if (self::schedulerInstalled($crontab)) {
|
||||||
|
$this->components->info('Koel scheduler is already installed. Skipping…');
|
||||||
|
|
||||||
|
return self::SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
$job = CrontabJob::createFromCrontabLine(
|
||||||
|
'* * * * * cd ' . base_path() . ' && php artisan schedule:run >> /dev/null 2>&1'
|
||||||
|
);
|
||||||
|
|
||||||
|
$crontab->addJob($job);
|
||||||
|
$crontab->persist();
|
||||||
|
|
||||||
|
$this->components->info('Koel scheduler installed successfully.');
|
||||||
|
|
||||||
|
return self::SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function schedulerInstalled(CrontabRepository $crontab): bool
|
||||||
|
{
|
||||||
|
return (bool) $crontab->findJobByRegex('/artisan schedule:run/');
|
||||||
|
}
|
||||||
|
}
|
|
@ -44,7 +44,8 @@
|
||||||
"league/flysystem-sftp-v3": "^3.0",
|
"league/flysystem-sftp-v3": "^3.0",
|
||||||
"saloonphp/xml-wrangler": "^1.2",
|
"saloonphp/xml-wrangler": "^1.2",
|
||||||
"phanan/poddle": "^1.0",
|
"phanan/poddle": "^1.0",
|
||||||
"spatie/laravel-ray": "^1.36"
|
"spatie/laravel-ray": "^1.36",
|
||||||
|
"tiben/crontab-manager": "*"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"mockery/mockery": "~1.0",
|
"mockery/mockery": "~1.0",
|
||||||
|
|
49
composer.lock
generated
49
composer.lock
generated
|
@ -4,7 +4,7 @@
|
||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "306146627425d3042b82f1cd347237c8",
|
"content-hash": "9da46e14c758c109ce78f30cbaa63a09",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "algolia/algoliasearch-client-php",
|
"name": "algolia/algoliasearch-client-php",
|
||||||
|
@ -9590,6 +9590,53 @@
|
||||||
],
|
],
|
||||||
"time": "2023-07-17T10:34:14+00:00"
|
"time": "2023-07-17T10:34:14+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "tiben/crontab-manager",
|
||||||
|
"version": "v1.4.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/TiBeN/CrontabManager.git",
|
||||||
|
"reference": "79ade7bfc895c4594905a2554d7a82f6567aabf3"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/TiBeN/CrontabManager/zipball/79ade7bfc895c4594905a2554d7a82f6567aabf3",
|
||||||
|
"reference": "79ade7bfc895c4594905a2554d7a82f6567aabf3",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">= 5.3"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"phpunit/phpunit": "^4.8.36|^5.7"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"TiBeN\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"Apache-2.0"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Benjamin Legendre",
|
||||||
|
"email": "legendre.benjamin@gmail.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "A library for managing linux cron jobs.",
|
||||||
|
"keywords": [
|
||||||
|
"crontab",
|
||||||
|
"scheduling"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/TiBeN/CrontabManager/issues",
|
||||||
|
"source": "https://github.com/TiBeN/CrontabManager/tree/v1.4.0"
|
||||||
|
},
|
||||||
|
"time": "2023-05-02T16:54:54+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "tijsverkoyen/css-to-inline-styles",
|
"name": "tijsverkoyen/css-to-inline-styles",
|
||||||
"version": "v2.2.7",
|
"version": "v2.2.7",
|
||||||
|
|
|
@ -143,9 +143,13 @@ php artisan koel:sync [options] # Alias, deprecated
|
||||||
| `I`, `--ignore=` | The comma-separated tags to ignore (exclude) from scanning. Valid tags are `title`, `album`,`artist`, `albumartist`, `track`, `disc`, `year`, `genre`, `lyrics`, and `cover`. |
|
| `I`, `--ignore=` | The comma-separated tags to ignore (exclude) from scanning. Valid tags are `title`, `album`,`artist`, `albumartist`, `track`, `disc`, `year`, `genre`, `lyrics`, and `cover`. |
|
||||||
| `F`, `--force` | Force re-scanning even unchanged files. |
|
| `F`, `--force` | Force re-scanning even unchanged files. |
|
||||||
|
|
||||||
|
### `koel:scheduler:install`
|
||||||
|
|
||||||
|
Install the command scheduler. Refer to [Command Scheduling](#command-scheduling) for more information.
|
||||||
|
|
||||||
### `koel:search:import`
|
### `koel:search:import`
|
||||||
|
|
||||||
Import all searchable entities with Scout. See [Instant Search](./usage/search) for more information.
|
Import all searchable entities with Scout. Refer to [Instant Search](./usage/search) for more information.
|
||||||
|
|
||||||
#### Usage
|
#### Usage
|
||||||
|
|
||||||
|
@ -210,16 +214,22 @@ php artisan koel:tags:collect
|
||||||
## Command Scheduling
|
## Command Scheduling
|
||||||
|
|
||||||
Some of the commands, such as `koel:scan` and `koel:prune`, can be scheduled to run at regular intervals.
|
Some of the commands, such as `koel:scan` and `koel:prune`, can be scheduled to run at regular intervals.
|
||||||
Koel uses Laravel’s built-in scheduler to manage this.
|
Instead of setting up individual cron jobs, you can use Koel’s built-in scheduler to automatically handle the commands for you.
|
||||||
|
|
||||||
In order to set up the scheduler, you need to add the following cron entry into the crontab of the webserver user (for example,
|
To set up the scheduler, run the `koel:scheduler:install` command as the web server user (e.g. `www-data` or `nginx`):
|
||||||
if it's `www-data`, run `sudo crontab -u www-data -e`):
|
|
||||||
|
```bash
|
||||||
|
php artisan koel:scheduler:install
|
||||||
|
```
|
||||||
|
|
||||||
|
Alternatively, you can manually add the following cron entry into the crontab of the webserver user (for example, if it's `www-data`, run `sudo crontab -u www-data -e`):
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
* * * * * cd /path-to-koel-installation && php artisan schedule:run >> /dev/null 2>&1
|
* * * * * cd /path-to-koel-installation && php artisan schedule:run >> /dev/null 2>&1
|
||||||
```
|
```
|
||||||
|
|
||||||
This will run the scheduler every minute, which will then run any scheduled commands as needed.
|
Either way, the scheduler will run every minute once installed, executing any scheduled commands as needed.
|
||||||
By default, `koel:scan`, `koel:prune`, and `koel:podcasts:sync` are set to run every day at midnight.
|
By default, `koel:scan`, `koel:prune`, and `koel:podcasts:sync` are set to run every day at midnight.
|
||||||
|
|
||||||
Though you can still manually set up cron jobs for individual commands, the scheduler is the recommended approach to command scheduling in Koel, as it will automatically cover any commands that may be added in the future.
|
Though you can still manually set up cron jobs for individual commands, the scheduler is the recommended approach to do command scheduling in Koel,
|
||||||
|
as it will automatically cover any commands that may be added in the future.
|
||||||
|
|
Loading…
Reference in a new issue