Commit 1dde11f8 authored by Yassine Doghri's avatar Yassine Doghri
Browse files

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

parent e1b66ed7
Loading
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -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', [
+42 −0
Original line number Diff line number Diff line
@@ -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!',
            ]);
    }
}
+7 −0
Original line number Diff line number Diff line
@@ -132,4 +132,11 @@ class FS implements FileManagerInterface

        return true;
    }

    public function isHealthy(): bool
    {
        helper('media');

        return is_really_writable(ROOTPATH . 'public/' . media_path());
    }
}
+2 −0
Original line number Diff line number Diff line
@@ -23,4 +23,6 @@ interface FileManagerInterface
    public function deletePodcastImageSizes(string $podcastHandle): bool;

    public function deletePersonImagesSizes(): bool;

    public function isHealthy(): bool;
}
+26 −8
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@ class S3 implements FileManagerInterface
            'use_path_style_endpoint' => $config->s3['path_style_endpoint'],
        ]);

        try {
            // create bucket if it does not already exist
            if (! $this->s3->doesBucketExist((string) $this->config->s3['bucket'])) {
                try {
@@ -37,6 +38,9 @@ class S3 implements FileManagerInterface
                    log_message('critical', $exception->getMessage());
                }
            }
        } catch (Exception $exception) {
            throw new Exception($exception->getMessage(), $exception->getCode(), $exception);
        }
    }

    public function save(File $file, string $key): string|false
@@ -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;
    }
}