dunglas
Repos
394
Followers
3257
Following
35

Create REST and GraphQL APIs, scaffold Jamstack webapps, stream changes in real-time.

7841
884

An open, easy, fast, reliable and battery-efficient solution for real-time communications

3290
230

Fast and idiomatic client-driven REST APIs.

3365
97

The Symfony PHP framework

28142
8785

A browser testing and web crawling library for PHP and Symfony

2701
208

React ESI: Blazing-fast Server-Side Rendering for React and Next.js

643
26

Events

issue comment
refactor(metadata): use HttpOperation constants for methods

👍 for consistency, but let's use a raw string everywhere then.

Created at 7 hours ago
pull request opened
fix: Vary HTTP header

Accept-Encoding is a request header. The intent here was to set the Vary header to prevent sending responses compressed with modern algorithms to old browsers and sending responses compressed with old suboptimal algorithms to modern browsers.

Created at 9 hours ago
create branch
dunglas create branch fix/vary-header
Created at 9 hours ago
Created at 9 hours ago
issue comment
refactor(metadata): use HttpOperation constants for methods

Could you do a profile please? IIRC resolving the constants has a runtime cost that can be significant and it's why we do not use them at least on the hot path.

Created at 12 hours ago

move the test app in FWBundle

Created at 5 days ago

[String] Correct inflection of 'codes' and 'names'

Add the Scheduler component

[Scheduler] Rework the component

[Validator] Update BIC validator IBAN mappings

[DependencyInjection] Add support for generating lazy closures

[ErrorHandler] Fixed tests

minor #49707 [ErrorHandler] Fixed tests (lyrixx)

This PR was merged into the 6.3 branch.

Discussion

[ErrorHandler] Fixed tests

| Q | A | ------------- | --- | Branch? | 6.3 | Bug fix? | no | New feature? | no | Deprecations? | no | Tickets | | License | MIT | Doc PR |

Commits

bb8b73ea22 [ErrorHandler] Fixed tests

feature #47112 [Messenger] Add a scheduler component (upyx, fabpot)

This PR was merged into the 6.3 branch.

Discussion

[Messenger] Add a scheduler component

| Q | A | ------------- | --- | Branch? | 6.3 | Bug fix? | no | New feature? | yes | Deprecations? | no | Tickets | no | License | MIT | Doc PR | TBD

Introdution

There is no easy way to schedule periodical tasks. There are few useful tools which I touched:

  • https://github.com/Guikingone/SchedulerBundle
  • https://github.com/Cron/Symfony-Bundle
  • https://github.com/zenstruck/schedule-bundle
  • https://github.com/lavary/crunz

They are complicated. They doesn't allow to set time with precision in seconds (at least it isn't easy). They require difficult tricks to set not linear periods (like on sunset in Tokyo). ~They are~ Part of them inefficient with infrequent tasks because resources are needed on every run (e.g. Kubernetes CronJob creates and destroes an entire container).

Proposal

I use a custom transport of Messenger that generates messages periodically. It's a simple solution to run periodical jobs without external software. It's especially helpful in environments where additional runners are impossible or very painful (like Kubernetes). Configuration is very flexible and accurate, it's possible to configure any rules when to run or not to run.

Compared to crond: there is no need to install something external, precision of schedule in microseconds instead of minutes, it's possible to set any periods.

Simple example

# messenger.yaml
framework:
  messenger:
    transports:
      schedule_default: 'schedule://default'

Few types of messages:

class SomeJob {}
class OtherJob {}

A handlers:

#[AsMessageHandler]
class SomeJobHandler {
    public function __invoke(SomeJob $job) {
        // do job or delegate it to other service
    }
}

#[AsMessageHandler]
class OtherJobHandler {
    public function __invoke(OtherJob $job) {
        // do job or delegate it to other service
    }
}

A schedules are provided by locators. It's possible to create many locators and/or provide many schedules by the same locator:

class ExampleLocator implements ScheduleLocatorInterface
{
    public function get(string $id): ScheduleConfig
    {
        // once after an hour from now
        $deferForAnHour = new \DatePeriod(
            new \DateTimeImmutable('now'),
            new \DateInterval('PT1H'),
            1,
            \DatePeriod::EXCLUDE_START_DATE
        );

        return (new ScheduleConfig())
            ->add(new OnceTrigger(new \DateTimeImmutable()), new WarmUpJob()) // once on every worker's start
            ->add(PeriodicalTrigger::create('P1D', '2022-01-01T03:00:00Z'), new SomeJob()) // every night at 3 a.m. (UTC)
            ->add(PeriodicalTrigger::fromPeriod($deferForAnHour), new OtherJob())
        ;
    }

    public function has(string $id): bool
    {
        return 'default' === $id;
    }
}

To run schedule:

bin/console messenger:consume schedule_default

It's easy to run jobs manually:

#[AsCommand(name: 'some', description: 'Manually runs SomeJob')]
class SomeCommand extends Command {
    public function __construct(private MessageBusInterface $bus) {
    }

    protected function execute(InputInterface $input, OutputInterface $output): int {
        $this->bus->dispatch(new SomeJob());
    }
}

Example with returning a result

class GoodJob {
    public function __construct(public readonly ?LoggerInterface $logger) {
    }
}
#[AsMessageHandler]
class GoodHandler {
    public function __construct(private readonly LoggerInterface $logger) {
    }

    public function __invoke(GoodJob $job){
        // compute $result
        ($job->logger ?? $this->logger)->info('The result is: {result}', ['result' => $result])
    }
}
#[AsCommand(name: 'job', description: 'Manually runs job')]
class SomeCommand extends Command {
    public function __construct(private MessageBusInterface $bus) {
    }

    protected function execute(InputInterface $input, OutputInterface $output): int {
        $this->bus->dispatch(new GoodJob(new ConsoleLogger($output))); // result will be printed in console
    }
}

Configuring

A minimal configuration:

# messenger.yaml
framework:
  messenger:
    transports:
      schedule_default: 'schedule://default'

More complex example:

# messenger.yaml
framework:
  messenger:
    transports:
      schedule_default:
        dsn: 'schedule://default'
        options:
          cache: 'app.cache'
          lock: 'default'

Example HA configuration with redis:

framework:
  cache:
    default_redis_provider: '%env(REDIS_DSN)%'
  lock:
    redis: '%env(REDIS_DSN)%'
  messenger:
    transports:
      schedule_default:
        dsn: 'schedule://default'
        options:
          cache: 'cache.redis'
          lock:
            resource: 'redis'
            ttl: 60
            auto_release: true

Deprecations

None

Implementation

This PR contains an implementation.

ToDo

  • [x] Remove obsolete code
  • [x] Add a configuration to the Framework
  • [x] Specialize exceptions and improve messages
  • [x] Cover with tests
  • [ ] Add acceptance tests for HA
  • [x] Fix CHANGELOGs & READMEs
  • [ ] Add documentation

Commits

a18127b789 [Scheduler] Rework the component 6d9311f087 Add the Scheduler component

add translations for the filename max length validator option

explicitly set the HTTP method override option to false

minor #49715 [FrameworkBundle] explicitly set the HTTP method override option to false (xabbuh)

This PR was merged into the 6.2 branch.

Discussion

[FrameworkBundle] explicitly set the HTTP method override option to false

| Q | A | ------------- | --- | Branch? | 6.2 | Bug fix? | no | New feature? | no | Deprecations? | no | Tickets | | License | MIT | Doc PR |

Commits

489f9ca64d explicitly set the HTTP method override option to false

[Scheduler] Fix some minor bugs

Merge branch '6.2' into 6.3

  • 6.2: explicitly set the HTTP method override option to false

[HttpFoundation] Add ParameterBag::getString() and deprecate accepting invalid values

[Scheduler] Remove unused variable in AddScheduleMessengerPass

minor #49717 [Scheduler] Remove unused variable in AddScheduleMessengerPass (onEXHovia)

This PR was merged into the 6.3 branch.

Discussion

[Scheduler] Remove unused variable in AddScheduleMessengerPass

| Q | A | ------------- | --- | Branch? | 6.3 | Bug fix? | yes | New feature? | no | Deprecations? | no | Tickets | n/a | License | MIT | Doc PR | n/a

Commits

09df772306 [Scheduler] Remove unused variable in AddScheduleMessengerPass

[Notifier] Add "retry" and "expire" options to Pushover bridge

minor #49695 [Notifier] Add "retry" and "expire" options to Pushover bridge (vlepeule)

This PR was squashed before being merged into the 6.3 branch.

Discussion

[Notifier] Add "retry" and "expire" options to Pushover bridge

| Q | A | ------------- | --- | Branch? | 6.3 | Bug fix? | yes | New feature? | no | Deprecations? | no | Tickets | - | License | MIT | Doc PR | -

Add "retry" and "expire" options to handle "Emergency Priority", according to Pushover API documentation :

To send an emergency-priority notification, the priority parameter must be set to 2 and the retry and expire parameters must be supplied.

Commits

2feabc641c [Notifier] Add "retry" and "expire" options to Pushover bridge

minor #49716 [Scheduler] Fix some minor bugs (fabpot)

This PR was merged into the 6.3 branch.

Discussion

[Scheduler] Fix some minor bugs

| Q | A | ------------- | --- | Branch? | 6.3 | Bug fix? | yes | New feature? | no | Deprecations? | no | Tickets | n/a | License | MIT | Doc PR | n/a

Commits

9fc7cf53dd [Scheduler] Fix some minor bugs

Stop stopwatch events in case of exception

Created at 5 days ago
issue comment
[ImportMaps] Manage JavaScript dependencies without a JS toolchain

Support for module preloading added and most comments fixed.

Created at 5 days ago

support for modules preloading

Created at 5 days ago

address review comments and cleanup

Created at 5 days ago

remove enums, simplify code

Created at 6 days ago

fix some issues

Created at 1 week ago