master

laravel/framework

Last updated at: 29/12/2023 09:21

CallbackEvent.php

TLDR

This file contains the CallbackEvent class, which extends the Event class. This class represents a scheduled event that executes a callback. The class contains methods for running the event, determining if the event should skip due to overlapping, running the callback in the background, executing the callback, and more.

Methods

__construct(EventMutex $mutex, $callback, array $parameters = [], $timezone = null)

This method is the constructor of the CallbackEvent class. It initializes the event by setting the mutex, callback, parameters, and timezone.

run(Container $container)

This method runs the callback event. It calls the run method of the parent class, checks if an exception was thrown during the callback execution, and returns the result of the callback.

shouldSkipDueToOverlapping()

This method determines if the event should skip because another process is overlapping. It checks if the event has a description and calls the shouldSkipDueToOverlapping method of the parent class.

runInBackground()

This method indicates that the callback should run in the background. It throws a RuntimeException with an error message.

execute($container)

This method runs the callback. It calls the callback using the Laravel container and stores the result. If an exception is thrown during the callback execution, it stores the exception. It returns the result of the callback.

withoutOverlapping($expiresAt = 1440)

This method does not allow the event to overlap each other. It throws a LogicException if the event does not have a description. It calls the withoutOverlapping method of the parent class with the specified expiration time.

onOneServer()

This method allows the event to only run on one server for each cron expression. It throws a LogicException if the event does not have a description. It calls the onOneServer method of the parent class.

getSummaryForDisplay()

This method gets the summary of the event for display. If the event has a description, it returns the description. Otherwise, if the callback is a string, it returns the callback. Otherwise, it returns "Callback".

mutexName()

This method gets the mutex name for the scheduled command. It returns a string that is the concatenation of "framework/schedule-" and the SHA1 hash of the event description (or an empty string if the description is not set).

removeMutex()

This method clears the mutex for the event. If the event has a description, it calls the removeMutex method of the parent class.

Classes

CallbackEvent

The CallbackEvent class represents a scheduled event that executes a callback. It extends the Event class and contains methods for running the event, determining if the event should skip due to overlapping, running the callback in the background, executing the callback, and more.

<?php

namespace Illuminate\Console\Scheduling;

use Illuminate\Contracts\Container\Container;
use Illuminate\Support\Reflector;
use InvalidArgumentException;
use LogicException;
use RuntimeException;
use Throwable;

class CallbackEvent extends Event
{
    /**
     * The callback to call.
     *
     * @var string
     */
    protected $callback;

    /**
     * The parameters to pass to the method.
     *
     * @var array
     */
    protected $parameters;

    /**
     * The result of the callback's execution.
     *
     * @var mixed
     */
    protected $result;

    /**
     * The exception that was thrown when calling the callback, if any.
     *
     * @var \Throwable|null
     */
    protected $exception;

    /**
     * Create a new event instance.
     *
     * @param  \Illuminate\Console\Scheduling\EventMutex  $mutex
     * @param  string|callable  $callback
     * @param  array  $parameters
     * @param  \DateTimeZone|string|null  $timezone
     * @return void
     *
     * @throws \InvalidArgumentException
     */
    public function __construct(EventMutex $mutex, $callback, array $parameters = [], $timezone = null)
    {
        if (! is_string($callback) && ! Reflector::isCallable($callback)) {
            throw new InvalidArgumentException(
                'Invalid scheduled callback event. Must be a string or callable.'
            );
        }

        $this->mutex = $mutex;
        $this->callback = $callback;
        $this->parameters = $parameters;
        $this->timezone = $timezone;
    }

    /**
     * Run the callback event.
     *
     * @param  \Illuminate\Contracts\Container\Container  $container
     * @return mixed
     *
     * @throws \Throwable
     */
    public function run(Container $container)
    {
        parent::run($container);

        if ($this->exception) {
            throw $this->exception;
        }

        return $this->result;
    }

    /**
     * Determine if the event should skip because another process is overlapping.
     *
     * @return bool
     */
    public function shouldSkipDueToOverlapping()
    {
        return $this->description && parent::shouldSkipDueToOverlapping();
    }

    /**
     * Indicate that the callback should run in the background.
     *
     * @return void
     *
     * @throws \RuntimeException
     */
    public function runInBackground()
    {
        throw new RuntimeException('Scheduled closures can not be run in the background.');
    }

    /**
     * Run the callback.
     *
     * @param  \Illuminate\Contracts\Container\Container  $container
     * @return int
     */
    protected function execute($container)
    {
        try {
            $this->result = is_object($this->callback)
                ? $container->call([$this->callback, '__invoke'], $this->parameters)
                : $container->call($this->callback, $this->parameters);

            return $this->result === false ? 1 : 0;
        } catch (Throwable $e) {
            $this->exception = $e;

            return 1;
        }
    }

    /**
     * Do not allow the event to overlap each other.
     *
     * The expiration time of the underlying cache lock may be specified in minutes.
     *
     * @param  int  $expiresAt
     * @return $this
     *
     * @throws \LogicException
     */
    public function withoutOverlapping($expiresAt = 1440)
    {
        if (! isset($this->description)) {
            throw new LogicException(
                "A scheduled event name is required to prevent overlapping. Use the 'name' method before 'withoutOverlapping'."
            );
        }

        return parent::withoutOverlapping($expiresAt);
    }

    /**
     * Allow the event to only run on one server for each cron expression.
     *
     * @return $this
     *
     * @throws \LogicException
     */
    public function onOneServer()
    {
        if (! isset($this->description)) {
            throw new LogicException(
                "A scheduled event name is required to only run on one server. Use the 'name' method before 'onOneServer'."
            );
        }

        return parent::onOneServer();
    }

    /**
     * Get the summary of the event for display.
     *
     * @return string
     */
    public function getSummaryForDisplay()
    {
        if (is_string($this->description)) {
            return $this->description;
        }

        return is_string($this->callback) ? $this->callback : 'Callback';
    }

    /**
     * Get the mutex name for the scheduled command.
     *
     * @return string
     */
    public function mutexName()
    {
        return 'framework/schedule-'.sha1($this->description ?? '');
    }

    /**
     * Clear the mutex for the event.
     *
     * @return void
     */
    protected function removeMutex()
    {
        if ($this->description) {
            parent::removeMutex();
        }
    }
}