#Schedule stopped itself

1 messages · Page 1 of 1 (latest)

south yew
#

Hello,
I would like my Laravel application to execute a function present in one of my controllers at certain times of the day, before that I wanted to do a test.
So in: app\Console\Kernel.php I did:

<?php

namespace App\Console;

use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
use App\Http\Controllers\LuccaController;

class Kernel extends ConsoleKernel
{
    /**
     * Define the application's command schedule.
     */
    protected function schedule(Schedule $schedule)
    {
        $schedule->call(function () {
            $luccaController = new LuccaController();
            $luccaController->testSchedule();
        })->everyTwoSeconds();
    }
    /**
     * Register the commands for the application.
     */
    protected function commands(): void
    {
        $this->load(__DIR__.'/Commands');

        require base_path('routes/console.php');
    }
}

And here is the function in my controller :

public function testSchedule()
    {
        error_log("Function has been called correctly !");
    }

It works well but for a few seconds after a while it stops by itself:

myproject> php artisan schedule:run

  2024-02-26 11:13:43 Running [Callback] Function has been called correctly !
.................................................................................................. 2ms DONE
  2024-02-26 11:13:45 Running [Callback] Function has been called correctly !
.................................................................................................. 0ms DONE
  2024-02-26 11:13:47 Running [Callback] Function has been called correctly !
.................................................................................................. 0ms DONE
  2024-02-26 11:13:49 Running [Callback] Function has been called correctly !
.................................................................................................. 1ms DONE
  2024-02-26 11:13:51 Running [Callback] Function has been called correctly !
.................................................................................................. 1ms DONE
  2024-02-26 11:13:53 Running [Callback] Function has been called correctly !
.................................................................................................. 0ms DONE
  2024-02-26 11:13:55 Running [Callback] Function has been called correctly !
.................................................................................................. 0ms DONE
  2024-02-26 11:13:57 Running [Callback] Function has been called correctly !
.................................................................................................. 1ms DONE
  2024-02-26 11:13:59 Running [Callback] Function has been called correctly !
.................................................................................................. 1ms DONE

And it stopped here, I have to re run it.
It's the same with everyMinute(); but it only run once.

Do you have any idea why ? Thx !

vernal marten
#

why does it have to be 'in a controller'?

move it to an action/service/jobs (depends on usecase) class and have both your schedule and controller call it

rich steeple
#

The schedule:run command has to be called once every minute (usually via cron). It doesn't keep running forever.

#

Also completely agree with what @vernal marten said. You should never, ever, instantiate controllers manually.

south yew
vernal marten
#

controllers are for handling (web) requests. Not neciserally for the logic that has to run.. said logic is usually extracted to an action or service class so it can be reused elsewhere

south yew
# vernal marten why does it have to be 'in a controller'? move it to an action/service/jobs (de...

I use an external service(multiple apis) which returns me several useful information for the users of my Laravel application.
I didn't know the concepts of services etc... So thank you !
In my controller function I call several APIs to save certain information in my database, I used this function manually via an API that I had created which was connected to a button because the data only changed very rarely.

vernal marten
#

yeah, you could extract communication with the api to a service class which you can use inside an action (structure we use at work)

south yew
#

So if I understood correctly:

  • I need to move the functions of my controller into a service file. app\Http\Service\TheService.php (is the path correct ?)
  • Then I need to call this service on my controller.
  • And finally I have to call the “schedule:run” command via cron which will call my service? But then what's the point of using a schedule?
#

Why do I put "everyMinute();" if he can't do that every minute?

vernal marten
#

schedule is only usefull if an action/job has to run at a specific time/interval

what is the right structure for you.. is up for you to decide, you may want to read into https://laravelactions.com/.. not saying to use the package.. but the way of working is quite useful

vernal marten
frozen forge
# south yew Why do I put "everyMinute();" if he can't do that every minute?

Are you referring to it stopping after a minute? That's exactly what the schedule:run command is supposed to do, as you'd add it to the CRON and run it every minute. If you want to test it out locally you can run the scheduler as a process until you stop it with schedule:work; https://laravel.com/docs/10.x/scheduling#running-the-scheduler-locally
I'd recommend reading through the documentation, what is what etc. Like what was said, a controller is a method that uses the request input and produces output for the request (the C in MVC). You wouldn't use that outside of a request, a scheduled task is not a request. That's where refactoring / extracting techniques come in, so you can reuse parts of your code. For example to dispatch a job every minute, which will then do certain actions on an API, you can reuse that action in other parts of your code as well

Also damnit Jordy..

south yew
vernal marten
#

I'd say use a job and schedule it?

#

the job can call your service/action jut like your controller can

#

there isn't really a 'do it like this' sadly

#

personal preference shrug .. just don't manually instantiate a controller

south yew
vernal marten
#

im dead

frozen forge
south yew
#

I think I didn't understand 😂

frozen forge
#

What are you on about? You could say the same for anything, you have a server which will receive a request, which is forwarded to nginx, which is forwarded to php-fpm, which will then execute the code, and then return a response all the way back

#

We were just saying, you shouldn't call a controller. You'd do that by abstracting your code in some way. How you do that is totally up to you. You could create a simple class, call that in a schedule closure. You could create a job that gets dispatched by the scheduler.

south yew
south yew
rich steeple
#

There is a lot of stuff to learn with such a big framework, and we've all been there. I recommend checking out the video tutorials on laracasts.com.

south yew
south yew
# frozen forge We were just saying, you shouldn't call a controller. You'd do that by abstracti...

So, I moved my logic into a service class, I am calling this service into my schedule and my controller and everything is working fine. Thank you for that !
But now I have a problem, my laravel web app is build with a dockerfile and then I push this image into a Kubernetes cluster.
Here is a part of my previous dockerfile when everything was working :

FROM webdevops/php-nginx:8.2-alpine

RUN apk add oniguruma-dev libxml2-dev
RUN docker-php-ext-install \
        bcmath \
        ctype \
        fileinfo \
        mbstring \
        pdo_mysql \
        xml

COPY --from=composer:latest /usr/bin/composer /usr/bin/composer

ENV WEB_DOCUMENT_ROOT /app/public
ENV APP_ENV production
WORKDIR /app
COPY . .

RUN cp -n .env.example .env

RUN composer install --no-interaction --optimize-autoloader --no-dev
# Generate security key
RUN php artisan key:generate
# Optimizing Configuration loading
RUN php artisan config:cache
# Optimizing View loading
RUN php artisan view:cache

RUN chown -R application:application .

I just added this part at then end of it :

RUN { \
        echo "* * * * * cd /app && php artisan schedule:run >> /dev/null 2>&1"; \
    } | crontab -

CMD ["sh", "-c", "crond -f -l 8 & php-fpm"]

But when I am going to my production Laravel web app I have this error :
503 Service Temporarily Unavailable

When I check the log kubectl get pods of my cluster I can see :
STATUS :
CrashLoopBackOff

And it keeps restarting itself,
So here is the question : does anyone know how can I start the schedule with Cron on a laravel web app which is deployed with docker and kubernetes

rich steeple
#

I'm not an expert, but I think the usual solution is to use Supervisor when you need to start multiple services in a single container.

mental rune
south yew
# mental rune The webdevops containers have supervisord built in, use that instead of run comm...

Hello, this part of my project was in standby.
I just added this to my dockerfile:

RUN apk --no-cache add supervisor

COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf

CMD ["/usr/bin/supervisord", "-n", "-c", "/etc/supervisor/conf.d/supervisord.conf"]

And I created a "supervisord.conf" file :

[supervisord]
nodaemon=true
user=root

[program:laravel-scheduler]
command=/bin/bash -c "sleep 300 && php artisan schedule:run"
directory=/app
autostart=true
autorestart=true
startsecs=300
startretries=0
stderr_logfile=/var/log/laravel-scheduler.err.log
stderr_logfile_maxbytes=1024MB
stdout_logfile=/var/log/laravel-scheduler.out.log
stdout_logfile_maxbytes=1024MB

And it works! My scheduler is working well because I see the data in my database being updated!

But, my Laravel application is no longer accessible

502 Bad Gateway

nginx

Any idea ? I have found this but I don't really know what to do :

"Don't forget that command key overrides default CMD in Dockerfile, therefore that command won't be run. For example, if php:7.4-fpm final command is CMD php-fpm, it won't be run."

Here is my dockerfile :

FROM webdevops/php-nginx:8.2-alpine

# Installation dans l'image du minimum pour que Docker fonctionne
RUN apk add oniguruma-dev libxml2-dev
RUN docker-php-ext-install \
        bcmath \
        ctype \
        fileinfo \
        mbstring \
        pdo_mysql \
        xml

# Installation de l'image de Composer
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer

# Installation de Supervisor
RUN apk --no-cache add supervisor
# Configuration de Supervisor
COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf

ENV WEB_DOCUMENT_ROOT /app/public
ENV APP_ENV production
ENV APP_DEBUG false

WORKDIR /app
COPY . .

RUN cp -n .env.example .env

# Installation et configuration du site pour la production
# https://laravel.com/docs/8.x/deployment#optimizing-configuration-loading
RUN composer install --no-interaction --optimize-autoloader --no-dev
# Generate security key
RUN php artisan key:generate
# Optimizing Configuration loading
RUN php artisan config:cache
# Optimizing View loading
RUN php artisan view:cache

RUN chown -R application:application .

# Exécutez supervisor pour gérer les processus
CMD ["/usr/bin/supervisord", "-n", "-c", "/etc/supervisor/conf.d/supervisord.conf"]

Thx 🙂

mental rune
#

Apologies, I should've suggested to use the inbuilt-crons instead of supervisor workers for the scheduler

# Configure Cron
RUN docker-service enable cron
RUN docker-cronjob '* * * * * php /app/artisan schedule:run'
#

that should configure the container to use cron and setup a cronjob

south yew
mental rune
#

yeah it should work, then remove the custom supervisor command

#

it's likely that you're preventing the other supervisor files from loading by specifying that specific config

#

the container will automatically include anything in /opt/docker/etc/supervisor.d/

mental rune
#

may need to be RUN docker-cronjob '* * * * * application php /app/artisan schedule:run'

#

actually just re-read the error, strange

#

maybe just try use supervisor for now by just copying your config file into /opt/docker/etc/supervisor.d/ and using the normal CMD

south yew