feat: add health route to check if db, cache and file manager are ok

This commit is contained in:
Yassine Doghri 2023-03-17 14:51:43 +00:00
parent e1b66ed7ed
commit 1dde11f8e4
5 changed files with 82 additions and 8 deletions

View File

@ -60,6 +60,11 @@ $routes->get('themes/colors', 'ColorsController', [
'as' => 'themes-colors-css',
]);
// health check
$routes->get('/health', 'HomeController::health', [
'as' => 'health',
]);
// We get a performance increase by specifying the default
// route since we don't have to scan directories.
$routes->get('/', 'HomeController', [

View File

@ -11,8 +11,11 @@ declare(strict_types=1);
namespace App\Controllers;
use App\Models\PodcastModel;
use CodeIgniter\Database\Exceptions\DatabaseException;
use CodeIgniter\HTTP\RedirectResponse;
use CodeIgniter\HTTP\ResponseInterface;
use Config\Services;
use Modules\Media\FileManagers\FileManagerInterface;
class HomeController extends BaseController
{
@ -48,4 +51,43 @@ class HomeController extends BaseController
return view('home', $data);
}
public function health(): ResponseInterface
{
$errors = [];
try {
db_connect();
} catch (DatabaseException) {
$errors[] = 'Unable to connect to the database.';
}
// --- Can Castopod connect to the cache handler
if (config('Cache')->handler !== 'dummy' && cache()->getCacheInfo() === null) {
$errors[] = 'Unable connect to the cache handler.';
}
// --- Can Castopod write to storage?
/** @var FileManagerInterface $fileManager */
$fileManager = service('file_manager', false);
if (! $fileManager->isHealthy()) {
$errors[] = 'Problem with file manager.';
}
if ($errors !== []) {
return $this->response->setStatusCode(503, 'Problem with cache handler.')
->setJSON([
'code' => 503,
'errors' => $errors,
]);
}
return $this->response->setStatusCode(200)
->setJSON([
'code' => 200,
'message' => '✨ All good!',
]);
}
}

View File

@ -132,4 +132,11 @@ class FS implements FileManagerInterface
return true;
}
public function isHealthy(): bool
{
helper('media');
return is_really_writable(ROOTPATH . 'public/' . media_path());
}
}

View File

@ -23,4 +23,6 @@ interface FileManagerInterface
public function deletePodcastImageSizes(string $podcastHandle): bool;
public function deletePersonImagesSizes(): bool;
public function isHealthy(): bool;
}

View File

@ -27,15 +27,19 @@ class S3 implements FileManagerInterface
'use_path_style_endpoint' => $config->s3['path_style_endpoint'],
]);
// create bucket if it does not already exist
if (! $this->s3->doesBucketExist((string) $this->config->s3['bucket'])) {
try {
$this->s3->createBucket([
'Bucket' => $this->config->s3['bucket'],
]);
} catch (Exception $exception) {
log_message('critical', $exception->getMessage());
try {
// create bucket if it does not already exist
if (! $this->s3->doesBucketExist((string) $this->config->s3['bucket'])) {
try {
$this->s3->createBucket([
'Bucket' => $this->config->s3['bucket'],
]);
} catch (Exception $exception) {
log_message('critical', $exception->getMessage());
}
}
} catch (Exception $exception) {
throw new Exception($exception->getMessage(), $exception->getCode(), $exception);
}
}
@ -171,4 +175,18 @@ class S3 implements FileManagerInterface
$podcastImageKeys = preg_grep("~^persons\/.*_.*.\.(jpg|png|webp)$~", $objectsKeys);
return (bool) $podcastImageKeys;
}
public function isHealthy(): bool
{
try {
// ok if bucket exists and you have permission to access it
$this->s3->headBucket([
'Bucket' => $this->config->s3['bucket'],
]);
} catch (Exception) {
return false;
}
return true;
}
}