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

Add schedule config possibility from database #66

Open
gisostallenberg opened this issue Jul 20, 2022 · 12 comments
Open

Add schedule config possibility from database #66

gisostallenberg opened this issue Jul 20, 2022 · 12 comments

Comments

@gisostallenberg
Copy link
Contributor

Are you open to a possibility to configure tasks (only the types that accept string arguments) using a database.
I'm aware this can be created in my app, but having this out of the box would be a great addition to this nice package.

@kbond
Copy link
Member

kbond commented Jul 20, 2022

Interesting idea. My concern is with the added complexity. I'm also not sure how common such a requirement is... Are you thinking to use Doctrine ORM?

In my app, I have the task results stored in the db (which was easy to achieve) but not the definitions themselves.

I am completely open to an added event example showing how to achieve what you want. This would better scope the feature too - I've added some of the extending examples as features.

@gisostallenberg
Copy link
Contributor Author

An example scheduler bundle that uses this is https://github.com/j-guyon/CommandSchedulerBundle.
One of the things I like about this construction is that it allows to enable/disable command runs and configure cron times from a GUI.
I think it could be in a separate package though.

@kbond
Copy link
Member

kbond commented Jul 20, 2022

What fields would we add to the Entity? Cron string for sure I think (maybe not if the user wants complete control) but what about the other properties/extensions?

I could see adding a basic base entity and subscriber:

abstract class ScheduledTask
{
    abstract public function createTask(): Task // customize to your spec

    public function isEnabled(): bool
    {
        return true; // override with your own logic
    }
}
class DoctrineScheduledTaskSubscriber implements EventSubscriberInterface
{
    public function __construct(
        private ObjectManager $om,
        private string $class, // your app's ScheduledTask class-string (from config)
    ) {}

    public static function getSubscribedEvents(): array
    {
        return [BuildScheduleEvent::class => 'configureTasks'];
    }

    public function configureTasks(BuildScheduleEvent $event): void
    {
        foreach ($this->om->getRepository($this->class) as $entity) {
            if (!$entity->isEnabled()) {
                continue;
            }

            $event->getSchedule()->add($entity->createTask());
        }
    }
}

@gisostallenberg
Copy link
Contributor Author

I thought more in a fully automated way.
The entity would not need a createTask.

class DoctrineScheduledTaskSubscriber implements EventSubscriberInterface
{
    /**
     * @param class-string $class
     */
    public function __construct(
        private ObjectManager $om,
        private string $class = \Zenstruck\ScheduleBundle\Entity\ScheduledCommandTask::class
    ) {}

    public static function getSubscribedEvents(): array
    {
        return [BuildScheduleEvent::class => 'configureTasks'];
    }

    public function configureTasks(BuildScheduleEvent $event): void
    {
        foreach ($this->om->getRepository($this->class)->findEnabled() as $scheduledCommandTask) {
            $event->getSchedule()
                ->addCommand($scheduledCommandTask->getCommand())
                ->description($scheduledCommandTask->getDescription())
                // ...
                ->cron($scheduledCommandTask->getCronExpression());
        }
    }
}

I think most entity properties of https://github.com/j-guyon/CommandSchedulerBundle are usable, so I would add:

  • (id)
  • description
  • command
  • arguments
  • cronExpression
  • lastExecutedAt
  • lastReturnCode
  • disabled
  • locked

@gisostallenberg
Copy link
Contributor Author

After having played around with this some time I would add the following properties to the entity:

  • (id)
  • description
  • command
  • arguments
  • expression
  • lastRunAt (RunContext.startTime)
  • lastResult (Result.type)
  • lastResultMessage (Result.description)
  • disabled
  • locked

@kbond
Copy link
Member

kbond commented Jul 22, 2022

What's the difference between locked and disabled?

What about lastDuration and lastMemoryUsage?

@kbond
Copy link
Member

kbond commented Jul 22, 2022

Here's sort of what I'm thinking (for task definitions from db):

  1. Model\TaskDefinition interface with method createTask(): Task.
  2. Model\TaskDefinitionRepository interface with method findTaskDefinitions(): array<TaskDefinition>.
  3. Abstract (MappedSuperclass) Model\BaseTaskDefinition with the implementation you describe above.
  4. Concrete Model\ORMTaskDefinitionRepository with an ORM-specific implementation.
  5. DoctrineTaskDefinitionSubscriber similar to above. This would use the repository to load tasks and add them to the schedule.

I think (1) and (2) above are important as it allows someone to do something custom.

This leaves adding the result to the task definition. Maybe TaskDefinitionRepository has a handleResult(Result $result): void method that a subscriber sends every result to it. It would be up to the definition to match with a db task definition and save. ORMTaskDefinitionRepository could provide this implementation for BaseTaskDefinition.

How are you planning to match up task results to task definitions?

@gisostallenberg
Copy link
Contributor Author

gisostallenberg commented Jul 27, 2022

What's the difference between locked and disabled?

Locked is a system state, disabled can be set by an admin interface for example.

What about lastDuration and lastMemoryUsage?

Good one, should be added...

@pribeirojtm
Copy link

hello @kbond and @gisostallenberg ,

Do you have any working example on how to implement Tasks managment via database like out of the box?

Thanks

@kbond
Copy link
Member

kbond commented Jan 26, 2024

Do you have any working example on how to implement Tasks managment via database like out of the box?

I don't, no. I'd suggest looking into symfony/scheduler if you can. I know it has this ability but the docs are still a work in progress.

I'm sort of keeping this bundle in maintenance mode until Symfony 5.4 is EOL.

@gisostallenberg
Copy link
Contributor Author

No, I'm sorry

@pribeirojtm
Copy link

Thank you. symfony/scheduler is the way for new projects

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

3 participants