Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Scheduler] Document hashed Cron expression #19441

Merged
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 67 additions & 15 deletions scheduler.rst
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ the task of creating a report::

class SendDailySalesReports
{
public function __construct(private string $id) {}
public function __construct(private int $id) {}

public function getId(): int
{
Expand All @@ -61,6 +61,9 @@ Next, create the handler that processes that kind of message::
// src/Scheduler/Handler/SendDailySalesReportsHandler.php
namespace App\Scheduler\Handler;

use App\Scheduler\Message\SendDailySalesReports;
use Symfony\Component\Messenger\Attribute\AsMessageHandler;

#[AsMessageHandler]
class SendDailySalesReportsHandler
{
Expand Down Expand Up @@ -105,9 +108,13 @@ The :class:`Symfony\\Component\\Scheduler\\Attribute\\AsSchedule` attribute,
which by default references the schedule named ``default``, allows you to register
on a particular schedule::

// src/Scheduler/MyScheduleProvider.php
// src/Scheduler/SaleTaskProvider.php
namespace App\Scheduler;

use Symfony\Component\Scheduler\Attribute\AsSchedule;
use Symfony\Component\Scheduler\Schedule;
use Symfony\Component\Scheduler\ScheduleProviderInterface;

#[AsSchedule]
class SaleTaskProvider implements ScheduleProviderInterface
{
Expand Down Expand Up @@ -168,22 +175,67 @@ Then, define the trigger date/time using the same syntax as the

RecurringMessage::cron('* * * * *', new Message());

.. tip::

Check out the `crontab.guru website`_ if you need help to construct/understand
cron expressions.

You can also use some special values that represent common cron expressions:

* ``#yearly``, ``#annually`` - Run once a year, midnight, Jan. 1 - ``0 0 1 1 *``
* ``#monthly`` - Run once a month, midnight, first of month - ``0 0 1 * *``
* ``#weekly`` - Run once a week, midnight on Sun - ``0 0 * * 0``
* ``#daily``, ``#midnight`` - Run once a day, midnight - ``0 0 * * *``
* ``#hourly`` - Run once an hour, first minute - ``0 * * * *``
* ``@yearly``, ``@annually`` - Run once a year, midnight, Jan. 1 - ``0 0 1 1 *``
* ``@monthly`` - Run once a month, midnight, first of month - ``0 0 1 * *``
* ``@weekly`` - Run once a week, midnight on Sun - ``0 0 * * 0``
* ``@daily``, ``@midnight`` - Run once a day, midnight - ``0 0 * * *``
* ``@hourly`` - Run once an hour, first minute - ``0 * * * *``

For example::

RecurringMessage::cron('#daily', new Message());
RecurringMessage::cron('@daily', new Message());

Hashed Cron Expression
~~~~~~~~~~~~~~~~~~~~~~
Comment on lines +195 to +196
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I want to make a sub section, which char should I use ?

Copy link
Member

@javiereguiluz javiereguiluz Jan 22, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We use the ........... separator for those sections. I did this while merging your PR.


If you have many trigger scheduled at same time (for example, at midnight, ``0 0 * * *``)
this will create a very long running schedules list right at this time.
This may cause an issue if a task has a memory leak.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like this sentence. Maybe we should talk about real use case.
If I remember fabpot talk about email campaign

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what about writing bottle neck like lot of I/O, memory spike, etc etc?


You can add a ``#``(for hash) symbol in expression to generate random value. The value
is deterministic based on the message. This means that while the value is random, it is
predictable and consistent. A message with string representation ``my task``
and a defined frequency of ``# # * * *`` will have an idempotent frequency
of ``56 20 * * *`` (every day at 8:56pm).

A hash range ``#(x-y)`` can also be used. For example, ``# #(0-7) * * *`` means daily,
some time between midnight and 7am. Using the ``#`` without a range creates a range
of any valid value for the field. ``# # # # #`` is short for ``#(0-59) #(0-23) #(1-28)
#(1-12) #(0-6)``.

You can also use some special values that represent common hashed cron expressions:

====================== ========================================================================
Alias Converts to
====================== ========================================================================
``#hourly`` ``# * * * *`` (at some minute every hour)
``#daily`` ``# # * * *`` (at some time every day)
``#weekly`` ``# # * * #`` (at some time every week)
``#weekly@midnight`` ``# #(0-2) * * #`` (at ``#midnight`` one day every week)
``#monthly`` ``# # # * *`` (at some time on some day, once per month)
``#monthly@midnight`` ``# #(0-2) # * *`` (at ``#midnight`` on some day, once per month)
``#annually`` ``# # # # *`` (at some time on some day, once per year)
``#annually@midnight`` ``# #(0-2) # # *`` (at ``#midnight`` on some day, once per year)
``#yearly`` ``# # # # *`` alias for ``#annually``
``#yearly@midnight`` ``# #(0-2) # # *`` alias for ``#annually@midnight``
``#midnight`` ``# #(0-2) * * *`` (at some time between midnight and 2:59am, every day)
====================== ========================================================================

.. tip::
For example::

Check out the `crontab.guru website`_ if you need help to construct/understand
cron expressions.
RecurringMessage::cron('#midnight', new Message());

.. note::

The day of month range is ``1-28``, this is to account for February
which has a minimum of 28 days.

.. versionadded:: 6.4

Expand Down Expand Up @@ -260,7 +312,7 @@ Then, define your recurring message::

Finally, the recurring messages has to be attached to a schedule::

// src/Scheduler/MyScheduleProvider.php
// src/Scheduler/SaleTaskProvider.php
namespace App\Scheduler;

#[AsSchedule('uptoyou')]
Expand Down Expand Up @@ -344,7 +396,7 @@ via the ``stateful`` option (and the :doc:`Cache component </components/cache>`)
This way, when it wakes up again, it looks at all the dates and can catch up on
what it missed::

// src/Scheduler/MyScheduleProvider.php
// src/Scheduler/SaleTaskProvider.php
namespace App\Scheduler;

#[AsSchedule('uptoyou')]
Expand All @@ -366,7 +418,7 @@ To scale your schedules more effectively, you can use multiple workers. In such
cases, a good practice is to add a :doc:`lock </components/lock>` to prevent the
same task more than once::

// src/Scheduler/MyScheduleProvider.php
// src/Scheduler/SaleTaskProvider.php
namespace App\Scheduler;

#[AsSchedule('uptoyou')]
Expand Down Expand Up @@ -395,7 +447,7 @@ your message in a :class:`Symfony\\Component\\Messenger\\Message\\RedispatchMess
This allows you to specify a transport on which your message will be redispatched
before being further redispatched to its corresponding handler::

// src/Scheduler/MyScheduleProvider.php
// src/Scheduler/SaleTaskProvider.php
namespace App\Scheduler;

#[AsSchedule('uptoyou')]
Expand Down