diff --git a/docker-compose.override.yaml.dist b/docker-compose.override.yaml.dist index e318e942..42626754 100644 --- a/docker-compose.override.yaml.dist +++ b/docker-compose.override.yaml.dist @@ -14,8 +14,8 @@ x-mutagen: permissions: defaultDirectoryMode: 0755 defaultFileMode: 0644 - ignore: - vcs: true + # ignore: + # vcs: true code: alpha: "." beta: "volume://code" diff --git a/docker-compose.override.yml.dist b/docker-compose.override.yml.dist deleted file mode 100644 index e318e942..00000000 --- a/docker-compose.override.yml.dist +++ /dev/null @@ -1,22 +0,0 @@ -version: '3.7' - -services: - php: - volumes: - - code:/srv/app - -volumes: - code: - -x-mutagen: - sync: - defaults: - permissions: - defaultDirectoryMode: 0755 - defaultFileMode: 0644 - ignore: - vcs: true - code: - alpha: "." - beta: "volume://code" - mode: "two-way-resolved" diff --git a/src/Command/ConsumeTasksCommand.php b/src/Command/ConsumeTasksCommand.php index d9aa08de..50cff6ff 100644 --- a/src/Command/ConsumeTasksCommand.php +++ b/src/Command/ConsumeTasksCommand.php @@ -107,26 +107,26 @@ protected function configure(): void */ protected function execute(InputInterface $input, OutputInterface $output): int { - $symfonyStyle = new SymfonyStyle($input, $output); + $symfonyStyle = new SymfonyStyle(input: $input, output: $output); - $wait = $input->getOption('wait'); - $force = $input->getOption('force'); - $lazy = $input->getOption('lazy'); - $strict = $input->getOption('strict'); + $wait = $input->getOption(name: 'wait'); + $force = $input->getOption(name: 'force'); + $lazy = $input->getOption(name: 'lazy'); + $strict = $input->getOption(name: 'strict'); - $dueTasks = $this->scheduler->getDueTasks(true === $lazy, true === $strict)->filter(static fn (TaskInterface $task): bool => !$task instanceof ProbeTask); + $dueTasks = $this->scheduler->getDueTasks(lazy: true === $lazy, strict: true === $strict)->filter(static fn (TaskInterface $task): bool => !$task instanceof ProbeTask); if (0 === $dueTasks->count() && false === $wait) { - $symfonyStyle->warning('No due tasks found'); + $symfonyStyle->warning(message: 'No due tasks found'); return self::SUCCESS; } if (false === $force) { - $nonPausedTasks = $dueTasks->filter(static fn (TaskInterface $task): bool => $task->getState() !== TaskInterface::PAUSED); + $nonPausedTasks = $dueTasks->filter(filter: static fn (TaskInterface $task): bool => $task->getState() !== TaskInterface::PAUSED); if (0 === $nonPausedTasks->count()) { - $symfonyStyle->warning([ + $symfonyStyle->warning(message: [ 'Each tasks has already been executed for the current minute', - sprintf('Consider calling this command again at "%s"', (new DateTimeImmutable('+ 1 minute'))->format('Y-m-d h:i')), + sprintf('Consider calling this command again at "%s"', (new DateTimeImmutable(datetime: '+ 1 minute'))->format(format: 'Y-m-d h:i')), ]); return self::SUCCESS; @@ -135,55 +135,56 @@ protected function execute(InputInterface $input, OutputInterface $output): int $stopOptions = []; - if (null !== $limit = $input->getOption('limit')) { + if (null !== $limit = $input->getOption(name: 'limit')) { $stopOptions[] = sprintf('%s task%s %s been consumed', $limit, (int) $limit > 1 ? 's' : '', (int) $limit > 1 ? 'have' : 'has'); - $this->eventDispatcher->addSubscriber(new StopWorkerOnTaskLimitSubscriber((int) $limit, $this->logger)); + $this->eventDispatcher->addSubscriber(subscriber: new StopWorkerOnTaskLimitSubscriber((int) $limit, $this->logger)); } - if (null !== $timeLimit = $input->getOption('time-limit')) { + if (null !== $timeLimit = $input->getOption(name: 'time-limit')) { $stopOptions[] = sprintf('it has been running for %d seconds', $timeLimit); - $this->eventDispatcher->addSubscriber(new StopWorkerOnTimeLimitSubscriber((int) $timeLimit, $this->logger)); + $this->eventDispatcher->addSubscriber(subscriber: new StopWorkerOnTimeLimitSubscriber((int) $timeLimit, $this->logger)); } - if (null !== $failureLimit = $input->getOption('failure-limit')) { + if (null !== $failureLimit = $input->getOption(name: 'failure-limit')) { $stopOptions[] = sprintf('%d task%s %s failed', $failureLimit, (int) $failureLimit > 1 ? 's' : '', (int) $failureLimit > 1 ? 'have' : 'has'); - $this->eventDispatcher->addSubscriber(new StopWorkerOnFailureLimitSubscriber((int) $failureLimit, $this->logger)); + $this->eventDispatcher->addSubscriber(subscriber: new StopWorkerOnFailureLimitSubscriber((int) $failureLimit, $this->logger)); } if ([] !== $stopOptions) { $last = array_pop($stopOptions); $stopsWhen = ([] !== $stopOptions ? implode(', ', $stopOptions).' or ' : '').$last; - $symfonyStyle->comment([ + $symfonyStyle->comment(message: [ 'The worker will automatically exit once:', sprintf('- %s', $stopsWhen), ]); } if (true === $wait) { - $symfonyStyle->note('The worker will wait for tasks every minutes'); + $symfonyStyle->note(message: 'The worker will wait for tasks every minutes'); } - $symfonyStyle->comment('Quit the worker with CONTROL-C.'); + $symfonyStyle->comment(message: 'Quit the worker with CONTROL-C.'); if (OutputInterface::VERBOSITY_VERY_VERBOSE !== $output->getVerbosity()) { - $symfonyStyle->note(sprintf('The task%s output can be displayed if the -vv option is used', $dueTasks->count() > 1 ? 's' : '')); + $symfonyStyle->note(message: sprintf('The task%s output can be displayed if the -vv option is used', $dueTasks->count() > 1 ? 's' : '')); } if ($output->isVeryVerbose()) { - $this->registerOutputSubscriber($symfonyStyle); + $this->registerOutputSubscriber(symfonyStyle: $symfonyStyle); } - $this->registerWorkerSleepingListener($symfonyStyle); - $this->registerTaskExecutedSubscriber($symfonyStyle); + $this->registerWorkerSleepingListener(symfonyStyle: $symfonyStyle); + $this->registerTaskExecutedSubscriber(symfonyStyle: $symfonyStyle); $workerConfiguration = WorkerConfiguration::create(); - $workerConfiguration->mustStrictlyCheckDate(true === $strict); - $workerConfiguration->mustSleepUntilNextMinute(true === $wait); + $workerConfiguration->mustStrictlyCheckDate(mustStrictlyCheckDate: true === $strict); + $workerConfiguration->mustSleepUntilNextMinute(sleepUntilNextMinute: true === $wait); + $workerConfiguration->lockTask(lock: true); try { - $this->worker->execute($workerConfiguration); + $this->worker->execute(configuration: $workerConfiguration); } catch (Throwable $throwable) { - $symfonyStyle->error([ + $symfonyStyle->error(message: [ 'An error occurred when executing the tasks', $throwable->getMessage(), ]); @@ -196,28 +197,28 @@ protected function execute(InputInterface $input, OutputInterface $output): int private function registerOutputSubscriber(SymfonyStyle $symfonyStyle): void { - $this->eventDispatcher->addListener(TaskExecutedEvent::class, static function (TaskExecutedEvent $event) use ($symfonyStyle): void { + $this->eventDispatcher->addListener(eventName: TaskExecutedEvent::class, listener: static function (TaskExecutedEvent $event) use ($symfonyStyle): void { $output = $event->getOutput(); if (null === $output->getOutput()) { return; } - $symfonyStyle->note(sprintf('Output for task "%s":', $event->getTask()->getName())); - $symfonyStyle->text($output->getOutput()); + $symfonyStyle->note(message: sprintf('Output for task "%s":', $event->getTask()->getName())); + $symfonyStyle->text(message: $output->getOutput()); }); } private function registerTaskExecutedSubscriber(SymfonyStyle $symfonyStyle): void { - $this->eventDispatcher->addListener(TaskExecutedEvent::class, static function (TaskExecutedEvent $event) use ($symfonyStyle): void { + $this->eventDispatcher->addListener(eventName: TaskExecutedEvent::class, listener: static function (TaskExecutedEvent $event) use ($symfonyStyle): void { $task = $event->getTask(); $output = $event->getOutput(); $taskExecutionDuration = Helper::formatTime((int) $task->getExecutionComputationTime() / 100); $taskExecutionMemoryUsage = Helper::formatMemory($task->getExecutionMemoryUsage()); - if (in_array($task->getExecutionState(), [TaskInterface::TO_RETRY, TaskInterface::INCOMPLETE], true)) { - $symfonyStyle->warning([ + if (in_array(needle: $task->getExecutionState(), haystack: [TaskInterface::TO_RETRY, TaskInterface::INCOMPLETE], strict: true)) { + $symfonyStyle->warning(message: [ sprintf('The task "%s" cannot be executed fully', $task->getName()), 'The task will be retried next time', ]); @@ -226,14 +227,14 @@ private function registerTaskExecutedSubscriber(SymfonyStyle $symfonyStyle): voi } if (Output::ERROR === $output->getType()) { - $symfonyStyle->error([ + $symfonyStyle->error(message: [ sprintf('Task "%s" failed. (Duration: %s, Memory used: %s)', $task->getName(), $taskExecutionDuration, $taskExecutionMemoryUsage), ]); return; } - $symfonyStyle->success([ + $symfonyStyle->success(message: [ sprintf('Task "%s" succeed. (Duration: %s, Memory used: %s)', $task->getName(), $taskExecutionDuration, $taskExecutionMemoryUsage), ]); }); @@ -241,8 +242,8 @@ private function registerTaskExecutedSubscriber(SymfonyStyle $symfonyStyle): voi private function registerWorkerSleepingListener(SymfonyStyle $symfonyStyle): void { - $this->eventDispatcher->addListener(WorkerSleepingEvent::class, static function (WorkerSleepingEvent $event) use ($symfonyStyle): void { - $symfonyStyle->info(sprintf('The worker is currently sleeping during %d seconds', $event->getSleepDuration())); + $this->eventDispatcher->addListener(eventName: WorkerSleepingEvent::class, listener: static function (WorkerSleepingEvent $event) use ($symfonyStyle): void { + $symfonyStyle->info(message: sprintf('The worker is currently sleeping during %d seconds', $event->getSleepDuration())); }); } } diff --git a/src/Command/DebugMiddlewareCommand.php b/src/Command/DebugMiddlewareCommand.php index 0a81c748..bbe23c3c 100644 --- a/src/Command/DebugMiddlewareCommand.php +++ b/src/Command/DebugMiddlewareCommand.php @@ -44,15 +44,15 @@ public function __construct( */ protected function execute(InputInterface $input, OutputInterface $output): int { - $style = new SymfonyStyle($input, $output); + $style = new SymfonyStyle(input: $input, output: $output); $schedulerMiddlewareList = $this->schedulerMiddlewareStack->getMiddlewareList(); if ([] === $schedulerMiddlewareList) { - $style->warning('No middleware found for the scheduling phase'); + $style->warning(message: 'No middleware found for the scheduling phase'); } else { - $style->info(sprintf('Found %d middleware for the scheduling phase', count($schedulerMiddlewareList))); + $style->info(message: sprintf('Found %d middleware for the scheduling phase', count($schedulerMiddlewareList))); - $schedulerTable = new Table($output); + $schedulerTable = new Table(output: $output); $schedulerTable->setHeaders(['Name', 'PreScheduling', 'PostScheduling', 'Priority', 'Required']); $schedulerTable->addRows(array_map(static fn (PostExecutionMiddlewareInterface|PreExecutionMiddlewareInterface|PreSchedulingMiddlewareInterface|PostSchedulingMiddlewareInterface|RequiredMiddlewareInterface|OrderedMiddlewareInterface $middleware): array => [ (new ReflectionClass($middleware))->getShortName(), diff --git a/src/DependencyInjection/SchedulerBundleExtension.php b/src/DependencyInjection/SchedulerBundleExtension.php index f721ada7..c6a60b61 100644 --- a/src/DependencyInjection/SchedulerBundleExtension.php +++ b/src/DependencyInjection/SchedulerBundleExtension.php @@ -190,40 +190,40 @@ public function load(array $configs, ContainerBuilder $container): void { $schedulerBundleConfiguration = new SchedulerBundleConfiguration(); - $config = $this->processConfiguration($schedulerBundleConfiguration, $configs); + $config = $this->processConfiguration(configuration: $schedulerBundleConfiguration, configs: $configs); - if (!array_key_exists('transport', $config)) { + if (!array_key_exists(key: 'transport', array: $config)) { return; } - $this->registerParameters($container, $config); - $this->registerAutoConfigure($container); - $this->registerConfigurationFactories($container); - $this->registerConfiguration($container, $config); - $this->registerTransportFactories($container, $config); - $this->registerTransport($container, $config); - $this->registerLockStore($container, $config); - $this->registerScheduler($container); - $this->registerCommands($container); - $this->registerExpressionFactoryAndPolicies($container); - $this->registerBuilders($container); - $this->registerRunners($container); - $this->registerNormalizer($container); - $this->registerMessengerTools($container); - $this->registerSubscribers($container); - $this->registerTracker($container); - $this->registerWorker($container); - $this->registerWorkerRegistry($container); - $this->registerExecutionPolicyRegistry($container); - $this->registerExecutionPolicies($container); - $this->registerTasks($container, $config); - $this->registerDoctrineBridge($container, $config); - $this->registerRedisBridge($container); - $this->registerMiddlewareStacks($container, $config); - $this->registerProbeContext($container, $config); - $this->registerMercureSupport($container, $config); - $this->registerPoolSupport($container, $config); - $this->registerDataCollector($container); + $this->registerParameters(container: $container, configuration: $config); + $this->registerAutoConfigure(container: $container); + $this->registerConfigurationFactories(container: $container); + $this->registerConfiguration($container, configuration: $config); + $this->registerTransportFactories($container, configuration: $config); + $this->registerTransport($container, configuration: $config); + $this->registerLockStore($container, configuration: $config); + $this->registerScheduler(container: $container); + $this->registerCommands(container: $container); + $this->registerExpressionFactoryAndPolicies(container: $container); + $this->registerBuilders(container: $container); + $this->registerRunners(container: $container); + $this->registerNormalizer(container: $container); + $this->registerMessengerTools(container: $container); + $this->registerSubscribers(container: $container); + $this->registerTracker(container: $container); + $this->registerWorker(container: $container); + $this->registerWorkerRegistry(container: $container); + $this->registerExecutionPolicyRegistry(container: $container); + $this->registerExecutionPolicies(container: $container); + $this->registerTasks($container, configuration: $config); + $this->registerDoctrineBridge($container, configuration: $config); + $this->registerRedisBridge(container: $container); + $this->registerMiddlewareStacks($container, configuration: $config); + $this->registerProbeContext($container, configuration: $config); + $this->registerMercureSupport($container, configuration: $config); + $this->registerPoolSupport($container); + $this->registerDataCollector(container: $container); } /** @@ -231,37 +231,37 @@ public function load(array $configs, ContainerBuilder $container): void */ private function registerParameters(ContainerBuilder $container, array $configuration): void { - $container->setParameter('scheduler.timezone', $configuration['timezone']); - $container->setParameter('scheduler.trigger_path', $configuration['path']); - $container->setParameter('scheduler.scheduler_mode', $configuration['scheduler']['mode'] ?? 'default'); - $container->setParameter('scheduler.probe_enabled', $configuration['probe']['enabled'] ?? false); - $container->setParameter('scheduler.mercure_support', $configuration['mercure']['enabled']); - $container->setParameter('scheduler.pool_support', $configuration['pool']['enabled']); - $container->setParameter('scheduler.worker_mode', $configuration['worker']['mode']); - $container->setParameter('scheduler.worker_registry', $configuration['worker']['registry']); - $container->setParameter('scheduler.middleware_mode', $configuration['middleware']['mode']); + $container->setParameter(name: 'scheduler.timezone', value: $configuration['timezone']); + $container->setParameter(name: 'scheduler.trigger_path', value: $configuration['path']); + $container->setParameter(name: 'scheduler.scheduler_mode', value: $configuration['scheduler']['mode'] ?? 'default'); + $container->setParameter(name: 'scheduler.probe_enabled', value: $configuration['probe']['enabled'] ?? false); + $container->setParameter(name: 'scheduler.mercure_support', value: $configuration['mercure']['enabled']); + $container->setParameter(name: 'scheduler.pool_support', value: $configuration['pool']['enabled']); + $container->setParameter(name: 'scheduler.worker_mode', value: $configuration['worker']['mode']); + $container->setParameter(name: 'scheduler.worker_registry', value: $configuration['worker']['registry']); + $container->setParameter(name: 'scheduler.middleware_mode', value: $configuration['middleware']['mode']); } private function registerAutoConfigure(ContainerBuilder $container): void { - $container->registerForAutoconfiguration(RunnerInterface::class)->addTag(self::SCHEDULER_RUNNER_TAG); - $container->registerForAutoconfiguration(TransportInterface::class)->addTag('scheduler.transport'); - $container->registerForAutoconfiguration(TransportFactoryInterface::class)->addTag(self::SCHEDULER_TRANSPORT_FACTORY_TAG); - $container->registerForAutoconfiguration(TransportConfigurationInterface::class)->addTag(self::TRANSPORT_CONFIGURATION_TAG); - $container->registerForAutoconfiguration(ConfigurationFactoryInterface::class)->addTag(self::TRANSPORT_CONFIGURATION_FACTORY_TAG); - $container->registerForAutoconfiguration(PolicyInterface::class)->addTag(self::SCHEDULER_SCHEDULE_POLICY); - $container->registerForAutoconfiguration(WorkerInterface::class)->addTag(self::WORKER_TAG); - $container->registerForAutoconfiguration(MiddlewareStackInterface::class)->addTag('scheduler.middleware_hub'); - $container->registerForAutoconfiguration(PreSchedulingMiddlewareInterface::class)->addTag(self::SCHEDULER_SCHEDULER_MIDDLEWARE_TAG); - $container->registerForAutoconfiguration(PostSchedulingMiddlewareInterface::class)->addTag(self::SCHEDULER_SCHEDULER_MIDDLEWARE_TAG); - $container->registerForAutoconfiguration(PreExecutionMiddlewareInterface::class)->addTag(self::SCHEDULER_WORKER_MIDDLEWARE_TAG); - $container->registerForAutoconfiguration(PostExecutionMiddlewareInterface::class)->addTag(self::SCHEDULER_WORKER_MIDDLEWARE_TAG); - $container->registerForAutoconfiguration(ExpressionBuilderInterface::class)->addTag(self::SCHEDULER_EXPRESSION_BUILDER_TAG); - $container->registerForAutoconfiguration(BuilderInterface::class)->addTag(self::SCHEDULER_TASK_BUILDER_TAG); - $container->registerForAutoconfiguration(ProbeInterface::class)->addTag(self::SCHEDULER_PROBE_TAG); - $container->registerForAutoconfiguration(TaskBagInterface::class)->addTag('scheduler.task_bag'); - $container->registerForAutoconfiguration(SchedulerAwareInterface::class)->addTag('scheduler.entry_point'); - $container->registerForAutoconfiguration(ExecutionPolicyInterface::class)->addTag(self::EXECUTION_POLICY_TAG); + $container->registerForAutoconfiguration(interface: RunnerInterface::class)->addTag(name: self::SCHEDULER_RUNNER_TAG); + $container->registerForAutoconfiguration(interface: TransportInterface::class)->addTag(name: 'scheduler.transport'); + $container->registerForAutoconfiguration(interface: TransportFactoryInterface::class)->addTag(name: self::SCHEDULER_TRANSPORT_FACTORY_TAG); + $container->registerForAutoconfiguration(interface: TransportConfigurationInterface::class)->addTag(name: self::TRANSPORT_CONFIGURATION_TAG); + $container->registerForAutoconfiguration(interface: ConfigurationFactoryInterface::class)->addTag(name: self::TRANSPORT_CONFIGURATION_FACTORY_TAG); + $container->registerForAutoconfiguration(interface: PolicyInterface::class)->addTag(name: self::SCHEDULER_SCHEDULE_POLICY); + $container->registerForAutoconfiguration(interface: WorkerInterface::class)->addTag(name: self::WORKER_TAG); + $container->registerForAutoconfiguration(interface: MiddlewareStackInterface::class)->addTag(name: 'scheduler.middleware_hub'); + $container->registerForAutoconfiguration(interface: PreSchedulingMiddlewareInterface::class)->addTag(name: self::SCHEDULER_SCHEDULER_MIDDLEWARE_TAG); + $container->registerForAutoconfiguration(interface: PostSchedulingMiddlewareInterface::class)->addTag(name: self::SCHEDULER_SCHEDULER_MIDDLEWARE_TAG); + $container->registerForAutoconfiguration(interface: PreExecutionMiddlewareInterface::class)->addTag(name: self::SCHEDULER_WORKER_MIDDLEWARE_TAG); + $container->registerForAutoconfiguration(interface: PostExecutionMiddlewareInterface::class)->addTag(name: self::SCHEDULER_WORKER_MIDDLEWARE_TAG); + $container->registerForAutoconfiguration(interface: ExpressionBuilderInterface::class)->addTag(name: self::SCHEDULER_EXPRESSION_BUILDER_TAG); + $container->registerForAutoconfiguration(interface: BuilderInterface::class)->addTag(name: self::SCHEDULER_TASK_BUILDER_TAG); + $container->registerForAutoconfiguration(interface: ProbeInterface::class)->addTag(name: self::SCHEDULER_PROBE_TAG); + $container->registerForAutoconfiguration(interface: TaskBagInterface::class)->addTag(name: 'scheduler.task_bag'); + $container->registerForAutoconfiguration(interface: SchedulerAwareInterface::class)->addTag(name: 'scheduler.entry_point'); + $container->registerForAutoconfiguration(interface: ExecutionPolicyInterface::class)->addTag(name: self::EXECUTION_POLICY_TAG); } private function registerConfigurationFactories(ContainerBuilder $container): void @@ -335,20 +335,20 @@ private function registerConfigurationFactories(ContainerBuilder $container): vo */ private function registerConfiguration(ContainerBuilder $container, array $configuration): void { - $container->register(self::TRANSPORT_CONFIGURATION_TAG, TransportConfigurationInterface::class) - ->setFactory([new Reference(ConfigurationFactory::class, ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE), 'build']) - ->setArguments([ + $container->register(id: self::TRANSPORT_CONFIGURATION_TAG, class: TransportConfigurationInterface::class) + ->setFactory(factory: [new Reference(id: ConfigurationFactory::class, invalidBehavior: ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE), 'build']) + ->setArguments(arguments: [ $configuration['configuration']['dsn'], - new Reference(SerializerInterface::class, ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE), + new Reference(id: SerializerInterface::class, invalidBehavior: ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE), ]) - ->setPublic(false) - ->addTag(self::TRANSPORT_CONFIGURATION_TAG) - ->addTag('container.preload', [ + ->setPublic(boolean: false) + ->addTag(name: self::TRANSPORT_CONFIGURATION_TAG) + ->addTag(name: 'container.preload', attributes: [ 'class' => TransportConfigurationInterface::class, ]) ; - $container->setAlias(TransportConfigurationInterface::class, self::TRANSPORT_CONFIGURATION_TAG); + $container->setAlias(alias: TransportConfigurationInterface::class, id: self::TRANSPORT_CONFIGURATION_TAG); } /** @@ -521,6 +521,8 @@ private function registerScheduler(ContainerBuilder $container): void new Reference(TransportInterface::class, ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE), new Reference(SchedulerMiddlewareStackInterface::class, ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE), new Reference(EventDispatcherInterface::class, ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE), + new Reference('scheduler.lock_store.factory', ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE), + new Reference(LoggerInterface::class, ContainerInterface::NULL_ON_INVALID_REFERENCE), new Reference(MessageBusInterface::class, ContainerInterface::NULL_ON_INVALID_REFERENCE), ]) ->setPublic(false) @@ -1164,54 +1166,54 @@ private function registerWorker(ContainerBuilder $container): void private function registerWorkerRegistry(ContainerBuilder $container): void { - if (false === $container->getParameter('scheduler.worker_registry')) { + if (false === $container->getParameter(name: 'scheduler.worker_registry')) { return; } - $container->register(WorkerRegistry::class, WorkerRegistry::class) - ->setArguments([ - new TaggedIteratorArgument(self::WORKER_TAG), + $container->register(id: WorkerRegistry::class, class: WorkerRegistry::class) + ->setArguments(arguments: [ + new TaggedIteratorArgument(tag: self::WORKER_TAG), ]) - ->addTag('container.hot_path') - ->addTag('container.preload', [ + ->addTag(name: 'container.hot_path') + ->addTag(name: 'container.preload', attributes: [ 'class' => WorkerRegistry::class, ]) ; - $container->setAlias(WorkerRegistryInterface::class, WorkerRegistry::class); + $container->setAlias(alias: WorkerRegistryInterface::class, id: WorkerRegistry::class); } private function registerExecutionPolicyRegistry(ContainerBuilder $container): void { - $container->register(ExecutionPolicyRegistry::class, ExecutionPolicyRegistry::class) - ->setArguments([ - new TaggedIteratorArgument(self::EXECUTION_POLICY_TAG), + $container->register(id: ExecutionPolicyRegistry::class, class: ExecutionPolicyRegistry::class) + ->setArguments(arguments: [ + new TaggedIteratorArgument(tag: self::EXECUTION_POLICY_TAG), ]) - ->addTag('container.hot_path') - ->addTag('container.preload', [ + ->addTag(name: 'container.hot_path') + ->addTag(name: 'container.preload', attributes: [ 'class' => ExecutionPolicyRegistry::class, ]) ; - $container->setAlias(ExecutionPolicyRegistryInterface::class, ExecutionPolicyRegistry::class); + $container->setAlias(alias: ExecutionPolicyRegistryInterface::class, id: ExecutionPolicyRegistry::class); } private function registerExecutionPolicies(ContainerBuilder $container): void { - $container->register(DefaultPolicy::class, DefaultPolicy::class) - ->addTag(self::EXECUTION_POLICY_TAG) - ->addTag('container.hot_path') - ->addTag('container.preload', [ + $container->register(id: DefaultPolicy::class, class: DefaultPolicy::class) + ->addTag(name: self::EXECUTION_POLICY_TAG) + ->addTag(name: 'container.hot_path') + ->addTag(name: 'container.preload', attributes: [ 'class' => DefaultPolicy::class, ]) ; - if ('fiber' === $container->getParameter('scheduler.worker_mode')) { - $container->register(FiberPolicy::class, FiberPolicy::class) + if ('fiber' === $container->getParameter(name: 'scheduler.worker_mode')) { + $container->register(id: FiberPolicy::class, class: FiberPolicy::class) ->setArguments([ - new Reference(LoggerInterface::class, ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE), + new Reference(id: LoggerInterface::class, invalidBehavior: ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE), ]) - ->addTag(self::EXECUTION_POLICY_TAG) - ->addTag('container.hot_path') - ->addTag('container.preload', [ + ->addTag(name: self::EXECUTION_POLICY_TAG) + ->addTag(name: 'container.hot_path') + ->addTag(name: 'container.preload', attributes: [ 'class' => FiberPolicy::class, ]) ; @@ -1310,6 +1312,7 @@ private function registerMiddlewareStacks(ContainerBuilder $container, array $co new TaggedIteratorArgument(self::SCHEDULER_MIDDLEWARE_TAG), ]) ->setPublic(false) + ->addTag('container.hot_path') ->addTag('container.preload', [ 'class' => MiddlewareRegistry::class, ]) @@ -1380,6 +1383,7 @@ private function registerMiddlewareStacks(ContainerBuilder $container, array $co ->addTag(self::SCHEDULER_MIDDLEWARE_TAG) ->addTag(self::SCHEDULER_SCHEDULER_MIDDLEWARE_TAG) ->addTag(self::SCHEDULER_WORKER_MIDDLEWARE_TAG) + ->addTag('container.hot_path') ->addTag('container.preload', [ 'class' => NotifierMiddleware::class, ]) @@ -1390,6 +1394,7 @@ private function registerMiddlewareStacks(ContainerBuilder $container, array $co ->addTag(self::SCHEDULER_MIDDLEWARE_TAG) ->addTag(self::SCHEDULER_SCHEDULER_MIDDLEWARE_TAG) ->addTag(self::SCHEDULER_WORKER_MIDDLEWARE_TAG) + ->addTag('container.hot_path') ->addTag('container.preload', [ 'class' => TaskCallbackMiddleware::class, ]) @@ -1403,6 +1408,7 @@ private function registerMiddlewareStacks(ContainerBuilder $container, array $co ->setPublic(false) ->addTag(self::SCHEDULER_MIDDLEWARE_TAG) ->addTag(self::SCHEDULER_WORKER_MIDDLEWARE_TAG) + ->addTag('container.hot_path') ->addTag('container.preload', [ 'class' => SingleRunTaskMiddleware::class, ]) @@ -1415,6 +1421,7 @@ private function registerMiddlewareStacks(ContainerBuilder $container, array $co ->setPublic(false) ->addTag(self::SCHEDULER_MIDDLEWARE_TAG) ->addTag(self::SCHEDULER_WORKER_MIDDLEWARE_TAG) + ->addTag('container.hot_path') ->addTag('container.preload', [ 'class' => TaskUpdateMiddleware::class, ]) @@ -1428,6 +1435,7 @@ private function registerMiddlewareStacks(ContainerBuilder $container, array $co ->setPublic(false) ->addTag(self::SCHEDULER_MIDDLEWARE_TAG) ->addTag(self::SCHEDULER_WORKER_MIDDLEWARE_TAG) + ->addTag('container.hot_path') ->addTag('container.preload', [ 'class' => TaskLockBagMiddleware::class, ]) @@ -1437,6 +1445,7 @@ private function registerMiddlewareStacks(ContainerBuilder $container, array $co ->setPublic(false) ->addTag(self::SCHEDULER_MIDDLEWARE_TAG) ->addTag(self::SCHEDULER_WORKER_MIDDLEWARE_TAG) + ->addTag('container.hot_path') ->addTag('container.preload', [ 'class' => TaskExecutionMiddleware::class, ]) @@ -1451,6 +1460,7 @@ private function registerMiddlewareStacks(ContainerBuilder $container, array $co ->setPublic(false) ->addTag(self::SCHEDULER_MIDDLEWARE_TAG) ->addTag(self::SCHEDULER_WORKER_MIDDLEWARE_TAG) + ->addTag('container.hot_path') ->addTag('container.preload', [ 'class' => MaxExecutionMiddleware::class, ]) @@ -1550,9 +1560,9 @@ private function registerProbeContext(ContainerBuilder $container, array $config /** * @param ContainerBuilder $container - * @param array $config + * @param array $configuration */ - private function registerMercureSupport(ContainerBuilder $container, array $config): void + private function registerMercureSupport(ContainerBuilder $container, array $configuration): void { if (false === $container->getParameter('scheduler.mercure_support')) { return; @@ -1560,7 +1570,7 @@ private function registerMercureSupport(ContainerBuilder $container, array $conf $container->register('scheduler.mercure_hub', Hub::class) ->setArguments([ - $config['mercure']['hub_url'], + $configuration['mercure']['hub_url'], new Reference('scheduler.mercure.token_provider', ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE), ]) ->setPublic(false) @@ -1571,7 +1581,7 @@ private function registerMercureSupport(ContainerBuilder $container, array $conf $container->register('scheduler.mercure.token_provider', StaticTokenProvider::class) ->setArguments([ - $config['mercure']['jwt_token'], + $configuration['mercure']['jwt_token'], ]) ->setPublic(false) ->addTag('container.preload', [ @@ -1582,7 +1592,7 @@ private function registerMercureSupport(ContainerBuilder $container, array $conf $container->register(MercureEventSubscriber::class, MercureEventSubscriber::class) ->setArguments([ new Reference('scheduler.mercure_hub', ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE), - $config['mercure']['update_url'], + $configuration['mercure']['update_url'], new Reference(SerializerInterface::class, ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE), ]) ->setPublic(false) @@ -1593,51 +1603,48 @@ private function registerMercureSupport(ContainerBuilder $container, array $conf ; } - /** - * @param array $configuration - */ - private function registerPoolSupport(ContainerBuilder $container, array $configuration): void + private function registerPoolSupport(ContainerBuilder $container): void { - if (false === $container->getParameter('scheduler.pool_support')) { + if (false === $container->getParameter(name: 'scheduler.pool_support')) { return; } - $container->register(SchedulerConfigurationNormalizer::class, SchedulerConfigurationNormalizer::class) - ->setArguments([ - new Reference(TaskNormalizer::class, ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE), - new Reference('serializer.normalizer.datetimezone', ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE), - new Reference('serializer.normalizer.datetime', ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE), - new Reference('serializer.normalizer.object', ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE), + $container->register(id: SchedulerConfigurationNormalizer::class, class: SchedulerConfigurationNormalizer::class) + ->setArguments(arguments: [ + new Reference(id: TaskNormalizer::class, invalidBehavior: ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE), + new Reference(id: 'serializer.normalizer.datetimezone', invalidBehavior: ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE), + new Reference(id: 'serializer.normalizer.datetime', invalidBehavior: ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE), + new Reference(id: 'serializer.normalizer.object', invalidBehavior: ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE), ]) - ->setPublic(false) - ->addTag('serializer.normalizer') - ->addTag('container.preload', [ + ->setPublic(boolean: false) + ->addTag(name: 'serializer.normalizer') + ->addTag(name: 'container.preload', attributes: [ 'class' => SchedulerConfigurationNormalizer::class, ]) ; - $container->register(SchedulerPool::class, SchedulerPool::class) - ->setPublic(false) - ->addTag('container.preload', [ + $container->register(id: SchedulerPool::class, class: SchedulerPool::class) + ->setPublic(boolean: false) + ->addTag(name: 'container.preload', attributes: [ 'class' => SchedulerPool::class, ]) ; - $container->setAlias(SchedulerPoolInterface::class, SchedulerPool::class); + $container->setAlias(alias: SchedulerPoolInterface::class, id: SchedulerPool::class); } private function registerDataCollector(ContainerBuilder $container): void { - $container->register(SchedulerDataCollector::class, SchedulerDataCollector::class) + $container->register(id: SchedulerDataCollector::class, class: SchedulerDataCollector::class) ->setArguments([ - new Reference(TaskLoggerSubscriber::class, ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE), - new Reference(ProbeInterface::class, ContainerInterface::NULL_ON_INVALID_REFERENCE), + new Reference(id: TaskLoggerSubscriber::class, invalidBehavior: ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE), + new Reference(id: ProbeInterface::class, invalidBehavior: ContainerInterface::NULL_ON_INVALID_REFERENCE), ]) - ->setPublic(false) - ->addTag('data_collector', [ + ->setPublic(boolean: false) + ->addTag(name: 'data_collector', attributes: [ 'template' => '@Scheduler/Collector/data_collector.html.twig', 'id' => SchedulerDataCollector::NAME, ]) - ->addTag('container.preload', [ + ->addTag(name: 'container.preload', attributes: [ 'class' => SchedulerDataCollector::class, ]) ; diff --git a/src/Expression/Expression.php b/src/Expression/Expression.php index a73a2c8a..fb4aa913 100644 --- a/src/Expression/Expression.php +++ b/src/Expression/Expression.php @@ -67,15 +67,15 @@ public function __toString(): string public static function createFromString(string $expression): self { $self = new self(); - $self->setExpression($expression); + $self->setExpression(expression: $expression); return $self; } public function setExpression(string $expression): void { - if (str_starts_with($expression, '@')) { - $this->setMacro($expression); + if (str_starts_with(haystack: $expression, needle: '@')) { + $this->setMacro(macro: $expression); return; } @@ -90,106 +90,106 @@ public function getExpression(): string public function everySpecificMinutes(string $minutes): string { - return $this->changeExpression(0, $minutes); + return $this->changeExpression(position: 0, value: $minutes); } public function everySpecificHours(string $hours): string { - return $this->changeExpression(1, $hours); + return $this->changeExpression(position: 1, value: $hours); } public function everySpecificDays(string $days): string { - return $this->changeExpression(2, $days); + return $this->changeExpression(position: 2, value: $days); } public function everySpecificDaysOfWeek(string $days): string { - return $this->changeExpression(4, $days); + return $this->changeExpression(position: 4, value: $days); } public function everySpecificMonths(string $months): string { - return $this->changeExpression(3, $months); + return $this->changeExpression(position: 3, value: $months); } public function every5Minutes(): string { - return $this->changeExpression(0, '*/5'); + return $this->changeExpression(position: 0, value: '*/5'); } public function every10Minutes(): string { - return $this->changeExpression(0, '*/10'); + return $this->changeExpression(position: 0, value: '*/10'); } public function every15Minutes(): string { - return $this->changeExpression(0, '*/15'); + return $this->changeExpression(position: 0, value: '*/15'); } public function every20Minutes(): string { - return $this->changeExpression(0, '*/20'); + return $this->changeExpression(position: 0, value: '*/20'); } public function every25Minutes(): string { - return $this->changeExpression(0, '*/25'); + return $this->changeExpression(position: 0, value: '*/25'); } public function every30Minutes(): string { - return $this->changeExpression(0, '*/30'); + return $this->changeExpression(position: 0, value: '*/30'); } public function everyHours(): string { - return $this->changeExpression(0, '0'); + return $this->changeExpression(position: 0, value: '0'); } public function everyDays(): string { - $this->setExpression(self::ALLOWED_MACROS[self::DAILY_MACRO]); + $this->setExpression(expression: self::ALLOWED_MACROS[self::DAILY_MACRO]); return $this->expression; } public function everyWeeks(): string { - $this->setExpression(self::ALLOWED_MACROS[self::WEEKLY_MACRO]); + $this->setExpression(expression: self::ALLOWED_MACROS[self::WEEKLY_MACRO]); return $this->expression; } public function everyMonths(): string { - $this->setExpression(self::ALLOWED_MACROS[self::MONTHLY_MACRO]); + $this->setExpression(expression: self::ALLOWED_MACROS[self::MONTHLY_MACRO]); return $this->expression; } public function everyYears(): string { - $this->setExpression(self::ALLOWED_MACROS[self::YEARLY_MACRO]); + $this->setExpression(expression: self::ALLOWED_MACROS[self::YEARLY_MACRO]); return $this->expression; } public function at(string $time): string { - $fields = explode(':', $time); + $fields = explode(separator: ':', string: $time); - $this->changeExpression(0, 2 === count($fields) ? $fields[1] : '0'); - $this->changeExpression(1, $fields[0]); + $this->changeExpression(position: 0, value: 2 === count(value: $fields) ? $fields[1] : '0'); + $this->changeExpression(position: 1, value: $fields[0]); return $this->expression; } private function setMacro(string $macro): string { - if (!array_key_exists($macro, self::ALLOWED_MACROS)) { - throw new InvalidExpressionException(sprintf('The desired macro "%s" is not supported!', $macro)); + if (!array_key_exists(key: $macro, array: self::ALLOWED_MACROS)) { + throw new InvalidExpressionException(message: sprintf('The desired macro "%s" is not supported!', $macro)); } $this->expression = $macro; @@ -205,13 +205,13 @@ private function setMacro(string $macro): string */ private function changeExpression(int $position, string $value): string { - $fields = explode(' ', $this->expression); - if (!array_key_exists($position, $fields)) { - throw new InvalidArgumentException('The desired position is not valid'); + $fields = explode(separator: ' ', string: $this->expression); + if (!array_key_exists(key: $position, array: $fields)) { + throw new InvalidArgumentException(message: 'The desired position is not valid'); } $fields[$position] = $value; - return $this->expression = implode(' ', $fields); + return $this->expression = implode(separator: ' ', array: $fields); } } diff --git a/src/Expression/ExpressionBuilder.php b/src/Expression/ExpressionBuilder.php index b4a99a97..8c71ae93 100644 --- a/src/Expression/ExpressionBuilder.php +++ b/src/Expression/ExpressionBuilder.php @@ -25,17 +25,17 @@ public function __construct(private iterable $builders) public function build(string $expression, ?string $timezone = null): Expression { if ([] === $this->builders) { - throw new RuntimeException('No builder found'); + throw new RuntimeException(message: 'No builder found'); } foreach ($this->builders as $builder) { - if (!$builder->support($expression)) { + if (!$builder->support(expression: $expression)) { continue; } - return $builder->build($expression, $timezone ?? 'UTC'); + return $builder->build(expression: $expression, timezone: $timezone ?? 'UTC'); } - throw new InvalidArgumentException('The expression cannot be used'); + throw new InvalidArgumentException(message: 'The expression cannot be used'); } } diff --git a/src/FiberScheduler.php b/src/FiberScheduler.php index dd3f2375..5156dbe4 100644 --- a/src/FiberScheduler.php +++ b/src/FiberScheduler.php @@ -11,6 +11,7 @@ use SchedulerBundle\Pool\Configuration\SchedulerConfiguration; use SchedulerBundle\Task\LazyTask; use SchedulerBundle\Task\LazyTaskList; +use SchedulerBundle\Task\LockedTaskList; use SchedulerBundle\Task\TaskInterface; use SchedulerBundle\Task\TaskListInterface; use Throwable; @@ -126,9 +127,9 @@ public function getTasks(bool $lazy = false): TaskListInterface|LazyTaskList * * @throws Throwable {@see AbstractFiberHandler::handleOperationViaFiber()} */ - public function getDueTasks(bool $lazy = false, bool $strict = false): TaskListInterface|LazyTaskList + public function getDueTasks(bool $lazy = false, bool $strict = false, bool $lock = false): TaskListInterface|LazyTaskList|LockedTaskList { - return $this->handleOperationViaFiber(func: fn (): TaskListInterface|LazyTaskList => $this->scheduler->getDueTasks(lazy: $lazy, strict: $strict)); + return $this->handleOperationViaFiber(func: fn (): TaskListInterface|LazyTaskList|LockedTaskList => $this->scheduler->getDueTasks(lazy: $lazy, strict: $strict, lock: $lock)); } /** diff --git a/src/HttpScheduler.php b/src/HttpScheduler.php index 270a3c84..888034e2 100644 --- a/src/HttpScheduler.php +++ b/src/HttpScheduler.php @@ -11,6 +11,7 @@ use SchedulerBundle\Pool\Configuration\SchedulerConfiguration; use SchedulerBundle\Task\LazyTask; use SchedulerBundle\Task\LazyTaskList; +use SchedulerBundle\Task\LockedTaskList; use SchedulerBundle\Task\TaskInterface; use SchedulerBundle\Task\TaskList; use SchedulerBundle\Task\TaskListInterface; @@ -166,13 +167,13 @@ public function getTasks(bool $lazy = false): TaskListInterface|LazyTaskList $list = $this->serializer->deserialize(data: $response->getContent(), type: TaskInterface::class.'[]', format: 'json'); - return new TaskList(tasks: $list); + return $lazy ? new LazyTaskList(sourceList: new TaskList(tasks: $list)) : new TaskList(tasks: $list); } /** * {@inheritdoc} */ - public function getDueTasks(bool $lazy = false, bool $strict = false): TaskListInterface|LazyTaskList + public function getDueTasks(bool $lazy = false, bool $strict = false, bool $lock = false): TaskListInterface|LazyTaskList|LockedTaskList { $response = $this->httpClient->request(method: 'GET', url: sprintf('%s/tasks:due', $this->externalSchedulerEndpoint), options: [ 'headers' => [ @@ -181,6 +182,7 @@ public function getDueTasks(bool $lazy = false, bool $strict = false): TaskListI 'query' => [ 'lazy' => $lazy, 'strict' => $strict, + 'lock' => $lock, ], ]); @@ -211,7 +213,9 @@ public function next(bool $lazy = false): TaskInterface|LazyTask throw new RuntimeException(message: 'The next task cannot be retrieved'); } - return $this->serializer->deserialize(data: $response->getContent(), type: TaskInterface::class, format: 'json'); + $task = $this->serializer->deserialize(data: $response->getContent(), type: TaskInterface::class, format: 'json'); + + return $lazy ? new LazyTask(name: $task->getName(), sourceTaskClosure: static fn (): TaskInterface => $task) : $task; } /** diff --git a/src/LazyScheduler.php b/src/LazyScheduler.php index d895bcdc..3de24234 100644 --- a/src/LazyScheduler.php +++ b/src/LazyScheduler.php @@ -9,6 +9,7 @@ use SchedulerBundle\Pool\Configuration\SchedulerConfiguration; use SchedulerBundle\Task\LazyTask; use SchedulerBundle\Task\LazyTaskList; +use SchedulerBundle\Task\LockedTaskList; use SchedulerBundle\Task\TaskInterface; use SchedulerBundle\Task\TaskListInterface; @@ -113,11 +114,11 @@ public function getTasks(bool $lazy = false): TaskListInterface|LazyTaskList /** * {@inheritdoc} */ - public function getDueTasks(bool $lazy = false, bool $strict = false): TaskListInterface|LazyTaskList + public function getDueTasks(bool $lazy = false, bool $strict = false, bool $lock = false): TaskListInterface|LazyTaskList|LockedTaskList { $this->initialize(); - return $this->scheduler->getDueTasks(lazy: $lazy, strict: $strict); + return $this->scheduler->getDueTasks(lazy: $lazy, strict: $strict, lock: $lock); } /** diff --git a/src/Messenger/TaskToExecuteMessageHandler.php b/src/Messenger/TaskToExecuteMessageHandler.php index faa0c4fd..fac2bf1b 100644 --- a/src/Messenger/TaskToExecuteMessageHandler.php +++ b/src/Messenger/TaskToExecuteMessageHandler.php @@ -35,16 +35,16 @@ public function __construct( public function __invoke(TaskToExecuteMessage $taskMessage): void { $task = $taskMessage->getTask(); - $timezone = $task->getTimezone() ?? new DateTimeZone('UTC'); + $timezone = $task->getTimezone() ?? new DateTimeZone(timezone: 'UTC'); - if (!(new CronExpression($task->getExpression()))->isDue(new DateTimeImmutable('now', $timezone), $timezone->getName())) { + if (!(new CronExpression(expression: $task->getExpression()))->isDue(currentTime: new DateTimeImmutable(datetime: 'now', timezone: $timezone), timeZone: $timezone->getName())) { return; } while ($this->worker->isRunning()) { - $this->logger->info(sprintf('The task "%s" cannot be executed for now as the worker is currently running', $task->getName())); + $this->logger->info(message: sprintf('The task "%s" cannot be executed for now as the worker is currently running', $task->getName())); } - $this->worker->execute(WorkerConfiguration::create(), $task); + $this->worker->execute(configuration: WorkerConfiguration::create(), tasks: $task); } } diff --git a/src/Messenger/TaskToPauseMessageHandler.php b/src/Messenger/TaskToPauseMessageHandler.php index 57f10e95..5f73f1aa 100644 --- a/src/Messenger/TaskToPauseMessageHandler.php +++ b/src/Messenger/TaskToPauseMessageHandler.php @@ -18,6 +18,6 @@ public function __construct(private SchedulerInterface $scheduler) public function __invoke(TaskToPauseMessage $taskToPauseMessage): void { - $this->scheduler->pause($taskToPauseMessage->getTask()); + $this->scheduler->pause(taskName: $taskToPauseMessage->getTask()); } } diff --git a/src/Messenger/TaskToUpdateMessageHandler.php b/src/Messenger/TaskToUpdateMessageHandler.php index 3e70b532..ea3ce5f3 100644 --- a/src/Messenger/TaskToUpdateMessageHandler.php +++ b/src/Messenger/TaskToUpdateMessageHandler.php @@ -18,6 +18,6 @@ public function __construct(private TransportInterface $transport) public function __invoke(TaskToUpdateMessage $message): void { - $this->transport->update($message->getTaskName(), $message->getTask()); + $this->transport->update(name: $message->getTaskName(), updatedTask: $message->getTask()); } } diff --git a/src/Messenger/TaskToYieldMessageHandler.php b/src/Messenger/TaskToYieldMessageHandler.php index 6fe41769..73d8b3f2 100644 --- a/src/Messenger/TaskToYieldMessageHandler.php +++ b/src/Messenger/TaskToYieldMessageHandler.php @@ -18,6 +18,6 @@ public function __construct(private SchedulerInterface $scheduler) public function __invoke(TaskToYieldMessage $taskToYieldMessage): void { - $this->scheduler->yieldTask($taskToYieldMessage->getName()); + $this->scheduler->yieldTask(name: $taskToYieldMessage->getName()); } } diff --git a/src/Middleware/TaskCallbackMiddleware.php b/src/Middleware/TaskCallbackMiddleware.php index a60ccb81..681beb73 100644 --- a/src/Middleware/TaskCallbackMiddleware.php +++ b/src/Middleware/TaskCallbackMiddleware.php @@ -27,7 +27,7 @@ public function preScheduling(TaskInterface $task, SchedulerInterface $scheduler return; } - if (!is_callable($callback)) { + if (!is_callable(value: $callback)) { return; } @@ -46,7 +46,7 @@ public function postScheduling(TaskInterface $task, SchedulerInterface $schedule return; } - if (!is_callable($callback)) { + if (!is_callable(value: $callback)) { return; } @@ -67,7 +67,7 @@ public function preExecute(TaskInterface $task): void return; } - if (!is_callable($callback)) { + if (!is_callable(value: $callback)) { return; } @@ -86,7 +86,7 @@ public function postExecute(TaskInterface $task, WorkerInterface $worker): void return; } - if (!is_callable($callback)) { + if (!is_callable(value: $callback)) { return; } diff --git a/src/Middleware/TaskLockBagMiddleware.php b/src/Middleware/TaskLockBagMiddleware.php index 0cb85535..74cc1c2c 100644 --- a/src/Middleware/TaskLockBagMiddleware.php +++ b/src/Middleware/TaskLockBagMiddleware.php @@ -18,7 +18,7 @@ /** * @author Guillaume Loulier */ -final class TaskLockBagMiddleware implements PostExecutionMiddlewareInterface, OrderedMiddlewareInterface +final class TaskLockBagMiddleware implements PreExecutionMiddlewareInterface, PostExecutionMiddlewareInterface, OrderedMiddlewareInterface { private const TASK_LOCK_MASK = '_symfony_scheduler_foo_'; @@ -31,6 +31,21 @@ public function __construct( $this->logger = $logger ?? new NullLogger(); } + /** + * {@inheritdoc} + */ + public function preExecute(TaskInterface $task): void + { + $key = self::createKey(task: $task); + + $lock = $this->lockFactory->createLockFromKey(key: $key, ttl: null, autoRelease: false); + if (!$lock->acquire()) { + $this->logger->warning(message: sprintf('The lock related to the task "%s" cannot be acquired', $task->getName())); + } + + $task->setAccessLockBag(bag: new AccessLockBag(key: $key)); + } + /** * {@inheritdoc} */ diff --git a/src/Scheduler.php b/src/Scheduler.php index d050ae5f..5255f5a3 100644 --- a/src/Scheduler.php +++ b/src/Scheduler.php @@ -10,6 +10,8 @@ use DateTimeImmutable; use DateTimeZone; use Exception; +use Psr\Log\LoggerInterface; +use Psr\Log\NullLogger; use SchedulerBundle\Event\TaskExecutingEvent; use SchedulerBundle\Exception\InvalidArgumentException; use SchedulerBundle\Messenger\TaskToPauseMessage; @@ -19,8 +21,11 @@ use SchedulerBundle\Pool\Configuration\SchedulerConfiguration; use SchedulerBundle\Task\LazyTask; use SchedulerBundle\Task\LazyTaskList; +use SchedulerBundle\Task\LockedTaskList; use SchedulerBundle\Task\TaskList; use Symfony\Component\EventDispatcher\EventDispatcherInterface; +use Symfony\Component\Lock\Key; +use Symfony\Component\Lock\LockFactory; use Symfony\Component\Messenger\MessageBusInterface; use SchedulerBundle\Event\SchedulerRebootedEvent; use SchedulerBundle\Event\TaskScheduledEvent; @@ -48,12 +53,15 @@ final class Scheduler implements SchedulerInterface /** * @throws Exception {@see DateTimeImmutable::__construct()} + * @throws Exception {@see DateInterval::__construct()} */ public function __construct( string $timezone, private TransportInterface $transport, private SchedulerMiddlewareStack $middlewareStack, private EventDispatcherInterface $eventDispatcher, + private LockFactory $lockFactory, + private ?LoggerInterface $logger = null, private ?MessageBusInterface $bus = null ) { $this->timezone = new DateTimeZone(timezone: $timezone); @@ -61,6 +69,8 @@ public function __construct( $this->minSynchronizationDelay = new DateInterval(duration: 'PT1S'); $this->maxSynchronizationDelay = new DateInterval(duration: 'P1D'); + + $this->logger = $logger ?? new NullLogger(); } /** @@ -123,7 +133,9 @@ public function yieldTask(string $name, bool $async = false): void */ public function preempt(string $taskToPreempt, Closure $filter): void { - $preemptTasks = $this->getDueTasks()->filter(filter: $filter); + $dueTasks = $this->getDueTasks(); + $preemptTasks = $dueTasks->filter(filter: $filter); + if (0 === $preemptTasks->count()) { return; } @@ -188,7 +200,7 @@ public function getTasks(bool $lazy = false): TaskListInterface|LazyTaskList /** * {@inheritdoc} */ - public function getDueTasks(bool $lazy = false, bool $strict = false): TaskListInterface|LazyTaskList + public function getDueTasks(bool $lazy = false, bool $strict = false, bool $lock = false): TaskListInterface|LazyTaskList|LockedTaskList { $synchronizedCurrentDate = $this->getSynchronizedCurrentDate(); @@ -211,7 +223,7 @@ public function getDueTasks(bool $lazy = false, bool $strict = false): TaskListI return $lastExecution->format(format: 'Y-m-d h:i') !== $synchronizedCurrentDate->format(format: 'Y-m-d h:i'); }); - return $dueTasks->filter(filter: static function (TaskInterface $task) use ($synchronizedCurrentDate): bool { + $filteredTasks = $dueTasks->filter(filter: static function (TaskInterface $task) use ($synchronizedCurrentDate): bool { $executionStartDate = $task->getExecutionStartDate(); $executionEndDate = $task->getExecutionEndDate(); @@ -241,6 +253,21 @@ public function getDueTasks(bool $lazy = false, bool $strict = false): TaskListI return true; }); + + if (!$lock) { + return $filteredTasks; + } + + $key = new Key(resource: $synchronizedCurrentDate->format(format: 'Y_m_d_h_i')); + + $lock = $this->lockFactory->createLockFromKey(key: $key, autoRelease: false); + if (!$lock->acquire()) { + $this->logger->warning(message: 'The current task list is already acquired.'); + + return $lazy ? new LazyTaskList(sourceList: new TaskList()) : new TaskList(); + } + + return new LockedTaskList(key: $key, sourceList: $filteredTasks); } /** @@ -261,7 +288,7 @@ public function next(bool $lazy = false): TaskInterface|LazyTask } return $lazy - ? new LazyTask(name: $nextTask->getName(), sourceTaskClosure: Closure::bind(fn (): TaskInterface => $nextTask, $this)) + ? new LazyTask(name: $nextTask->getName(), sourceTaskClosure: Closure::bind(closure: fn (): TaskInterface => $nextTask, newThis: $this)) : $nextTask ; } @@ -271,7 +298,9 @@ public function next(bool $lazy = false): TaskInterface|LazyTask */ public function reboot(): void { - $rebootTasks = $this->getTasks()->filter(filter: static fn (TaskInterface $task): bool => Expression::REBOOT_MACRO === $task->getExpression()); + $tasks = $this->getTasks(); + + $rebootTasks = $tasks->filter(filter: static fn (TaskInterface $task): bool => Expression::REBOOT_MACRO === $task->getExpression()); $this->transport->clear(); @@ -297,7 +326,7 @@ public function getPoolConfiguration(): SchedulerConfiguration { $dueTasks = $this->getDueTasks(); - return new SchedulerConfiguration($this->timezone, $this->getSynchronizedCurrentDate(), ...$dueTasks->toArray(false)); + return new SchedulerConfiguration($this->timezone, $this->getSynchronizedCurrentDate(), ...$dueTasks->toArray(keepKeys: false)); } /** diff --git a/src/SchedulerInterface.php b/src/SchedulerInterface.php index 96ca45b4..956bb6d0 100644 --- a/src/SchedulerInterface.php +++ b/src/SchedulerInterface.php @@ -9,6 +9,7 @@ use SchedulerBundle\Pool\Configuration\SchedulerConfiguration; use SchedulerBundle\Task\LazyTask; use SchedulerBundle\Task\LazyTaskList; +use SchedulerBundle\Task\LockedTaskList; use SchedulerBundle\Task\TaskInterface; use SchedulerBundle\Task\TaskListInterface; use SchedulerBundle\Transport\TransportInterface; @@ -81,16 +82,19 @@ public function resume(string $taskName): void; public function getTasks(bool $lazy = false): TaskListInterface|LazyTaskList; /** - * Allow to retrieve every due tasks, the logic used to build the TaskList is own to the scheduler. + * Allow to retrieve every due tasks, the logic used to build the TaskList its own to the scheduler. * * If the @param bool $lazy is used, the tasks are lazy-loaded. * If the @param bool $strict is used, the current date will assert that the seconds are equals to '00'. + * If the @param bool $lock is used, the tasks are retrieved using a {@see LockedTaskList}, the lock release is up to its consumer. * - * @return TaskListInterface|LazyTaskList + * By default, a {@see LockedTaskList} is returned, if the list cannot be locked, an empty list is returned. + * + * @return TaskListInterface|LazyTaskList|LockedTaskList * * @throws Throwable {@see TransportInterface::list()} */ - public function getDueTasks(bool $lazy = false, bool $strict = false): TaskListInterface|LazyTaskList; + public function getDueTasks(bool $lazy = false, bool $strict = false, bool $lock = false): TaskListInterface|LazyTaskList|LockedTaskList; /** * Return the next task that must be executed (based on {@see SchedulerInterface::getDueTasks()}) diff --git a/src/Task/LockedTaskList.php b/src/Task/LockedTaskList.php new file mode 100644 index 00000000..4dacb7ef --- /dev/null +++ b/src/Task/LockedTaskList.php @@ -0,0 +1,226 @@ + + */ +final class LockedTaskList implements TaskListInterface +{ + public function __construct( + private Key $key, + private TaskListInterface|LazyTaskList $sourceList + ) { + } + + /** + * {@inheritdoc} + */ + public function add(TaskInterface ...$task): void + { + $this->checkIfKeyIsExpired(); + + $this->sourceList->add(...$task); + } + + /** + * {@inheritdoc} + */ + public function has(string $taskName): bool + { + $this->checkIfKeyIsExpired(); + + return $this->sourceList->has(taskName: $taskName); + } + + /** + * {@inheritdoc} + */ + public function get(string $taskName, bool $lazy = false): TaskInterface|LazyTask + { + $this->checkIfKeyIsExpired(); + + return $this->sourceList->get(taskName: $taskName, lazy: $lazy); + } + + /** + * {@inheritdoc} + */ + public function findByName(array $names): TaskListInterface|LazyTaskList + { + $this->checkIfKeyIsExpired(); + + return $this->sourceList->findByName(names: $names); + } + + /** + * {@inheritdoc} + */ + public function filter(Closure $filter): TaskListInterface|LazyTaskList + { + $this->checkIfKeyIsExpired(); + + return $this->sourceList->filter(filter: $filter); + } + + /** + * {@inheritdoc} + */ + public function remove(string $taskName): void + { + $this->checkIfKeyIsExpired(); + + $this->sourceList->remove(taskName: $taskName); + } + + /** + * {@inheritdoc} + */ + public function walk(Closure $func): TaskListInterface|LazyTaskList + { + $this->checkIfKeyIsExpired(); + + return $this->sourceList->walk(func: $func); + } + + /** + * {@inheritdoc} + */ + public function map(Closure $func, bool $keepKeys = true): array + { + $this->checkIfKeyIsExpired(); + + return $this->sourceList->map(func: $func, keepKeys: $keepKeys); + } + + /** + * {@inheritdoc} + */ + public function last(): TaskInterface + { + $this->checkIfKeyIsExpired(); + + return $this->sourceList->last(); + } + + /** + * {@inheritdoc} + */ + public function uasort(Closure $func): TaskListInterface|LazyTaskList + { + $this->checkIfKeyIsExpired(); + + return $this->sourceList->uasort(func: $func); + } + + /** + * {@inheritdoc} + */ + public function chunk(int $size, bool $preserveKeys = false): array + { + $this->checkIfKeyIsExpired(); + + return $this->sourceList->chunk(size: $size, preserveKeys: $preserveKeys); + } + + /** + * {@inheritdoc} + */ + public function slice(string ...$tasks): TaskListInterface|LazyTaskList + { + $this->checkIfKeyIsExpired(); + + return $this->sourceList->slice(...$tasks); + } + + /** + * {@inheritdoc} + */ + public function toArray(bool $keepKeys = true): array + { + $this->checkIfKeyIsExpired(); + + return $this->sourceList->toArray(keepKeys: $keepKeys); + } + + /** + * {@inheritdoc} + */ + public function offsetExists(mixed $offset): bool + { + $this->checkIfKeyIsExpired(); + + return $this->sourceList->offsetExists(offset: $offset); + } + + /** + * {@inheritdoc} + */ + public function offsetGet(mixed $offset): TaskInterface|LazyTask + { + $this->checkIfKeyIsExpired(); + + return $this->sourceList->offsetGet(offset: $offset); + } + + /** + * {@inheritdoc} + */ + public function offsetSet(mixed $offset, mixed $value): void + { + $this->checkIfKeyIsExpired(); + + $this->sourceList->offsetSet(offset: $offset, value: $value); + } + + /** + * {@inheritdoc} + */ + public function offsetUnset(mixed $offset): void + { + $this->checkIfKeyIsExpired(); + + $this->sourceList->offsetUnset(offset: $offset); + } + + /** + * {@inheritdoc} + */ + public function count(): int + { + $this->checkIfKeyIsExpired(); + + return $this->sourceList->count(); + } + + /** + * {@inheritdoc} + */ + public function getIterator(): Traversable + { + $this->checkIfKeyIsExpired(); + + return $this->sourceList->getIterator(); + } + + public function getKey(): Key + { + return $this->key; + } + + private function checkIfKeyIsExpired(): void + { + if (!$this->key->isExpired()) { + return; + } + + throw new RuntimeException(message: 'The current list is expired and cannot be used anymore.'); + } +} diff --git a/src/Task/TaskExecutionTracker.php b/src/Task/TaskExecutionTracker.php index 858f1b33..d376cdcd 100644 --- a/src/Task/TaskExecutionTracker.php +++ b/src/Task/TaskExecutionTracker.php @@ -38,7 +38,7 @@ public function endTracking(TaskInterface $task): void return; } - $task->setExecutionMemoryUsage(memory_get_usage()); + $task->setExecutionMemoryUsage(executionMemoryUsage: memory_get_usage()); if (!$this->watch->isStarted(name: sprintf('task_execution.%s', $task->getName()))) { return; diff --git a/src/Task/TaskList.php b/src/Task/TaskList.php index 140f9205..e753b78c 100644 --- a/src/Task/TaskList.php +++ b/src/Task/TaskList.php @@ -209,7 +209,7 @@ public function offsetExists($offset): bool /** * {@inheritdoc} */ - public function offsetGet($offset): ?TaskInterface + public function offsetGet($offset): TaskInterface|LazyTask { if (!is_string(value: $offset)) { throw new InvalidArgumentException(message: sprintf('The offset must be a string, received "%s"', gettype($offset))); diff --git a/src/Transport/FailOverTransport.php b/src/Transport/FailOverTransport.php index be7ee201..c6ec6454 100644 --- a/src/Transport/FailOverTransport.php +++ b/src/Transport/FailOverTransport.php @@ -26,7 +26,7 @@ public function __construct( ) { $this->failedTransports = new SplObjectStorage(); - parent::__construct($registry, $configuration); + parent::__construct(registry: $registry, configuration: $configuration); } /** @@ -35,23 +35,23 @@ public function __construct( protected function execute(Closure $func) { if (0 === $this->registry->count()) { - throw new TransportException('No transport found'); + throw new TransportException(message: 'No transport found'); } foreach ($this->registry as $transport) { - if ($this->failedTransports->contains($transport)) { + if ($this->failedTransports->contains(object: $transport)) { continue; } try { return $func($transport); } catch (Throwable) { - $this->failedTransports->attach($transport); + $this->failedTransports->attach(object: $transport); continue; } } - throw new TransportException('All the transports failed to execute the requested action'); + throw new TransportException(message: 'All the transports failed to execute the requested action'); } } diff --git a/src/Worker/Worker.php b/src/Worker/Worker.php index 75a300b6..c39df26c 100644 --- a/src/Worker/Worker.php +++ b/src/Worker/Worker.php @@ -25,6 +25,8 @@ use SchedulerBundle\Runner\RunnerRegistryInterface; use SchedulerBundle\SchedulerInterface; use SchedulerBundle\Task\FailedTask; +use SchedulerBundle\Task\LazyTaskList; +use SchedulerBundle\Task\LockedTaskList; use SchedulerBundle\Task\Output; use SchedulerBundle\Task\TaskExecutionTrackerInterface; use SchedulerBundle\Task\TaskInterface; @@ -37,6 +39,8 @@ use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; use Throwable; use function in_array; +use function sleep; +use function sprintf; /** * @author Guillaume Loulier @@ -78,7 +82,7 @@ public function execute(WorkerConfiguration $configuration, TaskInterface ...$ta try { $executionPolicy = $this->executionPolicyRegistry->find(policy: $configuration->getExecutionPolicy()); } catch (Throwable $throwable) { - $this->logger->critical(sprintf('The tasks cannot be executed, an error occurred while retrieving the execution policy: %s', $throwable->getMessage())); + $this->logger->critical(message: sprintf('The tasks cannot be executed, an error occurred while retrieving the execution policy: %s', $throwable->getMessage())); return; } @@ -93,6 +97,11 @@ public function execute(WorkerConfiguration $configuration, TaskInterface ...$ta $this->handleTask(task: $task, taskList: $taskList); }); + if ($toExecuteTasks instanceof LockedTaskList) { + $postExecutionLock = $this->lockFactory->createLockFromKey(key: $toExecuteTasks->getKey()); + $postExecutionLock->release(); + } + if ($this->shouldStop(taskList: $toExecuteTasks)) { break; } @@ -118,7 +127,7 @@ public function preempt(TaskListInterface $preemptTaskList, TaskListInterface $t $lock = $this->lockFactory->createLockFromKey( key: $accessLockBag instanceof AccessLockBag && $accessLockBag->getKey() instanceof Key ? $accessLockBag->getKey() - : TaskLockBagMiddleware::createKey($task) + : TaskLockBagMiddleware::createKey(task: $task) ); $lock->release(); @@ -241,28 +250,15 @@ public function getConfiguration(): WorkerConfiguration * * @throws Throwable {@see SchedulerInterface::getDueTasks()} */ - protected function getTasks(array $tasks): TaskListInterface + protected function getTasks(array $tasks): TaskListInterface|LazyTaskList|LockedTaskList { $tasks = [] !== $tasks ? new TaskList(tasks: $tasks) : $this->scheduler->getDueTasks( lazy: $this->configuration->shouldRetrieveTasksLazily(), - strict: $this->configuration->isStrictlyCheckingDate() + strict: $this->configuration->isStrictlyCheckingDate(), + lock: $this->configuration->shouldLockTasks() ); - $lockedTasks = $tasks->filter(filter: function (TaskInterface $task): bool { - $key = TaskLockBagMiddleware::createKey(task: $task); - $task->setAccessLockBag(bag: new AccessLockBag(key: $key)); - - $lock = $this->lockFactory->createLockFromKey(key: $key, ttl: null, autoRelease: false); - if (!$lock->acquire()) { - $this->logger->info(sprintf('The lock related to the task "%s" cannot be acquired', $task->getName())); - - return false; - } - - return true; - }); - - return $lockedTasks->filter(filter: fn (TaskInterface $task): bool => $this->checkTaskState(task: $task)); + return $tasks->filter(filter: fn (TaskInterface $task): bool => $this->checkTaskState(task: $task)); } protected function handleTask(TaskInterface $task, TaskListInterface $taskList): void @@ -338,7 +334,7 @@ private function checkTaskState(TaskInterface $task): bool } if (in_array(needle: $task->getState(), haystack: [TaskInterface::PAUSED, TaskInterface::DISABLED], strict: true)) { - $this->logger->info(sprintf('The following task "%s" is paused|disabled, consider enable it if it should be executed!', $task->getName()), [ + $this->logger->info(message: sprintf('The following task "%s" is paused|disabled, consider enable it if it should be executed!', $task->getName()), context: [ 'name' => $task->getName(), 'expression' => $task->getExpression(), 'state' => $task->getState(), @@ -356,7 +352,7 @@ private function checkTaskState(TaskInterface $task): bool private function getSleepDuration(): int { $dateTimeImmutable = new DateTimeImmutable(datetime: '+ 1 minute', timezone: $this->scheduler->getTimezone()); - $updatedNextExecutionDate = $dateTimeImmutable->setTime(hour: (int) $dateTimeImmutable->format('H'), minute: (int) $dateTimeImmutable->format('i')); + $updatedNextExecutionDate = $dateTimeImmutable->setTime(hour: (int) $dateTimeImmutable->format(format: 'H'), minute: (int) $dateTimeImmutable->format(format: 'i')); return (new DateTimeImmutable(datetime: 'now', timezone: $this->scheduler->getTimezone()))->diff(targetObject: $updatedNextExecutionDate)->s + $this->configuration->getSleepDurationDelay(); } diff --git a/src/Worker/WorkerConfiguration.php b/src/Worker/WorkerConfiguration.php index 90813936..0799559c 100644 --- a/src/Worker/WorkerConfiguration.php +++ b/src/Worker/WorkerConfiguration.php @@ -23,6 +23,7 @@ final class WorkerConfiguration private bool $mustStrictlyCheckDate; private ?TaskInterface $currentlyExecutedTask = null; private string $executionPolicy; + private bool $shouldLockTasks; private function __construct() { @@ -43,6 +44,7 @@ public static function create(): self $self->lastExecutedTask = null; $self->forkedFrom = null; $self->mustStrictlyCheckDate = false; + $self->shouldLockTasks = false; $self->executionPolicy = 'default'; return $self; @@ -168,6 +170,16 @@ public function isStrictlyCheckingDate(): bool return $this->mustStrictlyCheckDate; } + public function shouldLockTasks(): bool + { + return $this->shouldLockTasks; + } + + public function lockTask(bool $lock): void + { + $this->shouldLockTasks = $lock; + } + /** * @return array */ diff --git a/tests/AbstractSchedulerTestCase.php b/tests/AbstractSchedulerTestCase.php index 4c555c96..d38fe584 100644 --- a/tests/AbstractSchedulerTestCase.php +++ b/tests/AbstractSchedulerTestCase.php @@ -4,6 +4,7 @@ namespace Tests\SchedulerBundle; +use DateTimeImmutable; use DateTimeZone; use Exception; use PHPUnit\Framework\TestCase; @@ -11,7 +12,9 @@ use SchedulerBundle\LazyScheduler; use SchedulerBundle\Scheduler; use SchedulerBundle\SchedulerInterface; +use SchedulerBundle\Task\LazyTask; use SchedulerBundle\Task\NullTask; +use SchedulerBundle\Task\TaskInterface; use Throwable; /** @@ -64,6 +67,93 @@ public function testSchedulerCanReturnTheTimezone(): void self::assertSame(expected: 'UTC', actual: $timezone->getName()); } + /** + * @throws Throwable {@see Scheduler::__construct()} + * @throws Throwable {@see SchedulerInterface::schedule()} + * @throws Throwable {@see SchedulerInterface::getDueTasks()} + */ + public function testSchedulerCanReturnNextDueTask(): void + { + $scheduler = $this->getScheduler(); + + $scheduler->schedule(task: new NullTask(name: 'foo')); + $scheduler->schedule(task: new NullTask(name: 'bar')); + + self::assertCount(expectedCount: 2, haystack: $scheduler->getDueTasks()); + + $nextDueTask = $scheduler->next(); + self::assertInstanceOf(expected: NullTask::class, actual: $nextDueTask); + self::assertSame(expected: 'bar', actual: $nextDueTask->getName()); + } + + /** + * @throws Throwable {@see Scheduler::__construct()} + * @throws Throwable {@see SchedulerInterface::schedule()} + * @throws Throwable {@see SchedulerInterface::getDueTasks()} + */ + public function testSchedulerCanReturnNextDueTaskAsynchronously(): void + { + $scheduler = $this->getScheduler(); + + $scheduler->schedule(task: new NullTask(name: 'foo')); + $scheduler->schedule(task: new NullTask(name: 'bar')); + + $nextDueTask = $scheduler->next(lazy: true); + self::assertInstanceOf(expected: LazyTask::class, actual: $nextDueTask); + self::assertFalse(condition: $nextDueTask->isInitialized()); + self::assertSame(expected: 'bar.lazy', actual: $nextDueTask->getName()); + + $task = $nextDueTask->getTask(); + self::assertTrue(condition: $nextDueTask->isInitialized()); + self::assertInstanceOf(expected: NullTask::class, actual: $task); + self::assertSame(expected: 'bar', actual: $task->getName()); + } + + /** + * @throws Throwable {@see Scheduler::__construct()} + */ + public function testSchedulerCanRebootWithEmptyTasks(): void + { + $scheduler = $this->getScheduler(); + + $scheduler->schedule(task: new NullTask(name: 'bar')); + self::assertCount(expectedCount: 1, haystack: $scheduler->getTasks()); + + $scheduler->reboot(); + self::assertCount(expectedCount: 0, haystack: $scheduler->getTasks()); + } + + /** + * @throws Throwable {@see Scheduler::__construct()} + */ + public function testSchedulerCanReboot(): void + { + $scheduler = $this->getScheduler(); + $scheduler->schedule(task: new NullTask(name: 'foo', options: [ + 'expression' => '@reboot', + ])); + + $scheduler->schedule(task: new NullTask(name: 'bar')); + self::assertCount(expectedCount: 2, haystack: $scheduler->getTasks()); + + $scheduler->reboot(); + self::assertCount(expectedCount: 1, haystack: $scheduler->getTasks()); + } + + /** + * @throws Throwable {@see Scheduler::__construct()} + * @throws Throwable {@see SchedulerInterface::schedule()} + */ + public function testSchedulerCannotPreemptEmptyDueTasks(): void + { + $task = new NullTask(name: 'foo'); + + $scheduler = $this->getScheduler(); + + $scheduler->preempt(taskToPreempt: 'foo', filter: static fn (TaskInterface $task): bool => $task->getName() === 'bar'); + self::assertNotSame(expected: TaskInterface::READY_TO_EXECUTE, actual: $task->getState()); + } + /** * @throws Exception {@see Scheduler::__construct()} * @throws Throwable {@see SchedulerInterface::getPoolConfiguration()} diff --git a/tests/Command/ConsumeTasksCommandTest.php b/tests/Command/ConsumeTasksCommandTest.php index dcfb6c13..08b025d2 100644 --- a/tests/Command/ConsumeTasksCommandTest.php +++ b/tests/Command/ConsumeTasksCommandTest.php @@ -184,7 +184,7 @@ public function testCommandCanConsumeTasks(): void $scheduler = new Scheduler('UTC', new InMemoryTransport(new InMemoryConfiguration(), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), $eventDispatcher); + ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), $eventDispatcher, new LockFactory(new InMemoryStore())); $scheduler->schedule(new NullTask('foo')); @@ -211,7 +211,7 @@ public function testCommandCanConsumeTasksUsingLazyLoading(): void $scheduler = new Scheduler('UTC', new InMemoryTransport(new InMemoryConfiguration(), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), $eventDispatcher); + ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), $eventDispatcher, new LockFactory(new InMemoryStore())); $scheduler->schedule(new NullTask('foo')); @@ -621,7 +621,7 @@ public function testCommandCanWaitForTasksWithoutPauseFilter(): void $scheduler = new Scheduler('UTC', new InMemoryTransport(new InMemoryConfiguration(), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), $eventDispatcher); + ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), $eventDispatcher, new LockFactory(new InMemoryStore())); $scheduler->schedule(new NullTask('foo')); @@ -652,7 +652,7 @@ public function testCommandCanAskForStrictDateCheckWithoutDueTasks(): void $scheduler = new Scheduler('UTC', new InMemoryTransport(new InMemoryConfiguration(), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), $eventDispatcher); + ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), $eventDispatcher, new LockFactory(new InMemoryStore())); $scheduler->schedule(new NullTask('foo')); diff --git a/tests/Command/DebugMiddlewareCommandTest.php b/tests/Command/DebugMiddlewareCommandTest.php index d072f34d..3a3b069a 100644 --- a/tests/Command/DebugMiddlewareCommandTest.php +++ b/tests/Command/DebugMiddlewareCommandTest.php @@ -123,7 +123,7 @@ public function testCommandCanDisplayExecutionPhaseMiddlewareList(): void self::assertStringContainsString('Required', $tester->getDisplay()); self::assertStringContainsString('No', $tester->getDisplay()); self::assertStringContainsString('| TaskCallbackMiddleware | Yes | Yes | 1 | No |', $tester->getDisplay()); - self::assertStringContainsString('| TaskLockBagMiddleware | No | Yes | 5 | No |', $tester->getDisplay()); + self::assertStringContainsString('| TaskLockBagMiddleware | Yes | Yes | 5 | No |', $tester->getDisplay()); self::assertStringContainsString('| SingleRunTaskMiddleware | No | Yes | 15 | Yes |', $tester->getDisplay()); self::assertStringContainsString('| PostExecutionMiddleware | No | Yes | No | No |', $tester->getDisplay()); self::assertStringContainsString('| PreExecutionMiddleware | Yes | No | No | No |', $tester->getDisplay()); diff --git a/tests/Command/ExecuteTaskCommandTest.php b/tests/Command/ExecuteTaskCommandTest.php index fda1fadc..4f3125b4 100644 --- a/tests/Command/ExecuteTaskCommandTest.php +++ b/tests/Command/ExecuteTaskCommandTest.php @@ -7,23 +7,32 @@ use PHPUnit\Framework\TestCase; use Psr\EventDispatcher\EventDispatcherInterface; use Psr\Log\LoggerInterface; +use Psr\Log\NullLogger; use SchedulerBundle\Command\ExecuteTaskCommand; use SchedulerBundle\EventListener\StopWorkerOnTaskLimitSubscriber; use SchedulerBundle\Middleware\SchedulerMiddlewareStack; +use SchedulerBundle\Middleware\WorkerMiddlewareStack; +use SchedulerBundle\Runner\RunnerRegistry; use SchedulerBundle\SchedulePolicy\FirstInFirstOutPolicy; use SchedulerBundle\SchedulePolicy\SchedulePolicyOrchestrator; use SchedulerBundle\Scheduler; use SchedulerBundle\SchedulerInterface; use SchedulerBundle\Task\NullTask; +use SchedulerBundle\Task\TaskExecutionTracker; use SchedulerBundle\Task\TaskList; use SchedulerBundle\Transport\Configuration\InMemoryConfiguration; use SchedulerBundle\Transport\InMemoryTransport; +use SchedulerBundle\Worker\ExecutionPolicy\ExecutionPolicyRegistry; +use SchedulerBundle\Worker\Worker; use SchedulerBundle\Worker\WorkerConfiguration; use SchedulerBundle\Worker\WorkerInterface; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Tester\CommandCompletionTester; use Symfony\Component\Console\Tester\CommandTester; use Symfony\Component\EventDispatcher\EventDispatcher; +use Symfony\Component\Lock\LockFactory; +use Symfony\Component\Lock\Store\InMemoryStore; +use Symfony\Component\Stopwatch\Stopwatch; use Throwable; /** @@ -31,11 +40,27 @@ */ final class ExecuteTaskCommandTest extends TestCase { + /** + * @throws Throwable {@see Scheduler::__construct()} + */ public function testCommandIsConfigured(): void { - $eventDispatcher = $this->createMock(EventDispatcherInterface::class); - $scheduler = $this->createMock(SchedulerInterface::class); - $worker = $this->createMock(WorkerInterface::class); + $eventDispatcher = new EventDispatcher(); + + $scheduler = new Scheduler(timezone: 'UTC', transport: new InMemoryTransport(configuration: new InMemoryConfiguration(), schedulePolicyOrchestrator: new SchedulePolicyOrchestrator(policies: [ + new FirstInFirstOutPolicy(), + ])), middlewareStack: new SchedulerMiddlewareStack([]), eventDispatcher: $eventDispatcher, lockFactory: new LockFactory(store: new InMemoryStore())); + + $worker = new Worker( + $scheduler, + new RunnerRegistry([]), + new ExecutionPolicyRegistry([]), + new TaskExecutionTracker(new Stopwatch()), + new WorkerMiddlewareStack(), + new EventDispatcher(), + new LockFactory(new InMemoryStore()), + new NullLogger() + ); $command = new ExecuteTaskCommand($eventDispatcher, $scheduler, $worker); @@ -90,11 +115,20 @@ public function testCommandCanSuggestStoredTasksPerName(): void { $scheduler = new Scheduler(timezone: 'UTC', transport: new InMemoryTransport(configuration: new InMemoryConfiguration(), schedulePolicyOrchestrator: new SchedulePolicyOrchestrator(policies: [ new FirstInFirstOutPolicy(), - ])), middlewareStack: new SchedulerMiddlewareStack([]), eventDispatcher: new EventDispatcher()); + ])), middlewareStack: new SchedulerMiddlewareStack([]), eventDispatcher: new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())); $scheduler->schedule(task: new NullTask(name: 'foo')); $scheduler->schedule(task: new NullTask(name: 'bar')); - $worker = $this->createMock(WorkerInterface::class); + $worker = new Worker( + $scheduler, + new RunnerRegistry([]), + new ExecutionPolicyRegistry([]), + new TaskExecutionTracker(new Stopwatch()), + new WorkerMiddlewareStack(), + new EventDispatcher(), + new LockFactory(new InMemoryStore()), + new NullLogger() + ); $tester = new CommandCompletionTester(command: new ExecuteTaskCommand(eventDispatcher: new EventDispatcher(), scheduler: $scheduler, worker: $worker)); $suggestions = $tester->complete(input: ['--name', 'f']); @@ -111,11 +145,20 @@ public function testCommandCanSuggestStoredTasksPerExpression(): void { $scheduler = new Scheduler(timezone: 'UTC', transport: new InMemoryTransport(configuration: new InMemoryConfiguration(), schedulePolicyOrchestrator: new SchedulePolicyOrchestrator(policies: [ new FirstInFirstOutPolicy(), - ])), middlewareStack: new SchedulerMiddlewareStack([]), eventDispatcher: new EventDispatcher()); + ])), middlewareStack: new SchedulerMiddlewareStack([]), eventDispatcher: new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())); $scheduler->schedule(task: new NullTask(name: 'foo')); $scheduler->schedule(task: new NullTask(name: 'bar')); - $worker = $this->createMock(WorkerInterface::class); + $worker = new Worker( + $scheduler, + new RunnerRegistry([]), + new ExecutionPolicyRegistry([]), + new TaskExecutionTracker(new Stopwatch()), + new WorkerMiddlewareStack(), + new EventDispatcher(), + new LockFactory(new InMemoryStore()), + new NullLogger() + ); $tester = new CommandCompletionTester(command: new ExecuteTaskCommand(eventDispatcher: new EventDispatcher(), scheduler: $scheduler, worker: $worker)); $suggestions = $tester->complete(input: ['--expression', '* * * * *']); @@ -132,7 +175,7 @@ public function testCommandCanSuggestStoredTasksPerTag(): void { $scheduler = new Scheduler(timezone: 'UTC', transport: new InMemoryTransport(configuration: new InMemoryConfiguration(), schedulePolicyOrchestrator: new SchedulePolicyOrchestrator(policies: [ new FirstInFirstOutPolicy(), - ])), middlewareStack: new SchedulerMiddlewareStack([]), eventDispatcher: new EventDispatcher()); + ])), middlewareStack: new SchedulerMiddlewareStack([]), eventDispatcher: new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())); $scheduler->schedule(task: new NullTask(name: 'foo', options: [ 'tags' => ['random'], ])); @@ -140,7 +183,16 @@ public function testCommandCanSuggestStoredTasksPerTag(): void 'tags' => ['second_random'], ])); - $worker = $this->createMock(WorkerInterface::class); + $worker = new Worker( + $scheduler, + new RunnerRegistry([]), + new ExecutionPolicyRegistry([]), + new TaskExecutionTracker(new Stopwatch()), + new WorkerMiddlewareStack(), + new EventDispatcher(), + new LockFactory(new InMemoryStore()), + new NullLogger() + ); $tester = new CommandCompletionTester(command: new ExecuteTaskCommand(eventDispatcher: new EventDispatcher(), scheduler: $scheduler, worker: $worker)); $suggestions = $tester->complete(input: ['--tags', 'random']); @@ -149,16 +201,29 @@ public function testCommandCanSuggestStoredTasksPerTag(): void self::assertSame(expected: ['random', 'second_random'], actual: $suggestions); } + /** + * @throws Throwable {@see Scheduler::__construct()} + */ public function testCommandCannotExecuteDueTasks(): void { - $worker = $this->createMock(WorkerInterface::class); + $scheduler = new Scheduler(timezone: 'UTC', transport: new InMemoryTransport(configuration: new InMemoryConfiguration(), schedulePolicyOrchestrator: new SchedulePolicyOrchestrator(policies: [ + new FirstInFirstOutPolicy(), + ])), middlewareStack: new SchedulerMiddlewareStack([]), eventDispatcher: new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())); + + $worker = new Worker( + $scheduler, + new RunnerRegistry([]), + new ExecutionPolicyRegistry([]), + new TaskExecutionTracker(new Stopwatch()), + new WorkerMiddlewareStack(), + new EventDispatcher(), + new LockFactory(new InMemoryStore()), + new NullLogger() + ); $eventDispatcher = $this->createMock(EventDispatcherInterface::class); $eventDispatcher->expects(self::never())->method('dispatch'); - $scheduler = $this->createMock(SchedulerInterface::class); - $scheduler->expects(self::once())->method('getDueTasks')->willReturn(new TaskList()); - $command = new ExecuteTaskCommand($eventDispatcher, $scheduler, $worker); $tester = new CommandTester($command); $tester->execute([ diff --git a/tests/Command/ListTasksCommandTest.php b/tests/Command/ListTasksCommandTest.php index d9d99f6b..76aef547 100644 --- a/tests/Command/ListTasksCommandTest.php +++ b/tests/Command/ListTasksCommandTest.php @@ -23,6 +23,8 @@ use SchedulerBundle\Task\TaskInterface; use SchedulerBundle\Task\TaskList; use Symfony\Component\EventDispatcher\EventDispatcher; +use Symfony\Component\Lock\LockFactory; +use Symfony\Component\Lock\Store\InMemoryStore; use Throwable; /** @@ -30,9 +32,15 @@ */ final class ListTasksCommandTest extends TestCase { + /** + * @throws Throwable {@see Scheduler::__construct()} + */ public function testCommandIsCorrectlyConfigured(): void { - $scheduler = $this->createMock(SchedulerInterface::class); + $scheduler = new Scheduler(timezone: 'UTC', transport: new InMemoryTransport(configuration: new InMemoryConfiguration(), schedulePolicyOrchestrator: new SchedulePolicyOrchestrator(policies: [ + new FirstInFirstOutPolicy(), + ])), middlewareStack: new SchedulerMiddlewareStack([]), eventDispatcher: new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())); + $listTasksCommand = new ListTasksCommand(scheduler: $scheduler); self::assertSame('scheduler:list', $listTasksCommand->getName()); @@ -70,7 +78,7 @@ public function testCommandCanSuggestStoredTasksPerExpression(): void { $scheduler = new Scheduler(timezone: 'UTC', transport: new InMemoryTransport(configuration: new InMemoryConfiguration(), schedulePolicyOrchestrator: new SchedulePolicyOrchestrator(policies: [ new FirstInFirstOutPolicy(), - ])), middlewareStack: new SchedulerMiddlewareStack([]), eventDispatcher: new EventDispatcher()); + ])), middlewareStack: new SchedulerMiddlewareStack([]), eventDispatcher: new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())); $scheduler->schedule(task: new NullTask(name: 'foo')); $scheduler->schedule(task: new NullTask(name: 'bar')); @@ -92,7 +100,7 @@ public function testCommandCanSuggestStoredTasksPerState(): void { $scheduler = new Scheduler(timezone: 'UTC', transport: new InMemoryTransport(configuration: new InMemoryConfiguration(), schedulePolicyOrchestrator: new SchedulePolicyOrchestrator(policies: [ new FirstInFirstOutPolicy(), - ])), middlewareStack: new SchedulerMiddlewareStack([]), eventDispatcher: new EventDispatcher()); + ])), middlewareStack: new SchedulerMiddlewareStack([]), eventDispatcher: new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())); $scheduler->schedule(task: new NullTask(name: 'foo')); $scheduler->schedule(task: new NullTask(name: 'bar')); @@ -113,7 +121,7 @@ public function testCommandCannotReturnTaskOnEmptyScheduler(): void { $scheduler = new Scheduler(timezone: 'UTC', transport: new InMemoryTransport(configuration: new InMemoryConfiguration(), schedulePolicyOrchestrator: new SchedulePolicyOrchestrator(policies: [ new FirstInFirstOutPolicy(), - ])), middlewareStack: new SchedulerMiddlewareStack([]), eventDispatcher: new EventDispatcher()); + ])), middlewareStack: new SchedulerMiddlewareStack([]), eventDispatcher: new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())); $commandTester = new CommandTester(command: new ListTasksCommand(scheduler: $scheduler)); $commandTester->execute(input: []); @@ -403,15 +411,19 @@ public function testCommandCanReturnTasksWithStateAndExpressionFilter(string $ex self::assertStringContainsString('fast', $commandTester->getDisplay()); } + /** + * @throws Throwable {@see Scheduler::__construct()} + * @throws Throwable {@see SchedulerInterface::schedule()} + */ public function testCommandCanReturnTasksWithInvalidExpressionFilter(): void { - $scheduler = $this->createMock(SchedulerInterface::class); - $scheduler->expects(self::once())->method('getTasks')->willReturn(new TaskList([ - new NullTask('foo'), - ])); + $scheduler = new Scheduler(timezone: 'UTC', transport: new InMemoryTransport(configuration: new InMemoryConfiguration(), schedulePolicyOrchestrator: new SchedulePolicyOrchestrator(policies: [ + new FirstInFirstOutPolicy(), + ])), middlewareStack: new SchedulerMiddlewareStack([]), eventDispatcher: new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())); + $scheduler->schedule(task: new NullTask(name: 'foo')); - $commandTester = new CommandTester(new ListTasksCommand($scheduler)); - $commandTester->execute([ + $commandTester = new CommandTester(command: new ListTasksCommand(scheduler: $scheduler)); + $commandTester->execute(input: [ '--expression' => '0 * * * *', ]); @@ -419,15 +431,19 @@ public function testCommandCanReturnTasksWithInvalidExpressionFilter(): void self::assertStringContainsString('[WARNING] No tasks found', $commandTester->getDisplay()); } + /** + * @throws Throwable {@see Scheduler::__construct()} + * @throws Throwable {@see SchedulerInterface::schedule()} + */ public function testCommandCanReturnTasksWithInvalidStateFilter(): void { - $scheduler = $this->createMock(SchedulerInterface::class); - $scheduler->expects(self::once())->method('getTasks')->willReturn(new TaskList([ - new NullTask('foo'), - ])); + $scheduler = new Scheduler(timezone: 'UTC', transport: new InMemoryTransport(configuration: new InMemoryConfiguration(), schedulePolicyOrchestrator: new SchedulePolicyOrchestrator(policies: [ + new FirstInFirstOutPolicy(), + ])), middlewareStack: new SchedulerMiddlewareStack([]), eventDispatcher: new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())); + $scheduler->schedule(task: new NullTask(name: 'foo')); - $commandTester = new CommandTester(new ListTasksCommand($scheduler)); - $commandTester->execute([ + $commandTester = new CommandTester(command: new ListTasksCommand(scheduler: $scheduler)); + $commandTester->execute(input: [ '--state' => 'test', ]); @@ -443,7 +459,7 @@ public function testCommandCanReturnTasksWithInvalidStateAndExpressionFilter(): { $scheduler = new Scheduler(timezone: 'UTC', transport: new InMemoryTransport(configuration: new InMemoryConfiguration(), schedulePolicyOrchestrator: new SchedulePolicyOrchestrator(policies: [ new FirstInFirstOutPolicy(), - ])), middlewareStack: new SchedulerMiddlewareStack([]), eventDispatcher: new EventDispatcher()); + ])), middlewareStack: new SchedulerMiddlewareStack([]), eventDispatcher: new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())); $scheduler->schedule(task: new NullTask(name: 'foo')); $commandTester = new CommandTester(command: new ListTasksCommand(scheduler: $scheduler)); diff --git a/tests/Command/RemoveFailedTaskCommandTest.php b/tests/Command/RemoveFailedTaskCommandTest.php index 99256b0d..fc35f8c5 100644 --- a/tests/Command/RemoveFailedTaskCommandTest.php +++ b/tests/Command/RemoveFailedTaskCommandTest.php @@ -21,6 +21,9 @@ use SchedulerBundle\SchedulerInterface; use SchedulerBundle\Worker\WorkerInterface; use Symfony\Component\EventDispatcher\EventDispatcher; +use Symfony\Component\Lock\LockFactory; +use Symfony\Component\Lock\Store\InMemoryStore; +use Throwable; /** * @author Guillaume Loulier @@ -34,7 +37,7 @@ public function testCommandIsConfigured(): void { $scheduler = new Scheduler(timezone: 'UTC', transport: new InMemoryTransport(configuration: new InMemoryConfiguration(), schedulePolicyOrchestrator: new SchedulePolicyOrchestrator(policies: [ new FirstInFirstOutPolicy(), - ])), middlewareStack: new SchedulerMiddlewareStack([]), eventDispatcher: new EventDispatcher()); + ])), middlewareStack: new SchedulerMiddlewareStack([]), eventDispatcher: new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())); $worker = $this->createMock(originalClassName: WorkerInterface::class); @@ -71,7 +74,7 @@ public function testCommandCanSuggestFailedTasks(): void { $scheduler = new Scheduler(timezone: 'UTC', transport: new InMemoryTransport(configuration: new InMemoryConfiguration(), schedulePolicyOrchestrator: new SchedulePolicyOrchestrator(policies: [ new FirstInFirstOutPolicy(), - ])), middlewareStack: new SchedulerMiddlewareStack([]), eventDispatcher: new EventDispatcher()); + ])), middlewareStack: new SchedulerMiddlewareStack([]), eventDispatcher: new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())); $worker = $this->createMock(originalClassName: WorkerInterface::class); $worker->expects(self::once())->method('getFailedTasks')->willReturn(new TaskList(tasks: [ @@ -87,9 +90,14 @@ public function testCommandCanSuggestFailedTasks(): void self::assertSame(['foo', 'bar'], $suggestions); } + /** + * @throws Throwable {@see Scheduler::__construct()} + */ public function testCommandCannotRemoveUndefinedTask(): void { - $scheduler = $this->createMock(SchedulerInterface::class); + $scheduler = new Scheduler(timezone: 'UTC', transport: new InMemoryTransport(configuration: new InMemoryConfiguration(), schedulePolicyOrchestrator: new SchedulePolicyOrchestrator(policies: [ + new FirstInFirstOutPolicy(), + ])), middlewareStack: new SchedulerMiddlewareStack([]), eventDispatcher: new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())); $worker = $this->createMock(WorkerInterface::class); $worker->expects(self::once())->method('getFailedTasks')->willReturn(new TaskList()); @@ -126,10 +134,18 @@ public function testCommandCannotRemoveTaskWithException(): void self::assertStringContainsString('Random error', $commandTester->getDisplay()); } + /** + * @throws Throwable {@see Scheduler::__construct()} + * @throws Throwable {@see SchedulerInterface::schedule()} + */ public function testCommandCannotRemoveWithoutConfirmationOrForceOption(): void { - $scheduler = $this->createMock(SchedulerInterface::class); - $scheduler->expects(self::never())->method('unschedule'); + $task = new NullTask('foo'); + + $scheduler = new Scheduler(timezone: 'UTC', transport: new InMemoryTransport(configuration: new InMemoryConfiguration(), schedulePolicyOrchestrator: new SchedulePolicyOrchestrator(policies: [ + new FirstInFirstOutPolicy(), + ])), middlewareStack: new SchedulerMiddlewareStack([]), eventDispatcher: new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())); + $scheduler->schedule($task); $worker = $this->createMock(WorkerInterface::class); $worker->expects(self::once())->method('getFailedTasks')->willReturn(new TaskList([ @@ -146,14 +162,22 @@ public function testCommandCannotRemoveWithoutConfirmationOrForceOption(): void self::assertStringContainsString('[NOTE] The task "foo" has not been unscheduled', $commandTester->getDisplay()); } + /** + * @throws Throwable {@see Scheduler::__construct()} + * @throws Throwable {@see SchedulerInterface::schedule()} + */ public function testCommandCanRemoveTaskWithForceOption(): void { - $scheduler = $this->createMock(SchedulerInterface::class); - $scheduler->expects(self::once())->method('unschedule'); + $task = new NullTask('foo'); + + $scheduler = new Scheduler(timezone: 'UTC', transport: new InMemoryTransport(configuration: new InMemoryConfiguration(), schedulePolicyOrchestrator: new SchedulePolicyOrchestrator(policies: [ + new FirstInFirstOutPolicy(), + ])), middlewareStack: new SchedulerMiddlewareStack([]), eventDispatcher: new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())); + $scheduler->schedule($task); $worker = $this->createMock(WorkerInterface::class); $worker->expects(self::once())->method('getFailedTasks')->willReturn(new TaskList([ - new NullTask('foo'), + $task, ])); $removeFailedTaskCommand = new RemoveFailedTaskCommand($scheduler, $worker); @@ -167,14 +191,22 @@ public function testCommandCanRemoveTaskWithForceOption(): void self::assertStringContainsString('[OK] The task "foo" has been unscheduled', $commandTester->getDisplay()); } + /** + * @throws Throwable {@see Scheduler::__construct()} + * @throws Throwable {@see SchedulerInterface::schedule()} + */ public function testCommandCanRemoveTask(): void { - $scheduler = $this->createMock(SchedulerInterface::class); - $scheduler->expects(self::once())->method('unschedule'); + $task = new NullTask('foo'); + + $scheduler = new Scheduler(timezone: 'UTC', transport: new InMemoryTransport(configuration: new InMemoryConfiguration(), schedulePolicyOrchestrator: new SchedulePolicyOrchestrator(policies: [ + new FirstInFirstOutPolicy(), + ])), middlewareStack: new SchedulerMiddlewareStack([]), eventDispatcher: new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())); + $scheduler->schedule($task); $worker = $this->createMock(WorkerInterface::class); $worker->expects(self::once())->method('getFailedTasks')->willReturn(new TaskList([ - new NullTask('foo'), + $task, ])); $removeFailedTaskCommand = new RemoveFailedTaskCommand($scheduler, $worker); diff --git a/tests/Command/YieldTaskCommandTest.php b/tests/Command/YieldTaskCommandTest.php index 591e1e9e..dcd5d8dd 100644 --- a/tests/Command/YieldTaskCommandTest.php +++ b/tests/Command/YieldTaskCommandTest.php @@ -18,6 +18,8 @@ use Symfony\Component\Console\Tester\CommandCompletionTester; use Symfony\Component\Console\Tester\CommandTester; use Symfony\Component\EventDispatcher\EventDispatcher; +use Symfony\Component\Lock\LockFactory; +use Symfony\Component\Lock\Store\InMemoryStore; use Throwable; /** @@ -25,25 +27,30 @@ */ final class YieldTaskCommandTest extends TestCase { + /** + * @throws Throwable {@see Scheduler::__construct()} + */ public function testCommandIsConfigured(): void { - $scheduler = $this->createMock(SchedulerInterface::class); - - $yieldTaskCommand = new YieldTaskCommand($scheduler); - - self::assertSame('scheduler:yield', $yieldTaskCommand->getName()); - self::assertSame('Yield a task', $yieldTaskCommand->getDescription()); - self::assertTrue($yieldTaskCommand->getDefinition()->hasArgument('name')); - self::assertSame('The task to yield', $yieldTaskCommand->getDefinition()->getArgument('name')->getDescription()); - self::assertTrue($yieldTaskCommand->getDefinition()->getArgument('name')->isRequired()); - self::assertTrue($yieldTaskCommand->getDefinition()->hasOption('async')); - self::assertSame('Yield the task using the message bus', $yieldTaskCommand->getDefinition()->getOption('async')->getDescription()); - self::assertSame('a', $yieldTaskCommand->getDefinition()->getOption('async')->getShortcut()); - self::assertTrue($yieldTaskCommand->getDefinition()->hasOption('force')); - self::assertSame('Force the operation without confirmation', $yieldTaskCommand->getDefinition()->getOption('force')->getDescription()); - self::assertSame('f', $yieldTaskCommand->getDefinition()->getOption('force')->getShortcut()); + $yieldTaskCommand = new YieldTaskCommand(scheduler: new Scheduler(timezone: 'UTC', transport: new InMemoryTransport(configuration: new InMemoryConfiguration(), schedulePolicyOrchestrator: new SchedulePolicyOrchestrator(policies: [ + new FirstInFirstOutPolicy(), + ])), middlewareStack: new SchedulerMiddlewareStack(), eventDispatcher: new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore()))); + + self::assertSame(expected: 'scheduler:yield', actual: $yieldTaskCommand->getName()); + self::assertSame(expected: 'Yield a task', actual: $yieldTaskCommand->getDescription()); + self::assertTrue(condition: $yieldTaskCommand->getDefinition()->hasArgument(name: 'name')); + self::assertSame(expected: 'The task to yield', actual: $yieldTaskCommand->getDefinition()->getArgument(name: 'name')->getDescription()); + self::assertTrue(condition: $yieldTaskCommand->getDefinition()->getArgument(name: 'name')->isRequired()); + self::assertTrue(condition: $yieldTaskCommand->getDefinition()->hasOption(name: 'async')); + self::assertSame(expected: 'Yield the task using the message bus', actual: $yieldTaskCommand->getDefinition()->getOption(name: 'async')->getDescription()); + self::assertSame(expected: 'a', actual: $yieldTaskCommand->getDefinition()->getOption(name: 'async')->getShortcut()); + self::assertTrue(condition: $yieldTaskCommand->getDefinition()->hasOption(name: 'force')); + self::assertSame(expected: 'Force the operation without confirmation', actual: $yieldTaskCommand->getDefinition()->getOption(name: 'force')->getDescription()); + self::assertSame(expected: 'f', actual: $yieldTaskCommand->getDefinition()->getOption(name: 'force')->getShortcut()); self::assertSame( + expected: $yieldTaskCommand->getHelp(), + actual: <<<'EOF' The %command.name% command yield a task. @@ -67,75 +74,94 @@ public function testCommandIsConfigured(): void */ public function testCommandCanSuggestStoredTasks(): void { - $scheduler = new Scheduler('UTC', new InMemoryTransport(new InMemoryConfiguration(), new SchedulePolicyOrchestrator([ + $scheduler = new Scheduler(timezone: 'UTC', transport: new InMemoryTransport(configuration: new InMemoryConfiguration(), schedulePolicyOrchestrator: new SchedulePolicyOrchestrator(policies: [ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(), new EventDispatcher()); - $scheduler->schedule(new NullTask('foo')); - $scheduler->schedule(new NullTask('bar')); + ])), middlewareStack: new SchedulerMiddlewareStack(), eventDispatcher: new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())); + $scheduler->schedule(task: new NullTask(name: 'foo')); + $scheduler->schedule(task: new NullTask(name: 'bar')); - $tester = new CommandCompletionTester(new YieldTaskCommand($scheduler)); - $suggestions = $tester->complete(['f', 'b']); + $tester = new CommandCompletionTester(command: new YieldTaskCommand(scheduler: $scheduler)); + $suggestions = $tester->complete(input: ['f', 'b']); - self::assertSame(['foo', 'bar'], $suggestions); + self::assertSame(expected: ['foo', 'bar'], actual: $suggestions); } + /** + * @throws Throwable {@see Scheduler::__construct()} + */ public function testCommandCannotYieldWithoutConfirmationOrForceOption(): void { - $scheduler = $this->createMock(SchedulerInterface::class); - $scheduler->expects(self::never())->method('yieldTask'); + $scheduler = new Scheduler(timezone: 'UTC', transport: new InMemoryTransport(configuration: new InMemoryConfiguration(), schedulePolicyOrchestrator: new SchedulePolicyOrchestrator(policies: [ + new FirstInFirstOutPolicy(), + ])), middlewareStack: new SchedulerMiddlewareStack(), eventDispatcher: new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())); - $commandTester = new CommandTester(new YieldTaskCommand($scheduler)); - $commandTester->execute([ + $commandTester = new CommandTester(command: new YieldTaskCommand(scheduler: $scheduler)); + $commandTester->execute(input: [ 'name' => 'foo', ]); - self::assertSame(Command::FAILURE, $commandTester->getStatusCode()); - self::assertStringContainsString('[WARNING] The task "foo" has not been yielded', $commandTester->getDisplay()); + self::assertSame(expected: Command::FAILURE, actual: $commandTester->getStatusCode()); + self::assertStringContainsString(needle: '[WARNING] The task "foo" has not been yielded', haystack: $commandTester->getDisplay()); } + /** + * @throws Throwable {@see Scheduler::__construct()} + */ public function testCommandCanYieldWithConfirmation(): void { - $scheduler = $this->createMock(SchedulerInterface::class); - $scheduler->expects(self::once())->method('yieldTask')->with(self::equalTo('foo'), self::equalTo(false)); + $scheduler = new Scheduler(timezone: 'UTC', transport: new InMemoryTransport(configuration: new InMemoryConfiguration(), schedulePolicyOrchestrator: new SchedulePolicyOrchestrator(policies: [ + new FirstInFirstOutPolicy(), + ])), middlewareStack: new SchedulerMiddlewareStack(), eventDispatcher: new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())); + $scheduler->schedule(task: new NullTask(name: 'foo')); - $commandTester = new CommandTester(new YieldTaskCommand($scheduler)); - $commandTester->setInputs(['yes']); - $commandTester->execute([ + $commandTester = new CommandTester(command: new YieldTaskCommand(scheduler: $scheduler)); + $commandTester->setInputs(inputs: ['yes']); + $commandTester->execute(input: [ 'name' => 'foo', ]); - self::assertSame(Command::SUCCESS, $commandTester->getStatusCode()); - self::assertStringContainsString('[OK] The task "foo" has been yielded', $commandTester->getDisplay()); + self::assertSame(expected: Command::SUCCESS, actual: $commandTester->getStatusCode()); + self::assertStringContainsString(needle: '[OK] The task "foo" has been yielded', haystack: $commandTester->getDisplay()); } + /** + * @throws Throwable {@see Scheduler::__construct()} + */ public function testCommandCanYieldWithForceOption(): void { - $scheduler = $this->createMock(SchedulerInterface::class); - $scheduler->expects(self::once())->method('yieldTask')->with(self::equalTo('foo'), self::equalTo(false)); + $scheduler = new Scheduler(timezone: 'UTC', transport: new InMemoryTransport(configuration: new InMemoryConfiguration(), schedulePolicyOrchestrator: new SchedulePolicyOrchestrator(policies: [ + new FirstInFirstOutPolicy(), + ])), middlewareStack: new SchedulerMiddlewareStack(), eventDispatcher: new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())); + $scheduler->schedule(task: new NullTask(name: 'foo')); - $commandTester = new CommandTester(new YieldTaskCommand($scheduler)); - $commandTester->execute([ + $commandTester = new CommandTester(command: new YieldTaskCommand(scheduler: $scheduler)); + $commandTester->execute(input: [ 'name' => 'foo', '--force' => true, ]); - self::assertSame(Command::SUCCESS, $commandTester->getStatusCode()); - self::assertStringContainsString('[OK] The task "foo" has been yielded', $commandTester->getDisplay()); + self::assertSame(expected: Command::SUCCESS, actual: $commandTester->getStatusCode()); + self::assertStringContainsString(needle: '[OK] The task "foo" has been yielded', haystack: $commandTester->getDisplay()); } + /** + * @throws Throwable {@see Scheduler::__construct()} + */ public function testCommandCanYieldUsingAsyncOption(): void { - $scheduler = $this->createMock(SchedulerInterface::class); - $scheduler->expects(self::once())->method('yieldTask')->with(self::equalTo('foo'), self::equalTo(true)); + $scheduler = new Scheduler(timezone: 'UTC', transport: new InMemoryTransport(configuration: new InMemoryConfiguration(), schedulePolicyOrchestrator: new SchedulePolicyOrchestrator(policies: [ + new FirstInFirstOutPolicy(), + ])), middlewareStack: new SchedulerMiddlewareStack(), eventDispatcher: new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())); + $scheduler->schedule(task: new NullTask(name: 'foo')); - $commandTester = new CommandTester(new YieldTaskCommand($scheduler)); - $commandTester->execute([ + $commandTester = new CommandTester(command: new YieldTaskCommand(scheduler: $scheduler)); + $commandTester->execute(input: [ 'name' => 'foo', '--async' => true, '--force' => true, ]); - self::assertSame(Command::SUCCESS, $commandTester->getStatusCode()); - self::assertStringContainsString('[OK] The task "foo" has been yielded', $commandTester->getDisplay()); + self::assertSame(expected: Command::SUCCESS, actual: $commandTester->getStatusCode()); + self::assertStringContainsString(needle: '[OK] The task "foo" has been yielded', haystack: $commandTester->getDisplay()); } } diff --git a/tests/DependencyInjection/SchedulerBundleExtensionTest.php b/tests/DependencyInjection/SchedulerBundleExtensionTest.php index 52b5979c..e5f73303 100644 --- a/tests/DependencyInjection/SchedulerBundleExtensionTest.php +++ b/tests/DependencyInjection/SchedulerBundleExtensionTest.php @@ -168,18 +168,18 @@ final class SchedulerBundleExtensionTest extends TestCase { public function testExtensionCannotBeConfiguredWithoutTransport(): void { - $container = $this->getContainer([ + $container = $this->getContainer(configuration: [ 'path' => '/_foo', 'timezone' => 'Europe/Paris', ]); - self::assertFalse($container->hasParameter('scheduler.timezone')); - self::assertFalse($container->hasParameter('scheduler.trigger_path')); + self::assertFalse(condition: $container->hasParameter(name: 'scheduler.timezone')); + self::assertFalse(condition: $container->hasParameter(name: 'scheduler.trigger_path')); } public function testParametersAreRegistered(): void { - $container = $this->getContainer([ + $container = $this->getContainer(configuration: [ 'path' => '/_foo', 'timezone' => 'Europe/Paris', 'transport' => [ @@ -187,25 +187,25 @@ public function testParametersAreRegistered(): void ], ]); - self::assertCount(9, $container->getParameterBag()->all()); - self::assertTrue($container->hasParameter('scheduler.timezone')); - self::assertSame('Europe/Paris', $container->getParameter('scheduler.timezone')); - self::assertTrue($container->hasParameter('scheduler.trigger_path')); - self::assertSame('/_foo', $container->getParameter('scheduler.trigger_path')); - self::assertTrue($container->hasParameter('scheduler.scheduler_mode')); - self::assertSame('default', $container->getParameter('scheduler.scheduler_mode')); - self::assertTrue($container->hasParameter('scheduler.probe_enabled')); - self::assertFalse($container->getParameter('scheduler.probe_enabled')); - self::assertFalse($container->getParameter('scheduler.pool_support')); - self::assertSame('default', $container->getParameter('scheduler.worker_mode')); - self::assertFalse($container->getParameter('scheduler.worker_registry')); - self::assertTrue($container->hasParameter('scheduler.middleware_mode')); - self::assertSame('default', $container->getParameter('scheduler.middleware_mode')); + self::assertCount(expectedCount: 9, haystack: $container->getParameterBag()->all()); + self::assertTrue(condition: $container->hasParameter(name: 'scheduler.timezone')); + self::assertSame(expected: 'Europe/Paris', actual: $container->getParameter(name: 'scheduler.timezone')); + self::assertTrue(condition: $container->hasParameter(name: 'scheduler.trigger_path')); + self::assertSame(expected: '/_foo', actual: $container->getParameter(name: 'scheduler.trigger_path')); + self::assertTrue(condition: $container->hasParameter(name: 'scheduler.scheduler_mode')); + self::assertSame(expected: 'default', actual: $container->getParameter(name: 'scheduler.scheduler_mode')); + self::assertTrue(condition: $container->hasParameter(name: 'scheduler.probe_enabled')); + self::assertFalse(condition: $container->getParameter(name: 'scheduler.probe_enabled')); + self::assertFalse(condition: $container->getParameter(name: 'scheduler.pool_support')); + self::assertSame(expected: 'default', actual: $container->getParameter(name: 'scheduler.worker_mode')); + self::assertFalse(condition: $container->getParameter(name: 'scheduler.worker_registry')); + self::assertTrue(condition: $container->hasParameter(name: 'scheduler.middleware_mode')); + self::assertSame(expected: 'default', actual: $container->getParameter(name: 'scheduler.middleware_mode')); } public function testInterfacesForAutoconfigureAreRegistered(): void { - $container = $this->getContainer([ + $container = $this->getContainer(configuration: [ 'path' => '/_foo', 'timezone' => 'Europe/Paris', 'transport' => [ @@ -517,7 +517,7 @@ public function testSchedulerIsRegistered(): void self::assertTrue($container->hasDefinition(Scheduler::class)); self::assertTrue($container->hasAlias(SchedulerInterface::class)); - self::assertCount(5, $container->getDefinition(Scheduler::class)->getArguments()); + self::assertCount(7, $container->getDefinition(Scheduler::class)->getArguments()); self::assertSame('Europe/Paris', $container->getDefinition(Scheduler::class)->getArgument(0)); self::assertInstanceOf(Reference::class, $container->getDefinition(Scheduler::class)->getArgument(1)); self::assertSame(TransportInterface::class, (string) $container->getDefinition(Scheduler::class)->getArgument(1)); @@ -529,8 +529,14 @@ public function testSchedulerIsRegistered(): void self::assertSame(EventDispatcherInterface::class, (string) $container->getDefinition(Scheduler::class)->getArgument(3)); self::assertSame(ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, $container->getDefinition(Scheduler::class)->getArgument(3)->getInvalidBehavior()); self::assertInstanceOf(Reference::class, $container->getDefinition(Scheduler::class)->getArgument(4)); - self::assertSame(MessageBusInterface::class, (string) $container->getDefinition(Scheduler::class)->getArgument(4)); - self::assertSame(ContainerInterface::NULL_ON_INVALID_REFERENCE, $container->getDefinition(Scheduler::class)->getArgument(4)->getInvalidBehavior()); + self::assertSame('scheduler.lock_store.factory', (string) $container->getDefinition(Scheduler::class)->getArgument(4)); + self::assertSame(ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, $container->getDefinition(Scheduler::class)->getArgument(4)->getInvalidBehavior()); + self::assertInstanceOf(Reference::class, $container->getDefinition(Scheduler::class)->getArgument(5)); + self::assertSame(LoggerInterface::class, (string) $container->getDefinition(Scheduler::class)->getArgument(5)); + self::assertSame(ContainerInterface::NULL_ON_INVALID_REFERENCE, $container->getDefinition(Scheduler::class)->getArgument(5)->getInvalidBehavior()); + self::assertInstanceOf(Reference::class, $container->getDefinition(Scheduler::class)->getArgument(6)); + self::assertSame(MessageBusInterface::class, (string) $container->getDefinition(Scheduler::class)->getArgument(6)); + self::assertSame(ContainerInterface::NULL_ON_INVALID_REFERENCE, $container->getDefinition(Scheduler::class)->getArgument(6)->getInvalidBehavior()); self::assertFalse($container->getDefinition(Scheduler::class)->isPublic()); self::assertCount(3, $container->getDefinition(Scheduler::class)->getTags()); self::assertTrue($container->getDefinition(Scheduler::class)->hasTag('monolog.logger')); @@ -560,7 +566,7 @@ public function testLazySchedulerIsRegistered(): void self::assertTrue($container->hasDefinition(Scheduler::class)); self::assertTrue($container->hasAlias(SchedulerInterface::class)); - self::assertCount(5, $container->getDefinition(Scheduler::class)->getArguments()); + self::assertCount(7, $container->getDefinition(Scheduler::class)->getArguments()); self::assertSame('Europe/Paris', $container->getDefinition(Scheduler::class)->getArgument(0)); self::assertInstanceOf(Reference::class, $container->getDefinition(Scheduler::class)->getArgument(1)); self::assertSame(TransportInterface::class, (string) $container->getDefinition(Scheduler::class)->getArgument(1)); @@ -572,8 +578,14 @@ public function testLazySchedulerIsRegistered(): void self::assertSame(EventDispatcherInterface::class, (string) $container->getDefinition(Scheduler::class)->getArgument(3)); self::assertSame(ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, $container->getDefinition(Scheduler::class)->getArgument(3)->getInvalidBehavior()); self::assertInstanceOf(Reference::class, $container->getDefinition(Scheduler::class)->getArgument(4)); - self::assertSame(MessageBusInterface::class, (string) $container->getDefinition(Scheduler::class)->getArgument(4)); - self::assertSame(ContainerInterface::NULL_ON_INVALID_REFERENCE, $container->getDefinition(Scheduler::class)->getArgument(4)->getInvalidBehavior()); + self::assertSame('scheduler.lock_store.factory', (string) $container->getDefinition(Scheduler::class)->getArgument(4)); + self::assertSame(ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, $container->getDefinition(Scheduler::class)->getArgument(4)->getInvalidBehavior()); + self::assertInstanceOf(Reference::class, $container->getDefinition(Scheduler::class)->getArgument(5)); + self::assertSame(LoggerInterface::class, (string) $container->getDefinition(Scheduler::class)->getArgument(5)); + self::assertSame(ContainerInterface::NULL_ON_INVALID_REFERENCE, $container->getDefinition(Scheduler::class)->getArgument(5)->getInvalidBehavior()); + self::assertInstanceOf(Reference::class, $container->getDefinition(Scheduler::class)->getArgument(6)); + self::assertSame(MessageBusInterface::class, (string) $container->getDefinition(Scheduler::class)->getArgument(6)); + self::assertSame(ContainerInterface::NULL_ON_INVALID_REFERENCE, $container->getDefinition(Scheduler::class)->getArgument(6)->getInvalidBehavior()); self::assertFalse($container->getDefinition(Scheduler::class)->isPublic()); self::assertTrue($container->getDefinition(Scheduler::class)->hasTag('monolog.logger')); self::assertSame('scheduler', $container->getDefinition(Scheduler::class)->getTag('monolog.logger')[0]['channel']); @@ -623,7 +635,7 @@ public function testFiberSchedulerIsRegistered(): void self::assertTrue($container->hasDefinition(Scheduler::class)); self::assertTrue($container->hasAlias(SchedulerInterface::class)); - self::assertCount(5, $container->getDefinition(Scheduler::class)->getArguments()); + self::assertCount(7, $container->getDefinition(Scheduler::class)->getArguments()); self::assertSame('Europe/Paris', $container->getDefinition(Scheduler::class)->getArgument(0)); self::assertInstanceOf(Reference::class, $container->getDefinition(Scheduler::class)->getArgument(1)); self::assertSame(TransportInterface::class, (string) $container->getDefinition(Scheduler::class)->getArgument(1)); @@ -635,8 +647,14 @@ public function testFiberSchedulerIsRegistered(): void self::assertSame(EventDispatcherInterface::class, (string) $container->getDefinition(Scheduler::class)->getArgument(3)); self::assertSame(ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, $container->getDefinition(Scheduler::class)->getArgument(3)->getInvalidBehavior()); self::assertInstanceOf(Reference::class, $container->getDefinition(Scheduler::class)->getArgument(4)); - self::assertSame(MessageBusInterface::class, (string) $container->getDefinition(Scheduler::class)->getArgument(4)); - self::assertSame(ContainerInterface::NULL_ON_INVALID_REFERENCE, $container->getDefinition(Scheduler::class)->getArgument(4)->getInvalidBehavior()); + self::assertSame('scheduler.lock_store.factory', (string) $container->getDefinition(Scheduler::class)->getArgument(4)); + self::assertSame(ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, $container->getDefinition(Scheduler::class)->getArgument(4)->getInvalidBehavior()); + self::assertInstanceOf(Reference::class, $container->getDefinition(Scheduler::class)->getArgument(5)); + self::assertSame(LoggerInterface::class, (string) $container->getDefinition(Scheduler::class)->getArgument(5)); + self::assertSame(ContainerInterface::NULL_ON_INVALID_REFERENCE, $container->getDefinition(Scheduler::class)->getArgument(5)->getInvalidBehavior()); + self::assertInstanceOf(Reference::class, $container->getDefinition(Scheduler::class)->getArgument(6)); + self::assertSame(MessageBusInterface::class, (string) $container->getDefinition(Scheduler::class)->getArgument(6)); + self::assertSame(ContainerInterface::NULL_ON_INVALID_REFERENCE, $container->getDefinition(Scheduler::class)->getArgument(6)->getInvalidBehavior()); self::assertFalse($container->getDefinition(Scheduler::class)->isPublic()); self::assertTrue($container->getDefinition(Scheduler::class)->hasTag('monolog.logger')); self::assertSame('scheduler', $container->getDefinition(Scheduler::class)->getTag('monolog.logger')[0]['channel']); @@ -1375,7 +1393,7 @@ public function testExecutionPolicyRegistryIsRegistered(): void public function testExecutionPoliciesAreRegistered(): void { - $container = $this->getContainer([ + $container = $this->getContainer(configuration: [ 'timezone' => 'Europe/Paris', 'transport' => [ 'dsn' => 'memory://first_in_first_out', @@ -1386,18 +1404,20 @@ public function testExecutionPoliciesAreRegistered(): void ], ]); - self::assertTrue($container->hasDefinition(DefaultPolicy::class)); - self::assertCount(0, $container->getDefinition(DefaultPolicy::class)->getArguments()); - self::assertCount(3, $container->getDefinition(DefaultPolicy::class)->getTags()); - self::assertTrue($container->getDefinition(DefaultPolicy::class)->hasTag('scheduler.execution_policy')); - self::assertTrue($container->getDefinition(DefaultPolicy::class)->hasTag('container.hot_path')); - self::assertTrue($container->getDefinition(DefaultPolicy::class)->hasTag('container.preload')); - self::assertSame(DefaultPolicy::class, $container->getDefinition(DefaultPolicy::class)->getTag('container.preload')[0]['class']); + self::assertTrue(condition: $container->hasDefinition(id: DefaultPolicy::class)); + self::assertCount(expectedCount: 0, haystack: $container->getDefinition(id: DefaultPolicy::class)->getArguments()); + self::assertCount(expectedCount: 3, haystack: $container->getDefinition(id: DefaultPolicy::class)->getTags()); + self::assertTrue(condition: $container->getDefinition(id: DefaultPolicy::class)->hasTag(name: 'scheduler.execution_policy')); + self::assertTrue(condition: $container->getDefinition(id: DefaultPolicy::class)->hasTag(name: 'container.hot_path')); + self::assertTrue(condition: $container->getDefinition(id: DefaultPolicy::class)->hasTag(name: 'container.preload')); + self::assertSame(expected: DefaultPolicy::class, actual: $container->getDefinition(id: DefaultPolicy::class)->getTag(name: 'container.preload')[0]['class']); + + self::assertFalse(condition: $container->hasDefinition(id: FiberPolicy::class)); } public function testExecutionPoliciesAreRegisteredWhenUsingFiber(): void { - $container = $this->getContainer([ + $container = $this->getContainer(configuration: [ 'timezone' => 'Europe/Paris', 'transport' => [ 'dsn' => 'memory://first_in_first_out', @@ -1408,21 +1428,29 @@ public function testExecutionPoliciesAreRegisteredWhenUsingFiber(): void ], ]); - self::assertTrue($container->hasDefinition(FiberPolicy::class)); - self::assertCount(1, $container->getDefinition(FiberPolicy::class)->getArguments()); - self::assertInstanceOf(Reference::class, $container->getDefinition(FiberPolicy::class)->getArgument(0)); - self::assertSame(LoggerInterface::class, (string) $container->getDefinition(FiberPolicy::class)->getArgument(0)); - self::assertSame(ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, $container->getDefinition(FiberPolicy::class)->getArgument(0)->getInvalidBehavior()); - self::assertCount(3, $container->getDefinition(FiberPolicy::class)->getTags()); - self::assertTrue($container->getDefinition(FiberPolicy::class)->hasTag('scheduler.execution_policy')); - self::assertTrue($container->getDefinition(FiberPolicy::class)->hasTag('container.hot_path')); - self::assertTrue($container->getDefinition(FiberPolicy::class)->hasTag('container.preload')); - self::assertSame(FiberPolicy::class, $container->getDefinition(FiberPolicy::class)->getTag('container.preload')[0]['class']); + self::assertTrue(condition: $container->hasDefinition(id: DefaultPolicy::class)); + self::assertCount(expectedCount: 0, haystack: $container->getDefinition(id: DefaultPolicy::class)->getArguments()); + self::assertCount(expectedCount: 3, haystack: $container->getDefinition(id: DefaultPolicy::class)->getTags()); + self::assertTrue(condition: $container->getDefinition(id: DefaultPolicy::class)->hasTag(name: 'scheduler.execution_policy')); + self::assertTrue(condition: $container->getDefinition(id: DefaultPolicy::class)->hasTag(name: 'container.hot_path')); + self::assertTrue(condition: $container->getDefinition(id: DefaultPolicy::class)->hasTag(name: 'container.preload')); + self::assertSame(expected: DefaultPolicy::class, actual: $container->getDefinition(id: DefaultPolicy::class)->getTag(name: 'container.preload')[0]['class']); + + self::assertTrue(condition: $container->hasDefinition(id: FiberPolicy::class)); + self::assertCount(expectedCount: 1, haystack: $container->getDefinition(id: FiberPolicy::class)->getArguments()); + self::assertInstanceOf(expected: Reference::class, actual: $container->getDefinition(id: FiberPolicy::class)->getArgument(index: 0)); + self::assertSame(expected: LoggerInterface::class, actual: (string) $container->getDefinition(id: FiberPolicy::class)->getArgument(index: 0)); + self::assertSame(expected: ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, actual: $container->getDefinition(id: FiberPolicy::class)->getArgument(index: 0)->getInvalidBehavior()); + self::assertCount(expectedCount: 3, haystack: $container->getDefinition(id: FiberPolicy::class)->getTags()); + self::assertTrue(condition: $container->getDefinition(id: FiberPolicy::class)->hasTag(name: 'scheduler.execution_policy')); + self::assertTrue(condition: $container->getDefinition(id: FiberPolicy::class)->hasTag(name: 'container.hot_path')); + self::assertTrue(condition: $container->getDefinition(id: FiberPolicy::class)->hasTag(name: 'container.preload')); + self::assertSame(expected: FiberPolicy::class, actual: $container->getDefinition(id: FiberPolicy::class)->getTag(name: 'container.preload')[0]['class']); } public function testWorkerRegistryCannotBeRegisteredWithoutBeingEnabled(): void { - $container = $this->getContainer([ + $container = $this->getContainer(configuration: [ 'path' => '/_foo', 'timezone' => 'Europe/Paris', 'transport' => [ @@ -1432,7 +1460,7 @@ public function testWorkerRegistryCannotBeRegisteredWithoutBeingEnabled(): void 'lock_store' => null, ]); - self::assertFalse($container->hasDefinition(WorkerRegistry::class)); + self::assertFalse(condition: $container->hasDefinition(id: WorkerRegistry::class)); } public function testWorkerRegistryIsRegistered(): void @@ -1711,22 +1739,22 @@ public function testMiddlewareStackAreConfigured(): void self::assertTrue($container->hasDefinition(MiddlewareRegistry::class)); self::assertTrue($container->hasAlias(MiddlewareRegistryInterface::class)); self::assertSame(MiddlewareRegistry::class, (string) $container->getAlias(MiddlewareRegistryInterface::class)); - self::assertFalse($container->getDefinition(MiddlewareRegistry::class)->isPublic()); self::assertCount(1, $container->getDefinition(MiddlewareRegistry::class)->getArguments()); self::assertInstanceOf(TaggedIteratorArgument::class, $container->getDefinition(MiddlewareRegistry::class)->getArgument(0)); - self::assertCount(1, $container->getDefinition(MiddlewareRegistry::class)->getTags()); self::assertSame('scheduler.middleware', $container->getDefinition(MiddlewareRegistry::class)->getArgument(0)->getTag()); - self::assertCount(1, $container->getDefinition(MiddlewareRegistry::class)->getTags()); + self::assertFalse($container->getDefinition(MiddlewareRegistry::class)->isPublic()); + self::assertCount(2, $container->getDefinition(MiddlewareRegistry::class)->getTags()); + self::assertTrue($container->getDefinition(MiddlewareRegistry::class)->hasTag('container.hot_path')); self::assertTrue($container->getDefinition(MiddlewareRegistry::class)->hasTag('container.preload')); self::assertSame(MiddlewareRegistry::class, $container->getDefinition(MiddlewareRegistry::class)->getTag('container.preload')[0]['class']); self::assertTrue($container->hasAlias(SchedulerMiddlewareStackInterface::class)); self::assertTrue($container->hasDefinition(SchedulerMiddlewareStack::class)); - self::assertFalse($container->getDefinition(SchedulerMiddlewareStack::class)->isPublic()); self::assertCount(1, $container->getDefinition(SchedulerMiddlewareStack::class)->getArguments()); self::assertInstanceOf(Reference::class, $container->getDefinition(SchedulerMiddlewareStack::class)->getArgument(0)); self::assertSame(MiddlewareRegistryInterface::class, (string) $container->getDefinition(SchedulerMiddlewareStack::class)->getArgument(0)); self::assertSame(ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, $container->getDefinition(SchedulerMiddlewareStack::class)->getArgument(0)->getInvalidBehavior()); + self::assertFalse($container->getDefinition(SchedulerMiddlewareStack::class)->isPublic()); self::assertCount(3, $container->getDefinition(SchedulerMiddlewareStack::class)->getTags()); self::assertTrue($container->getDefinition(SchedulerMiddlewareStack::class)->hasTag('scheduler.middleware_hub')); self::assertTrue($container->getDefinition(SchedulerMiddlewareStack::class)->hasTag('container.hot_path')); @@ -1751,19 +1779,21 @@ public function testMiddlewareStackAreConfigured(): void self::assertCount(1, $container->getDefinition(NotifierMiddleware::class)->getArguments()); self::assertInstanceOf(Reference::class, $container->getDefinition(NotifierMiddleware::class)->getArgument(0)); self::assertSame(NotifierInterface::class, (string) $container->getDefinition(NotifierMiddleware::class)->getArgument(0)); - self::assertCount(4, $container->getDefinition(NotifierMiddleware::class)->getTags()); + self::assertCount(5, $container->getDefinition(NotifierMiddleware::class)->getTags()); self::assertTrue($container->getDefinition(NotifierMiddleware::class)->hasTag('scheduler.middleware')); self::assertTrue($container->getDefinition(NotifierMiddleware::class)->hasTag('scheduler.scheduler_middleware')); self::assertTrue($container->getDefinition(NotifierMiddleware::class)->hasTag('scheduler.worker_middleware')); + self::assertTrue($container->getDefinition(NotifierMiddleware::class)->hasTag('container.hot_path')); self::assertTrue($container->getDefinition(NotifierMiddleware::class)->hasTag('container.preload')); self::assertSame(NotifierMiddleware::class, $container->getDefinition(NotifierMiddleware::class)->getTag('container.preload')[0]['class']); self::assertTrue($container->hasDefinition(TaskCallbackMiddleware::class)); self::assertFalse($container->getDefinition(TaskCallbackMiddleware::class)->isPublic()); - self::assertCount(4, $container->getDefinition(TaskCallbackMiddleware::class)->getTags()); + self::assertCount(5, $container->getDefinition(TaskCallbackMiddleware::class)->getTags()); self::assertTrue($container->getDefinition(TaskCallbackMiddleware::class)->hasTag('scheduler.middleware')); self::assertTrue($container->getDefinition(TaskCallbackMiddleware::class)->hasTag('scheduler.scheduler_middleware')); self::assertTrue($container->getDefinition(TaskCallbackMiddleware::class)->hasTag('scheduler.worker_middleware')); + self::assertTrue($container->getDefinition(TaskCallbackMiddleware::class)->hasTag('container.hot_path')); self::assertTrue($container->getDefinition(TaskCallbackMiddleware::class)->hasTag('container.preload')); self::assertSame(TaskCallbackMiddleware::class, $container->getDefinition(TaskCallbackMiddleware::class)->getTag('container.preload')[0]['class']); @@ -1776,9 +1806,10 @@ public function testMiddlewareStackAreConfigured(): void self::assertInstanceOf(Reference::class, $container->getDefinition(SingleRunTaskMiddleware::class)->getArgument(1)); self::assertSame(LoggerInterface::class, (string) $container->getDefinition(SingleRunTaskMiddleware::class)->getArgument(1)); self::assertSame(ContainerInterface::NULL_ON_INVALID_REFERENCE, $container->getDefinition(SingleRunTaskMiddleware::class)->getArgument(1)->getInvalidBehavior()); - self::assertCount(3, $container->getDefinition(SingleRunTaskMiddleware::class)->getTags()); + self::assertCount(4, $container->getDefinition(SingleRunTaskMiddleware::class)->getTags()); self::assertTrue($container->getDefinition(SingleRunTaskMiddleware::class)->hasTag('scheduler.middleware')); self::assertTrue($container->getDefinition(SingleRunTaskMiddleware::class)->hasTag('scheduler.worker_middleware')); + self::assertTrue($container->getDefinition(SingleRunTaskMiddleware::class)->hasTag('container.hot_path')); self::assertTrue($container->getDefinition(SingleRunTaskMiddleware::class)->hasTag('container.preload')); self::assertSame(SingleRunTaskMiddleware::class, $container->getDefinition(SingleRunTaskMiddleware::class)->getTag('container.preload')[0]['class']); @@ -1787,9 +1818,10 @@ public function testMiddlewareStackAreConfigured(): void self::assertCount(1, $container->getDefinition(TaskUpdateMiddleware::class)->getArguments()); self::assertInstanceOf(Reference::class, $container->getDefinition(TaskUpdateMiddleware::class)->getArgument(0)); self::assertSame(TransportInterface::class, (string) $container->getDefinition(TaskUpdateMiddleware::class)->getArgument(0)); - self::assertCount(3, $container->getDefinition(TaskUpdateMiddleware::class)->getTags()); + self::assertCount(4, $container->getDefinition(TaskUpdateMiddleware::class)->getTags()); self::assertTrue($container->getDefinition(TaskUpdateMiddleware::class)->hasTag('scheduler.middleware')); self::assertTrue($container->getDefinition(TaskUpdateMiddleware::class)->hasTag('scheduler.worker_middleware')); + self::assertTrue($container->getDefinition(TaskUpdateMiddleware::class)->hasTag('container.hot_path')); self::assertTrue($container->getDefinition(TaskUpdateMiddleware::class)->hasTag('container.preload')); self::assertSame(TaskUpdateMiddleware::class, $container->getDefinition(TaskUpdateMiddleware::class)->getTag('container.preload')[0]['class']); @@ -1802,18 +1834,20 @@ public function testMiddlewareStackAreConfigured(): void self::assertInstanceOf(Reference::class, $container->getDefinition(TaskLockBagMiddleware::class)->getArgument(1)); self::assertSame(LoggerInterface::class, (string) $container->getDefinition(TaskLockBagMiddleware::class)->getArgument(1)); self::assertSame(ContainerInterface::NULL_ON_INVALID_REFERENCE, $container->getDefinition(TaskLockBagMiddleware::class)->getArgument(1)->getInvalidBehavior()); - self::assertCount(3, $container->getDefinition(TaskLockBagMiddleware::class)->getTags()); + self::assertCount(4, $container->getDefinition(TaskLockBagMiddleware::class)->getTags()); self::assertTrue($container->getDefinition(TaskLockBagMiddleware::class)->hasTag('scheduler.middleware')); self::assertTrue($container->getDefinition(TaskLockBagMiddleware::class)->hasTag('scheduler.worker_middleware')); + self::assertTrue($container->getDefinition(TaskLockBagMiddleware::class)->hasTag('container.hot_path')); self::assertTrue($container->getDefinition(TaskLockBagMiddleware::class)->hasTag('container.preload')); self::assertSame(TaskLockBagMiddleware::class, $container->getDefinition(TaskLockBagMiddleware::class)->getTag('container.preload')[0]['class']); self::assertTrue($container->hasDefinition(TaskExecutionMiddleware::class)); self::assertFalse($container->getDefinition(TaskExecutionMiddleware::class)->isPublic()); self::assertCount(0, $container->getDefinition(TaskExecutionMiddleware::class)->getArguments()); - self::assertCount(3, $container->getDefinition(TaskExecutionMiddleware::class)->getTags()); + self::assertCount(4, $container->getDefinition(TaskExecutionMiddleware::class)->getTags()); self::assertTrue($container->getDefinition(TaskExecutionMiddleware::class)->hasTag('scheduler.middleware')); self::assertTrue($container->getDefinition(TaskExecutionMiddleware::class)->hasTag('scheduler.worker_middleware')); + self::assertTrue($container->getDefinition(TaskExecutionMiddleware::class)->hasTag('container.hot_path')); self::assertTrue($container->getDefinition(TaskExecutionMiddleware::class)->hasTag('container.preload')); self::assertSame(TaskExecutionMiddleware::class, $container->getDefinition(TaskExecutionMiddleware::class)->getTag('container.preload')[0]['class']); @@ -1954,9 +1988,10 @@ public function testRateLimiterMiddlewareCanBeConfigured(): void self::assertSame('limiter.foo', (string) $container->getDefinition(MaxExecutionMiddleware::class)->getArgument(0)); self::assertInstanceOf(Reference::class, $container->getDefinition(MaxExecutionMiddleware::class)->getArgument(1)); self::assertSame(LoggerInterface::class, (string) $container->getDefinition(MaxExecutionMiddleware::class)->getArgument(1)); - self::assertCount(3, $container->getDefinition(MaxExecutionMiddleware::class)->getTags()); + self::assertCount(4, $container->getDefinition(MaxExecutionMiddleware::class)->getTags()); self::assertTrue($container->getDefinition(MaxExecutionMiddleware::class)->hasTag('scheduler.middleware')); self::assertTrue($container->getDefinition(MaxExecutionMiddleware::class)->hasTag('scheduler.worker_middleware')); + self::assertTrue($container->getDefinition(MaxExecutionMiddleware::class)->hasTag('container.hot_path')); self::assertTrue($container->getDefinition(MaxExecutionMiddleware::class)->hasTag('container.preload')); self::assertSame(MaxExecutionMiddleware::class, $container->getDefinition(MaxExecutionMiddleware::class)->getTag('container.preload')[0]['class']); } diff --git a/tests/FiberSchedulerTest.php b/tests/FiberSchedulerTest.php index 4fb24860..0b484b57 100644 --- a/tests/FiberSchedulerTest.php +++ b/tests/FiberSchedulerTest.php @@ -9,6 +9,7 @@ use Exception; use PDO; use Psr\Log\LoggerInterface; +use Psr\Log\NullLogger; use SchedulerBundle\Event\TaskScheduledEvent; use SchedulerBundle\Event\TaskUnscheduledEvent; use SchedulerBundle\Exception\RuntimeException; @@ -36,7 +37,6 @@ use SchedulerBundle\Serializer\AccessLockBagNormalizer; use SchedulerBundle\Serializer\NotificationTaskBagNormalizer; use SchedulerBundle\Serializer\TaskNormalizer; -use SchedulerBundle\Task\LazyTask; use SchedulerBundle\Task\LazyTaskList; use SchedulerBundle\Task\MessengerTask; use SchedulerBundle\Task\NullTask; @@ -96,7 +96,7 @@ protected function getScheduler(): SchedulerInterface|FiberScheduler|LazySchedul 'execution_mode' => 'first_in_first_out', ]), schedulePolicyOrchestrator: new SchedulePolicyOrchestrator(policies: [ new FirstInFirstOutPolicy(), - ])), middlewareStack: new SchedulerMiddlewareStack(), eventDispatcher: new EventDispatcher())); + ])), middlewareStack: new SchedulerMiddlewareStack(), eventDispatcher: new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore()), logger: new NullLogger())); } /** @@ -108,18 +108,19 @@ public function testSchedulerCannotScheduleTasksWithErroredBeforeCallback(): voi $logger = $this->createMock(LoggerInterface::class); $logger->expects(self::once())->method('critical'); - $scheduler = new FiberScheduler(new Scheduler('UTC', new InMemoryTransport(new InMemoryConfiguration([ + $scheduler = new FiberScheduler(new Scheduler(timezone: 'UTC', transport: new InMemoryTransport(configuration: new InMemoryConfiguration(options: [ 'execution_mode' => 'first_in_first_out', - ]), new SchedulePolicyOrchestrator([ + ]), schedulePolicyOrchestrator: new SchedulePolicyOrchestrator(policies: [ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack([ + ])), middlewareStack: new SchedulerMiddlewareStack(stack: [ + new NotifierMiddleware(), new TaskCallbackMiddleware(), - ]), new EventDispatcher()), $logger); + ]), eventDispatcher: new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())), logger: $logger); - self::expectException(RuntimeException::class); - self::expectExceptionMessage('The task cannot be scheduled'); - self::expectExceptionCode(0); - $scheduler->schedule(new NullTask('foo', [ + self::expectException(exception: RuntimeException::class); + self::expectExceptionMessage(message: 'The task cannot be scheduled'); + self::expectExceptionCode(code: 0); + $scheduler->schedule(task: new NullTask(name: 'foo', options: [ 'before_scheduling' => static fn (): bool => false, ])); } @@ -136,7 +137,7 @@ public function testSchedulerCanScheduleTasksWithBeforeCallback(): void new FirstInFirstOutPolicy(), ])), new SchedulerMiddlewareStack([ new TaskCallbackMiddleware(), - ]), new EventDispatcher())); + ]), new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore()), logger: new NullLogger())); $scheduler->schedule(new NullTask('foo', [ 'before_scheduling' => static fn (): int => 1 + 1, @@ -164,7 +165,7 @@ public function testSchedulerCanScheduleTasksWithBeforeSchedulingNotificationAnd ])), new SchedulerMiddlewareStack([ new TaskCallbackMiddleware(), new NotifierMiddleware(), - ]), new EventDispatcher())); + ]), new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore()), logger: new NullLogger())); $scheduler->schedule(new NullTask('foo', [ 'before_scheduling_notification' => new NotificationTaskBag($notification, $recipient), @@ -191,7 +192,7 @@ public function testSchedulerCanScheduleTasksWithBeforeSchedulingNotificationAnd ])), new SchedulerMiddlewareStack([ new TaskCallbackMiddleware(), new NotifierMiddleware($notifier), - ]), new EventDispatcher())); + ]), new EventDispatcher(), new LockFactory(new InMemoryStore()))); $scheduler->schedule(new NullTask('foo', [ 'before_scheduling_notification' => new NotificationTaskBag($notification, $recipient), @@ -218,7 +219,7 @@ public function testSchedulerCanScheduleTasksWithAfterSchedulingNotificationAndW ])), new SchedulerMiddlewareStack([ new TaskCallbackMiddleware(), new NotifierMiddleware(), - ]), new EventDispatcher())); + ]), new EventDispatcher(), new LockFactory(new InMemoryStore()))); $scheduler->schedule(new NullTask('foo', [ 'after_scheduling_notification' => new NotificationTaskBag($notification, $recipient), @@ -245,7 +246,7 @@ public function testSchedulerCanScheduleTasksWithAfterSchedulingNotificationAndW ])), new SchedulerMiddlewareStack([ new TaskCallbackMiddleware(), new NotifierMiddleware($notifier), - ]), new EventDispatcher())); + ]), new EventDispatcher(), new LockFactory(new InMemoryStore()))); $scheduler->schedule(new NullTask('foo', [ 'after_scheduling_notification' => new NotificationTaskBag($notification, $recipient), @@ -278,7 +279,7 @@ public function testSchedulerCannotScheduleTasksWithErroredAfterCallback(): void new FirstInFirstOutPolicy(), ])), new SchedulerMiddlewareStack([ new TaskCallbackMiddleware(), - ]), $eventDispatcher), $logger); + ]), $eventDispatcher, new LockFactory(new InMemoryStore())), $logger); self::expectException(RuntimeException::class); self::expectExceptionMessage('The task has encountered an error after scheduling, it has been unscheduled'); @@ -298,7 +299,7 @@ public function testSchedulerCanScheduleTasksWithAfterCallback(): void new FirstInFirstOutPolicy(), ])), new SchedulerMiddlewareStack([ new TaskCallbackMiddleware(), - ]), new EventDispatcher())); + ]), new EventDispatcher(), new LockFactory(new InMemoryStore()))); $scheduler->schedule(new NullTask('foo', [ 'after_scheduling' => static fn (): bool => true, @@ -323,7 +324,7 @@ public function testSchedulerCanScheduleTasksWithMessageBus(): void 'execution_mode' => 'first_in_first_out', ]), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(), new EventDispatcher(), $bus)); + ])), new SchedulerMiddlewareStack(), new EventDispatcher(), new LockFactory(new InMemoryStore()), new NullLogger(), $bus)); $scheduler->schedule($task); } @@ -346,7 +347,7 @@ public function testTaskCanBeScheduledWithEventDispatcherAndMessageBus(TaskInter 'execution_mode' => 'first_in_first_out', ]), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(), new EventDispatcher(), $bus)); + ])), new SchedulerMiddlewareStack(), new EventDispatcher(), new LockFactory(new InMemoryStore()), new NullLogger(), $bus)); $task->setQueued(true); $scheduler->schedule($task); @@ -365,440 +366,14 @@ public function testTaskCanBeScheduledWithEventDispatcherAndMessageBus(TaskInter */ public function testMessengerTaskCanBeScheduledWithMessageBus(TransportInterface $transport): void { - $scheduler = new FiberScheduler(new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher(), new MessageBus())); + $scheduler = new FiberScheduler(new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher(), new LockFactory(new InMemoryStore()), new NullLogger(), new MessageBus())); - $scheduler->schedule(new MessengerTask('bar', new stdClass())); + $scheduler->schedule(task: new MessengerTask(name: 'bar', message: new stdClass())); self::assertCount(1, $scheduler->getTasks()); self::assertInstanceOf(TaskList::class, $scheduler->getTasks()); - self::assertCount(1, $scheduler->getTasks(true)); - self::assertInstanceOf(LazyTaskList::class, $scheduler->getTasks(true)); - } - - /** - * @throws Throwable {@see Scheduler::__construct()} - */ - public function testTaskCannotBeScheduledTwice(): void - { - $scheduler = new FiberScheduler(new Scheduler('UTC', new InMemoryTransport(new InMemoryConfiguration([ - 'execution_mode' => 'first_in_first_out', - ]), new SchedulePolicyOrchestrator([ - new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(), new EventDispatcher())); - - $scheduler->schedule(new NullTask('foo')); - $scheduler->schedule(new NullTask('foo')); - - self::assertCount(1, $scheduler->getTasks()); - } - - /** - * @throws Throwable {@see Scheduler::__construct()} - * @throws Throwable {@see SchedulerInterface::getDueTasks()} - * - * @dataProvider provideTasks - */ - public function testDueTasksCanBeReturned(TaskInterface $task): void - { - $task->setLastExecution(new DateTimeImmutable('- 2 minutes')); - - $scheduler = new FiberScheduler(new Scheduler( - 'UTC', - new InMemoryTransport(new InMemoryConfiguration([ - 'execution_mode' => 'first_in_first_out', - ]), new SchedulePolicyOrchestrator([ - new FirstInFirstOutPolicy(), - ])), - new SchedulerMiddlewareStack(), - new EventDispatcher() - )); - - $scheduler->schedule($task); - - self::assertCount(1, $scheduler->getDueTasks()); - self::assertInstanceOf(TaskList::class, $scheduler->getDueTasks()); - } - - /** - * @group time-sensitive - * - * @throws Throwable {@see Scheduler::__construct()} - * @throws Throwable {@see SchedulerInterface::getDueTasks()} - * - * @dataProvider provideTasks - */ - public function testDueTasksCanBeReturnedStrictly(TaskInterface $task): void - { - $task->setLastExecution(new DateTimeImmutable('- 2 minutes')); - - $scheduler = new FiberScheduler(new Scheduler( - 'UTC', - new InMemoryTransport(new InMemoryConfiguration([ - 'execution_mode' => 'first_in_first_out', - ]), new SchedulePolicyOrchestrator([ - new FirstInFirstOutPolicy(), - ])), - new SchedulerMiddlewareStack(), - new EventDispatcher() - )); - - $scheduler->schedule($task); - - self::assertCount(0, $scheduler->getDueTasks(false, true)); - self::assertInstanceOf(TaskList::class, $scheduler->getDueTasks()); - } - - /** - * @throws Throwable {@see Scheduler::__construct()} - * @throws Throwable {@see SchedulerInterface::getDueTasks()} - * - * @dataProvider provideTasks - */ - public function testDueTasksCanBeReturnedUsingLazyLoad(TaskInterface $task): void - { - $task->setLastExecution(new DateTimeImmutable('- 2 minutes')); - - $scheduler = new FiberScheduler(new Scheduler( - 'UTC', - new InMemoryTransport(new InMemoryConfiguration([ - 'execution_mode' => 'first_in_first_out', - ]), new SchedulePolicyOrchestrator([ - new FirstInFirstOutPolicy(), - ])), - new SchedulerMiddlewareStack(), - new EventDispatcher() - )); - - $scheduler->schedule($task); - - $list = $scheduler->getDueTasks(true); - self::assertCount(1, $list); - self::assertInstanceOf(LazyTaskList::class, $list); - } - - /** - * @group time-sensitive - * - * @throws Throwable {@see Scheduler::__construct()} - * @throws Throwable {@see SchedulerInterface::getDueTasks()} - * - * @dataProvider provideTasks - */ - public function testDueTasksCanBeReturnedStrictlyUsingLazyLoad(TaskInterface $task): void - { - $task->setLastExecution(new DateTimeImmutable('- 2 minutes')); - - $scheduler = new FiberScheduler(new Scheduler( - 'UTC', - new InMemoryTransport(new InMemoryConfiguration([ - 'execution_mode' => 'first_in_first_out', - ]), new SchedulePolicyOrchestrator([ - new FirstInFirstOutPolicy(), - ])), - new SchedulerMiddlewareStack(), - new EventDispatcher() - )); - - $scheduler->schedule($task); - - $list = $scheduler->getDueTasks(true, true); - self::assertCount(0, $list); - self::assertInstanceOf(LazyTaskList::class, $list); - } - - /** - * @throws Throwable {@see Scheduler::__construct()} - * @throws Throwable {@see SchedulerInterface::getTasks()} - * - * @dataProvider provideTasks - */ - public function testDueTasksCanBeReturnedWithSpecificFilter(TaskInterface $task): void - { - $scheduler = new FiberScheduler(new Scheduler('UTC', new InMemoryTransport(new InMemoryConfiguration([ - 'execution_mode' => 'first_in_first_out', - ]), new SchedulePolicyOrchestrator([ - new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(), new EventDispatcher())); - - $scheduler->schedule($task); - $filteredTasks = $scheduler->getTasks()->filter(static fn (TaskInterface $task): bool => null !== $task->getTimezone() && 0 === $task->getPriority()); - - self::assertCount(1, $filteredTasks); - } - - /** - * @throws Throwable {@see Scheduler::__construct()} - * @throws Throwable {@see SchedulerInterface::getTasks()} - * - * @dataProvider provideTasks - */ - public function testLazyDueTasksCanBeReturnedWithSpecificFilter(TaskInterface $task): void - { - $scheduler = new FiberScheduler(new Scheduler('UTC', new InMemoryTransport(new InMemoryConfiguration([ - 'execution_mode' => 'first_in_first_out', - ]), new SchedulePolicyOrchestrator([ - new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(), new EventDispatcher())); - $scheduler->schedule($task); - - $dueTasks = $scheduler->getTasks(true); - self::assertInstanceOf(LazyTaskList::class, $dueTasks); - - $dueTasks = $dueTasks->filter(static fn (TaskInterface $task): bool => null !== $task->getTimezone() && 0 === $task->getPriority()); - self::assertCount(1, $dueTasks); - } - - /** - * @throws Exception|Throwable {@see Scheduler::__construct()} - */ - public function testNonExecutedDueTasksCanBeReturned(): void - { - $task = new NullTask('foo'); - $secondTask = new NullTask('bar'); - $thirdTask = new NullTask('random'); - $fourthTask = new NullTask('executed', [ - 'last_execution' => new DateTimeImmutable(), - ]); - - $scheduler = new FiberScheduler(new Scheduler( - 'UTC', - new InMemoryTransport(new InMemoryConfiguration([ - 'execution_mode' => 'first_in_first_out', - ]), new SchedulePolicyOrchestrator([ - new FirstInFirstOutPolicy(), - ])), - new SchedulerMiddlewareStack(), - new EventDispatcher() - )); - - $scheduler->schedule($task); - $scheduler->schedule($secondTask); - $scheduler->schedule($thirdTask); - $scheduler->schedule($fourthTask); - - self::assertCount(3, $scheduler->getDueTasks()); - self::assertInstanceOf(TaskList::class, $scheduler->getDueTasks()); - self::assertTrue($scheduler->getDueTasks()->has('foo')); - self::assertTrue($scheduler->getDueTasks()->has('bar')); - self::assertTrue($scheduler->getDueTasks()->has('random')); - self::assertFalse($scheduler->getDueTasks()->has('executed')); - } - - /** - * @throws Exception|Throwable {@see Scheduler::__construct()} - */ - public function testNonExecutedDueTasksCanBeReturnedUsingLazyLoad(): void - { - $task = new NullTask('foo'); - $secondTask = new NullTask('bar'); - $thirdTask = new NullTask('random'); - $fourthTask = new NullTask('executed', [ - 'last_execution' => new DateTimeImmutable(), - ]); - - $scheduler = new FiberScheduler(new Scheduler( - 'UTC', - new InMemoryTransport(new InMemoryConfiguration([ - 'execution_mode' => 'first_in_first_out', - ]), new SchedulePolicyOrchestrator([ - new FirstInFirstOutPolicy(), - ])), - new SchedulerMiddlewareStack(), - new EventDispatcher() - )); - - $scheduler->schedule($task); - $scheduler->schedule($secondTask); - $scheduler->schedule($thirdTask); - $scheduler->schedule($fourthTask); - - self::assertCount(3, $scheduler->getDueTasks(true)); - self::assertInstanceOf(TaskList::class, $scheduler->getDueTasks()); - self::assertTrue($scheduler->getDueTasks(true)->has('foo')); - self::assertTrue($scheduler->getDueTasks(true)->has('bar')); - self::assertTrue($scheduler->getDueTasks(true)->has('random')); - self::assertFalse($scheduler->getDueTasks(true)->has('executed')); - } - - /** - * @throws Exception|Throwable {@see Scheduler::__construct()} - */ - public function testCurentMinuteExecutedDueTasksCannotBeReturned(): void - { - $task = new NullTask('foo', [ - 'last_execution' => new DateTimeImmutable(), - ]); - $secondTask = new NullTask('bar', [ - 'last_execution' => new DateTimeImmutable('- 1 minute'), - ]); - $thirdTask = new NullTask('random', [ - 'last_execution' => new DateTimeImmutable(), - ]); - - $scheduler = new FiberScheduler(new Scheduler( - 'UTC', - new InMemoryTransport(new InMemoryConfiguration([ - 'execution_mode' => 'first_in_first_out', - ]), new SchedulePolicyOrchestrator([ - new FirstInFirstOutPolicy(), - ])), - new SchedulerMiddlewareStack(), - new EventDispatcher() - )); - - $scheduler->schedule($task); - $scheduler->schedule($secondTask); - $scheduler->schedule($thirdTask); - - self::assertCount(1, $scheduler->getDueTasks()); - self::assertInstanceOf(TaskList::class, $scheduler->getDueTasks()); - self::assertFalse($scheduler->getDueTasks()->has('foo')); - self::assertTrue($scheduler->getDueTasks()->has('bar')); - self::assertFalse($scheduler->getDueTasks()->has('random')); - } - - /** - * @throws Exception|Throwable {@see Scheduler::__construct()} - */ - public function testCurentMinuteExecutedDueTasksCannotBeReturnedUsingLazyLoad(): void - { - $task = new NullTask('foo', [ - 'last_execution' => new DateTimeImmutable(), - ]); - $secondTask = new NullTask('bar', [ - 'last_execution' => new DateTimeImmutable('- 1 minute'), - ]); - $thirdTask = new NullTask('random', [ - 'last_execution' => new DateTimeImmutable(), - ]); - - $scheduler = new FiberScheduler(new Scheduler( - 'UTC', - new InMemoryTransport(new InMemoryConfiguration([ - 'execution_mode' => 'first_in_first_out', - ]), new SchedulePolicyOrchestrator([ - new FirstInFirstOutPolicy(), - ])), - new SchedulerMiddlewareStack(), - new EventDispatcher() - )); - - $scheduler->schedule($task); - $scheduler->schedule($secondTask); - $scheduler->schedule($thirdTask); - - self::assertCount(1, $scheduler->getDueTasks(true)); - self::assertInstanceOf(TaskList::class, $scheduler->getDueTasks()); - self::assertFalse($scheduler->getDueTasks(true)->has('foo')); - self::assertTrue($scheduler->getDueTasks(true)->has('bar')); - self::assertFalse($scheduler->getDueTasks(true)->has('random')); - } - - /** - * @throws Exception|Throwable {@see Scheduler::__construct()} - */ - public function testDueTasksCanBeReturnedWithCurrentExecutionStartDate(): void - { - $scheduler = new FiberScheduler(new Scheduler( - 'UTC', - new InMemoryTransport(new InMemoryConfiguration([ - 'execution_mode' => 'first_in_first_out', - ]), new SchedulePolicyOrchestrator([ - new FirstInFirstOutPolicy(), - ])), - new SchedulerMiddlewareStack(), - new EventDispatcher() - )); - - $scheduler->schedule(new NullTask('foo', [ - 'execution_start_date' => 'now', - 'execution_end_date' => '+ 5 minute', - ])); - - $dueTasks = $scheduler->getDueTasks(); - self::assertInstanceOf(TaskList::class, $dueTasks); - self::assertCount(1, $dueTasks); - - $task = $dueTasks->get('foo'); - self::assertSame('* * * * *', $task->getExpression()); - } - - /** - * @throws Exception|Throwable {@see Scheduler::__construct()} - */ - public function testDueTasksCanBeReturnedWithPastExecutionStartDate(): void - { - $scheduler = new FiberScheduler(new Scheduler( - 'UTC', - new InMemoryTransport(new InMemoryConfiguration([ - 'execution_mode' => 'first_in_first_out', - ]), new SchedulePolicyOrchestrator([ - new FirstInFirstOutPolicy(), - ])), - new SchedulerMiddlewareStack(), - new EventDispatcher() - )); - - $scheduler->schedule(new NullTask('foo', [ - 'execution_start_date' => '- 1 minute', - 'execution_end_date' => '+ 5 minute', - ])); - - $dueTasks = $scheduler->getDueTasks(); - self::assertInstanceOf(TaskList::class, $dueTasks); - self::assertCount(1, $dueTasks); - - $task = $dueTasks->get('foo'); - self::assertSame('* * * * *', $task->getExpression()); - } - - /** - * @throws Exception|Throwable {@see Scheduler::__construct()} - */ - public function testDueTasksCanBeReturnedWithPastExecutionStartDateLazily(): void - { - $scheduler = new FiberScheduler(new Scheduler( - 'UTC', - new InMemoryTransport(new InMemoryConfiguration([ - 'execution_mode' => 'first_in_first_out', - ]), new SchedulePolicyOrchestrator([ - new FirstInFirstOutPolicy(), - ])), - new SchedulerMiddlewareStack(), - new EventDispatcher() - )); - - $scheduler->schedule(new NullTask('foo', [ - 'execution_start_date' => '- 1 minute', - 'execution_end_date' => '+ 5 minute', - ])); - - $dueTasks = $scheduler->getDueTasks(true); - self::assertInstanceOf(LazyTaskList::class, $dueTasks); - self::assertCount(1, $dueTasks); - - $task = $dueTasks->get('foo'); - self::assertSame('* * * * *', $task->getExpression()); - } - - /** - * @throws Exception|Throwable {@see Scheduler::__construct()} - * - * @dataProvider provideTasks - */ - public function testTaskCanBeUnScheduled(TaskInterface $task): void - { - $scheduler = new FiberScheduler(new Scheduler('UTC', new InMemoryTransport(new InMemoryConfiguration([ - 'execution_mode' => 'first_in_first_out', - ]), new SchedulePolicyOrchestrator([ - new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(), new EventDispatcher())); - - $scheduler->schedule($task); - self::assertCount(1, $scheduler->getTasks()); - - $scheduler->unschedule($task->getName()); - self::assertCount(0, $scheduler->getTasks()); + self::assertCount(1, $scheduler->getTasks(lazy: true)); + self::assertInstanceOf(LazyTaskList::class, $scheduler->getTasks(lazy: true)); } /** @@ -812,7 +387,7 @@ public function testTaskCanBeUnScheduledAndLazilyRetrieved(TaskInterface $task): 'execution_mode' => 'first_in_first_out', ]), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(), new EventDispatcher())); + ])), new SchedulerMiddlewareStack(), new EventDispatcher(), new LockFactory(new InMemoryStore()))); $scheduler->schedule($task); self::assertInstanceOf(LazyTaskList::class, $scheduler->getTasks(true)); @@ -836,7 +411,7 @@ public function testTaskCanBeUpdated(): void $scheduler = new FiberScheduler(new Scheduler('UTC', new InMemoryTransport(new InMemoryConfiguration(), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher(), $bus)); + ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher(), new LockFactory(new InMemoryStore()), new NullLogger(), $bus)); $scheduler->schedule($task); self::assertCount(1, $scheduler->getTasks()); @@ -865,7 +440,7 @@ public function testTaskCanBeUpdatedAsynchronously(): void ])), ]); - $scheduler = new FiberScheduler(new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher(), $bus)); + $scheduler = new FiberScheduler(new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher(), new LockFactory(new InMemoryStore()), new NullLogger(), $bus)); $scheduler->schedule($task); self::assertCount(1, $scheduler->getTasks()); @@ -892,7 +467,7 @@ public function testTaskCanBeUpdatedThenRetrieved(TaskInterface $task): void 'execution_mode' => 'first_in_first_out', ]), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher(), $bus)); + ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher(), new LockFactory(new InMemoryStore()), new NullLogger(), $bus)); $scheduler->schedule($task); self::assertCount(1, $scheduler->getTasks()->toArray()); @@ -918,7 +493,7 @@ public function testTaskCanBeUpdatedThenLazilyRetrieved(TaskInterface $task): vo 'execution_mode' => 'first_in_first_out', ]), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher(), $bus)); + ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher(), new LockFactory(new InMemoryStore()), new NullLogger(), $bus)); $scheduler->schedule($task); self::assertInstanceOf(LazyTaskList::class, $scheduler->getTasks(true)); @@ -946,7 +521,7 @@ public function testTaskCanBePausedAndResumed(TaskInterface $task): void 'execution_mode' => 'first_in_first_out', ]), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(), new EventDispatcher(), $bus)); + ])), new SchedulerMiddlewareStack(), new EventDispatcher(), new LockFactory(new InMemoryStore()), new NullLogger(), $bus)); $scheduler->schedule($task); self::assertCount(1, $scheduler->getTasks()); @@ -971,7 +546,7 @@ public function testSchedulerCanPauseTaskWithoutMessageBus(): void $bus = $this->createMock(MessageBusInterface::class); $bus->expects(self::never())->method('dispatch'); - $scheduler = new FiberScheduler(new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher())); + $scheduler = new FiberScheduler(new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher(), new LockFactory(new InMemoryStore()))); $scheduler->pause('foo', true); } @@ -989,7 +564,7 @@ public function testSchedulerCanPauseTaskWithMessageBus(): void ->willReturn(new Envelope(new stdClass())) ; - $scheduler = new FiberScheduler(new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher(), $bus)); + $scheduler = new FiberScheduler(new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher(), new LockFactory(new InMemoryStore()), new NullLogger(), $bus)); $scheduler->pause('foo', true); } @@ -1011,7 +586,7 @@ public function testDueTasksCanBeReturnedWithStartAndEndDate(): void 'execution_mode' => 'first_in_first_out', ]), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(), new EventDispatcher())); + ])), new SchedulerMiddlewareStack(), new EventDispatcher(), new LockFactory(new InMemoryStore()))); $scheduler->schedule($task); self::assertCount(1, $scheduler->getDueTasks()); @@ -1034,7 +609,7 @@ public function testDueTasksCanBeReturnedWithStartAndEndDateUsingLazyLoad(): voi 'execution_mode' => 'first_in_first_out', ]), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(), new EventDispatcher())); + ])), new SchedulerMiddlewareStack(), new EventDispatcher(), new LockFactory(new InMemoryStore()))); $scheduler->schedule($task); @@ -1059,7 +634,7 @@ public function testDueTasksCanBeReturnedWithCurrentStartDate(): void 'execution_mode' => 'first_in_first_out', ]), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(), new EventDispatcher())); + ])), new SchedulerMiddlewareStack(), new EventDispatcher(), new LockFactory(new InMemoryStore()))); $scheduler->schedule($task); self::assertCount(1, $scheduler->getDueTasks()); @@ -1081,7 +656,7 @@ public function testDueTasksCanBeReturnedWithPreviousStartDate(): void 'execution_mode' => 'first_in_first_out', ]), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(), new EventDispatcher())); + ])), new SchedulerMiddlewareStack(), new EventDispatcher(), new LockFactory(new InMemoryStore()))); $scheduler->schedule($task); self::assertCount(1, $scheduler->getDueTasks()); @@ -1102,7 +677,7 @@ public function testDueTasksCanBeReturnedWithPreviousStartDateUsingLazyLoad(): v 'execution_mode' => 'first_in_first_out', ]), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(), new EventDispatcher())); + ])), new SchedulerMiddlewareStack(), new EventDispatcher(), new LockFactory(new InMemoryStore()))); $scheduler->schedule($task); @@ -1127,7 +702,7 @@ public function testDueTasksCanBeReturnedWithEndDate(): void 'execution_mode' => 'first_in_first_out', ]), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(), new EventDispatcher())); + ])), new SchedulerMiddlewareStack(), new EventDispatcher(), new LockFactory(new InMemoryStore()))); $scheduler->schedule($task); @@ -1149,7 +724,7 @@ public function testDueTasksCanBeReturnedWithEndDateUsingLazyLoad(): void 'execution_mode' => 'first_in_first_out', ]), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(), new EventDispatcher())); + ])), new SchedulerMiddlewareStack(), new EventDispatcher(), new LockFactory(new InMemoryStore()))); $scheduler->schedule($task); @@ -1175,7 +750,7 @@ public function testDueTasksCanBeReturnedWithCurrentStartDateAndFutureEndDate(): 'execution_mode' => 'first_in_first_out', ]), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(), new EventDispatcher())); + ])), new SchedulerMiddlewareStack(), new EventDispatcher(), new LockFactory(new InMemoryStore()))); $scheduler->schedule($task); @@ -1200,7 +775,7 @@ public function testDueTasksCannotBeReturnedWithPreviousStartDateAndCurrentEndDa 'execution_mode' => 'first_in_first_out', ]), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(), new EventDispatcher())); + ])), new SchedulerMiddlewareStack(), new EventDispatcher(), new LockFactory(new InMemoryStore()))); $scheduler->schedule($task); @@ -1225,7 +800,7 @@ public function testDueTasksCannotBeReturnedWithPreviousStartDateAndCurrentEndDa 'execution_mode' => 'first_in_first_out', ]), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(), new EventDispatcher())); + ])), new SchedulerMiddlewareStack(), new EventDispatcher(), new LockFactory(new InMemoryStore()))); $scheduler->schedule($task); @@ -1250,7 +825,7 @@ public function testDueTasksCanBeReturnedWithPreviousStartDateAndFutureEndDate() 'execution_mode' => 'first_in_first_out', ]), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(), new EventDispatcher())); + ])), new SchedulerMiddlewareStack(), new EventDispatcher(), new LockFactory(new InMemoryStore()))); $scheduler->schedule($task); @@ -1275,7 +850,7 @@ public function testDueTasksCannotBeReturnedWithFutureStartDateAndFutureEndDate( 'execution_mode' => 'first_in_first_out', ]), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(), new EventDispatcher())); + ])), new SchedulerMiddlewareStack(), new EventDispatcher(), new LockFactory(new InMemoryStore()))); $scheduler->schedule($task); @@ -1300,7 +875,7 @@ public function testDueTasksCannotBeReturnedWithFutureStartDateAndFutureEndDateU 'execution_mode' => 'first_in_first_out', ]), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(), new EventDispatcher())); + ])), new SchedulerMiddlewareStack(), new EventDispatcher(), new LockFactory(new InMemoryStore()))); $scheduler->schedule($task); @@ -1380,7 +955,7 @@ public function testSchedulerCannotYieldTaskAsynchronouslyWithMessageBus(): void ->willReturn(new Envelope(new stdClass())) ; - $scheduler = new FiberScheduler(new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher(), $bus)); + $scheduler = new FiberScheduler(new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher(), new LockFactory(new InMemoryStore()), new NullLogger(), $bus)); $scheduler->yieldTask('foo', true); } @@ -1415,7 +990,7 @@ public function testSchedulerCanLockTaskWithInvalidLockFactory(): void 'execution_mode' => 'first_in_first_out', ]), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack([]), new EventDispatcher())); + ])), new SchedulerMiddlewareStack([]), new EventDispatcher(), new LockFactory(new InMemoryStore()))); $scheduler->schedule(new NullTask('foo')); @@ -1461,7 +1036,7 @@ public function testSchedulerCanLockTaskWithValidLockFactory(): void $scheduler = new FiberScheduler(new Scheduler('UTC', new InMemoryTransport(new InMemoryConfiguration(), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack([]), new EventDispatcher())); + ])), new SchedulerMiddlewareStack([]), new EventDispatcher(), new LockFactory(new InMemoryStore()))); $scheduler->schedule(new NullTask('foo')); @@ -1484,7 +1059,7 @@ public function testSchedulerCannotReturnNextDueTaskWhenEmpty(): void $scheduler = new FiberScheduler(new Scheduler('UTC', new InMemoryTransport(new InMemoryConfiguration(), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(), new EventDispatcher()), $logger); + ])), new SchedulerMiddlewareStack(), new EventDispatcher(), new LockFactory(new InMemoryStore())), $logger); self::assertCount(0, $scheduler->getDueTasks()); @@ -1506,7 +1081,7 @@ public function testSchedulerCannotReturnNextDueTaskWhenASingleTaskIsFound(): vo $scheduler = new FiberScheduler(new Scheduler('UTC', new InMemoryTransport(new InMemoryConfiguration(), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(), new EventDispatcher()), $logger); + ])), new SchedulerMiddlewareStack(), new EventDispatcher(), new LockFactory(new InMemoryStore())), $logger); self::assertCount(0, $scheduler->getDueTasks()); @@ -1519,103 +1094,6 @@ public function testSchedulerCannotReturnNextDueTaskWhenASingleTaskIsFound(): vo $scheduler->next(); } - /** - * @throws Throwable {@see Scheduler::__construct()} - * @throws Throwable {@see SchedulerInterface::schedule()} - * @throws Throwable {@see SchedulerInterface::getDueTasks()} - */ - public function testSchedulerCanReturnNextDueTask(): void - { - $scheduler = new FiberScheduler(new Scheduler('UTC', new InMemoryTransport(new InMemoryConfiguration(), new SchedulePolicyOrchestrator([ - new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(), new EventDispatcher())); - - $scheduler->schedule(new NullTask('foo')); - $scheduler->schedule(new NullTask('bar')); - - self::assertCount(2, $scheduler->getDueTasks()); - - $nextDueTask = $scheduler->next(); - self::assertInstanceOf(NullTask::class, $nextDueTask); - self::assertSame('bar', $nextDueTask->getName()); - } - - /** - * @throws Throwable {@see Scheduler::__construct()} - * @throws Throwable {@see SchedulerInterface::schedule()} - * @throws Throwable {@see SchedulerInterface::getDueTasks()} - */ - public function testSchedulerCanReturnNextDueTaskAsynchronously(): void - { - $scheduler = new FiberScheduler(new Scheduler('UTC', new InMemoryTransport(new InMemoryConfiguration(), new SchedulePolicyOrchestrator([ - new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(), new EventDispatcher())); - - $scheduler->schedule(new NullTask('foo')); - $scheduler->schedule(new NullTask('bar')); - - $nextDueTask = $scheduler->next(true); - self::assertInstanceOf(LazyTask::class, $nextDueTask); - self::assertFalse($nextDueTask->isInitialized()); - self::assertSame('bar.lazy', $nextDueTask->getName()); - - $task = $nextDueTask->getTask(); - self::assertTrue($nextDueTask->isInitialized()); - self::assertInstanceOf(NullTask::class, $task); - self::assertSame('bar', $task->getName()); - } - - /** - * @throws Throwable {@see Scheduler::__construct()} - */ - public function testSchedulerCanRebootWithEmptyTasks(): void - { - $scheduler = new FiberScheduler(new Scheduler('UTC', new InMemoryTransport(new InMemoryConfiguration(), new SchedulePolicyOrchestrator([ - new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher())); - - $scheduler->schedule(new NullTask('bar')); - self::assertCount(1, $scheduler->getTasks()); - - $scheduler->reboot(); - self::assertCount(0, $scheduler->getTasks()); - } - - /** - * @throws Throwable {@see Scheduler::__construct()} - */ - public function testSchedulerCanReboot(): void - { - $scheduler = new FiberScheduler(new Scheduler('UTC', new InMemoryTransport(new InMemoryConfiguration(), new SchedulePolicyOrchestrator([ - new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher())); - - $scheduler->schedule(new NullTask('foo', [ - 'expression' => '@reboot', - ])); - $scheduler->schedule(new NullTask('bar')); - self::assertCount(2, $scheduler->getTasks()); - - $scheduler->reboot(); - self::assertCount(1, $scheduler->getTasks()); - } - - /** - * @throws Throwable {@see Scheduler::__construct()} - * @throws Throwable {@see SchedulerInterface::schedule()} - */ - public function testSchedulerCannotPreemptEmptyDueTasks(): void - { - $task = new NullTask('foo'); - - $scheduler = new FiberScheduler(new Scheduler('UTC', new InMemoryTransport(new InMemoryConfiguration(), new SchedulePolicyOrchestrator([ - new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(), new EventDispatcher())); - - $scheduler->preempt('foo', fn (TaskInterface $task): bool => $task->getName() === 'bar'); - self::assertNotSame(TaskInterface::READY_TO_EXECUTE, $task->getState()); - } - /** * @throws Throwable {@see Scheduler::__construct()} * @throws Throwable {@see SchedulerInterface::getDueTasks()} @@ -1627,7 +1105,7 @@ public function testSchedulerCannotPreemptEmptyToPreemptTasks(): void $scheduler = new FiberScheduler(new Scheduler('UTC', new InMemoryTransport(new InMemoryConfiguration(), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(), $eventDispatcher)); + ])), new SchedulerMiddlewareStack(), $eventDispatcher, new LockFactory(new InMemoryStore()))); $scheduler->schedule(new NullTask('foo')); $scheduler->preempt('foo', static fn (TaskInterface $task): bool => $task->getName() === 'bar'); @@ -1647,12 +1125,12 @@ public function testSchedulerCanPreemptTasks(): void new FirstInFirstOutPolicy(), ])); - $scheduler = new FiberScheduler(new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), $eventDispatcher)); + $scheduler = new FiberScheduler(new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), $eventDispatcher, new LockFactory(new InMemoryStore()))); $scheduler->schedule(new NullTask('foo')); $scheduler->schedule(new NullTask('bar')); $scheduler->schedule(new NullTask('reboot')); - $scheduler->preempt('foo', fn (TaskInterface $task): bool => $task->getName() === 'reboot'); + $scheduler->preempt('foo', static fn (TaskInterface $task): bool => $task->getName() === 'reboot'); $lockFactory = new LockFactory(new InMemoryStore()); diff --git a/tests/HttpSchedulerTest.php b/tests/HttpSchedulerTest.php index a6f57aab..db1f7801 100644 --- a/tests/HttpSchedulerTest.php +++ b/tests/HttpSchedulerTest.php @@ -42,32 +42,32 @@ final class HttpSchedulerTest extends TestCase { public function testSchedulerCannotScheduleWithInvalidResponse(): void { - $httpClientMock = new MockHttpClient([ - new MockResponse('', [ + $httpClientMock = new MockHttpClient(responseFactory: [ + new MockResponse(body: '', info: [ 'http_code' => 500, ]), - ], 'https://127.0.0.1:9090'); + ], baseUri: 'https://127.0.0.1:9090'); - $scheduler = new HttpScheduler('https://127.0.0.1:9090', $this->getSerializer(), $httpClientMock); + $scheduler = new HttpScheduler(externalSchedulerEndpoint: 'https://127.0.0.1:9090', serializer: $this->getSerializer(), httpClient: $httpClientMock); - self::expectException(RuntimeException::class); - self::expectExceptionMessage('The task "foo" cannot be scheduled'); - self::expectExceptionCode(0); - $scheduler->schedule(new NullTask('foo')); + self::expectException(exception: RuntimeException::class); + self::expectExceptionMessage(message: 'The task "foo" cannot be scheduled'); + self::expectExceptionCode(code: 0); + $scheduler->schedule(task: new NullTask(name: 'foo')); } public function testSchedulerCanSchedule(): void { - $httpClientMock = new MockHttpClient([ - new MockResponse('', [ + $httpClientMock = new MockHttpClient(responseFactory: [ + new MockResponse(body: '', info: [ 'http_code' => 201, ]), - ], 'https://127.0.0.1:9090'); + ], baseUri: 'https://127.0.0.1:9090'); - $scheduler = new HttpScheduler('https://127.0.0.1:9090', $this->getSerializer(), $httpClientMock); - $scheduler->schedule(new NullTask('foo')); + $scheduler = new HttpScheduler(externalSchedulerEndpoint: 'https://127.0.0.1:9090', serializer: $this->getSerializer(), httpClient: $httpClientMock); + $scheduler->schedule(task: new NullTask(name: 'foo')); - self::assertSame(1, $httpClientMock->getRequestsCount()); + self::assertSame(expected: 1, actual: $httpClientMock->getRequestsCount()); } public function testSchedulerCanScheduleWithCustomHttpClient(): void @@ -718,6 +718,7 @@ public function testSchedulerCannotGetDueTasksWithInvalidResponseAndMockedClient 'query' => [ 'lazy' => false, 'strict' => false, + 'lock' => false, ], ]))->willReturn(new MockResponse('', [ 'http_code' => 500, @@ -744,6 +745,7 @@ public function testSchedulerCannotGetDueTasksLazilyWithInvalidResponseAndMocked 'query' => [ 'lazy' => true, 'strict' => false, + 'lock' => false, ], ]))->willReturn(new MockResponse('', [ 'http_code' => 500, @@ -770,6 +772,7 @@ public function testSchedulerCannotGetDueTasksLazilyAndStrictlyWithInvalidRespon 'query' => [ 'lazy' => true, 'strict' => true, + 'lock' => false, ], ]))->willReturn(new MockResponse('', [ 'http_code' => 500, @@ -949,18 +952,18 @@ public function testSchedulerCannotGetNextTasksLazilyWithInvalidResponseAndMocke public function testSchedulerCanGetNextTask(): void { $serializer = $this->getSerializer(); - $payload = $serializer->serialize(new NullTask('foo'), 'json'); + $payload = $serializer->serialize(data: new NullTask(name: 'foo'), format: 'json'); - $httpClientMock = new MockHttpClient([ - new MockResponse($payload, [ + $httpClientMock = new MockHttpClient(responseFactory: [ + new MockResponse(body: $payload, info: [ 'http_code' => 200, ]), - ], 'https://127.0.0.1:9090'); + ], baseUri: 'https://127.0.0.1:9090'); - $scheduler = new HttpScheduler('https://127.0.0.1:9090', $serializer, $httpClientMock); + $scheduler = new HttpScheduler(externalSchedulerEndpoint: 'https://127.0.0.1:9090', serializer: $serializer, httpClient: $httpClientMock); $task = $scheduler->next(); - self::assertSame('foo', $task->getName()); + self::assertSame(expected: 'foo', actual: $task->getName()); } /** @@ -969,18 +972,18 @@ public function testSchedulerCanGetNextTask(): void public function testSchedulerCanGetNextTaskLazily(): void { $serializer = $this->getSerializer(); - $payload = $serializer->serialize(new NullTask('foo'), 'json'); + $payload = $serializer->serialize(data: new NullTask(name: 'foo'), format: 'json'); - $httpClientMock = new MockHttpClient([ - new MockResponse($payload, [ + $httpClientMock = new MockHttpClient(responseFactory: [ + new MockResponse(body: $payload, info: [ 'http_code' => 200, ]), - ], 'https://127.0.0.1:9090'); + ], baseUri: 'https://127.0.0.1:9090'); - $scheduler = new HttpScheduler('https://127.0.0.1:9090', $serializer, $httpClientMock); - $task = $scheduler->next(true); + $scheduler = new HttpScheduler(externalSchedulerEndpoint: 'https://127.0.0.1:9090', serializer: $serializer, httpClient: $httpClientMock); + $task = $scheduler->next(lazy: true); - self::assertSame('foo', $task->getName()); + self::assertSame(expected: 'foo.lazy', actual: $task->getName()); } /** diff --git a/tests/LazySchedulerTest.php b/tests/LazySchedulerTest.php index 3088f8cd..2fb9b771 100644 --- a/tests/LazySchedulerTest.php +++ b/tests/LazySchedulerTest.php @@ -9,6 +9,7 @@ use Generator; use PHPUnit\Framework\TestCase; use Psr\Log\LoggerInterface; +use Psr\Log\NullLogger; use SchedulerBundle\Exception\InvalidArgumentException; use SchedulerBundle\Exception\RuntimeException; use SchedulerBundle\LazyScheduler; @@ -66,7 +67,7 @@ public function testSchedulerCanSchedule(): void { $lazyScheduler = new LazyScheduler(sourceScheduler: new Scheduler(timezone: 'UTC', transport: new InMemoryTransport(configuration: new InMemoryConfiguration(), schedulePolicyOrchestrator: new SchedulePolicyOrchestrator(policies: [ new FirstInFirstOutPolicy(), - ])), middlewareStack: new SchedulerMiddlewareStack(new MiddlewareRegistry([])), eventDispatcher: new EventDispatcher())); + ])), middlewareStack: new SchedulerMiddlewareStack(new MiddlewareRegistry([])), eventDispatcher: new EventDispatcher(), lockFactory: new LockFactory(new InMemoryStore()))); self::assertFalse(condition: $lazyScheduler->isInitialized()); @@ -87,7 +88,7 @@ public function testSchedulerCanUnscheduleWhenNotInitialized(): void { $lazyScheduler = new LazyScheduler(sourceScheduler: new Scheduler(timezone: 'UTC', transport: new InMemoryTransport(configuration: new InMemoryConfiguration(), schedulePolicyOrchestrator: new SchedulePolicyOrchestrator(policies: [ new FirstInFirstOutPolicy(), - ])), middlewareStack: new SchedulerMiddlewareStack(new MiddlewareRegistry([])), eventDispatcher: new EventDispatcher())); + ])), middlewareStack: new SchedulerMiddlewareStack(new MiddlewareRegistry([])), eventDispatcher: new EventDispatcher(), lockFactory: new LockFactory(new InMemoryStore()))); self::assertFalse($lazyScheduler->isInitialized()); @@ -104,7 +105,7 @@ public function testSchedulerCanUnschedule(): void { $lazyScheduler = new LazyScheduler(sourceScheduler: new Scheduler(timezone: 'UTC', transport: new InMemoryTransport(configuration: new InMemoryConfiguration(), schedulePolicyOrchestrator: new SchedulePolicyOrchestrator(policies: [ new FirstInFirstOutPolicy(), - ])), middlewareStack: new SchedulerMiddlewareStack(new MiddlewareRegistry([])), eventDispatcher: new EventDispatcher())); + ])), middlewareStack: new SchedulerMiddlewareStack(new MiddlewareRegistry([])), eventDispatcher: new EventDispatcher(), lockFactory: new LockFactory(new InMemoryStore()))); self::assertFalse($lazyScheduler->isInitialized()); @@ -123,7 +124,7 @@ public function testSchedulerCannotYieldUndefinedTask(): void { $scheduler = new Scheduler('UTC', new InMemoryTransport(new InMemoryConfiguration(), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher()); + ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher(), new LockFactory(new InMemoryStore())); $lazyScheduler = new LazyScheduler($scheduler); self::assertFalse($lazyScheduler->isInitialized()); @@ -144,7 +145,7 @@ public function testSchedulerCanYield(): void $scheduler = new Scheduler('UTC', new InMemoryTransport(new InMemoryConfiguration(), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher(), $bus); + ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher(), new LockFactory(new InMemoryStore()), new NullLogger(), $bus); $lazyScheduler = new LazyScheduler($scheduler); self::assertFalse($lazyScheduler->isInitialized()); @@ -169,7 +170,7 @@ public function testSchedulerCanYieldAsynchronously(): void $scheduler = new Scheduler('UTC', new InMemoryTransport(new InMemoryConfiguration(), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher(), $bus); + ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher(), new LockFactory(new InMemoryStore()), new NullLogger(), $bus); $lazyScheduler = new LazyScheduler($scheduler); self::assertFalse($lazyScheduler->isInitialized()); @@ -188,7 +189,7 @@ public function testSchedulerCannotPauseUndefinedTask(): void { $scheduler = new Scheduler('UTC', new InMemoryTransport(new InMemoryConfiguration(), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher()); + ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher(), new LockFactory(new InMemoryStore())); $lazyScheduler = new LazyScheduler($scheduler); self::assertFalse($lazyScheduler->isInitialized()); @@ -210,7 +211,7 @@ public function testSchedulerCanPause(): void $scheduler = new Scheduler('UTC', new InMemoryTransport(new InMemoryConfiguration(), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher(), $bus); + ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher(), new LockFactory(new InMemoryStore()), new NullLogger(), $bus); $lazyScheduler = new LazyScheduler($scheduler); self::assertFalse($lazyScheduler->isInitialized()); @@ -240,7 +241,7 @@ public function testSchedulerCanPauseAsynchronously(): void $scheduler = new Scheduler('UTC', new InMemoryTransport(new InMemoryConfiguration(), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher(), $bus); + ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher(), new LockFactory(new InMemoryStore()), new NullLogger(), $bus); $lazyScheduler = new LazyScheduler($scheduler); self::assertFalse($lazyScheduler->isInitialized()); @@ -264,7 +265,7 @@ public function testSchedulerCannotResumeUndefinedTask(): void { $scheduler = new Scheduler('UTC', new InMemoryTransport(new InMemoryConfiguration(), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher()); + ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher(), new LockFactory(new InMemoryStore())); $lazyScheduler = new LazyScheduler($scheduler); self::assertFalse($lazyScheduler->isInitialized()); @@ -283,7 +284,7 @@ public function testSchedulerCanResume(): void { $scheduler = new Scheduler('UTC', new InMemoryTransport(new InMemoryConfiguration(), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher()); + ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher(), new LockFactory(new InMemoryStore())); $lazyScheduler = new LazyScheduler($scheduler); self::assertFalse($lazyScheduler->isInitialized()); @@ -314,7 +315,7 @@ public function testSchedulerCanGetTasksWhenEmpty(): void { $scheduler = new Scheduler('UTC', new InMemoryTransport(new InMemoryConfiguration(), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher()); + ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher(), new LockFactory(new InMemoryStore())); $lazyScheduler = new LazyScheduler($scheduler); self::assertFalse($lazyScheduler->isInitialized()); @@ -332,7 +333,7 @@ public function testSchedulerCanGetTasks(): void { $scheduler = new Scheduler('UTC', new InMemoryTransport(new InMemoryConfiguration(), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher()); + ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher(), new LockFactory(new InMemoryStore())); $lazyScheduler = new LazyScheduler($scheduler); self::assertFalse($lazyScheduler->isInitialized()); @@ -354,7 +355,7 @@ public function testSchedulerCanGetTasksLazilyWhenEmpty(): void { $scheduler = new Scheduler('UTC', new InMemoryTransport(new InMemoryConfiguration(), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher()); + ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher(), new LockFactory(new InMemoryStore())); $lazyScheduler = new LazyScheduler($scheduler); self::assertFalse($lazyScheduler->isInitialized()); @@ -372,7 +373,7 @@ public function testSchedulerCanGetTasksLazily(): void { $scheduler = new Scheduler('UTC', new InMemoryTransport(new InMemoryConfiguration(), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher()); + ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher(), new LockFactory(new InMemoryStore())); $lazyScheduler = new LazyScheduler($scheduler); self::assertFalse($lazyScheduler->isInitialized()); @@ -401,7 +402,7 @@ public function testSchedulerCanGetDueTasksWhenEmpty(): void { $scheduler = new Scheduler('UTC', new InMemoryTransport(new InMemoryConfiguration(), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher()); + ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher(), new LockFactory(new InMemoryStore())); $lazyScheduler = new LazyScheduler($scheduler); self::assertFalse($lazyScheduler->isInitialized()); @@ -419,7 +420,7 @@ public function testSchedulerCanGetDueTasks(): void { $scheduler = new Scheduler('UTC', new InMemoryTransport(new InMemoryConfiguration(), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher()); + ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher(), new LockFactory(new InMemoryStore())); $lazyScheduler = new LazyScheduler($scheduler); self::assertFalse($lazyScheduler->isInitialized()); @@ -441,7 +442,7 @@ public function testSchedulerCanGetDueTasksLazilyWhenEmpty(): void { $scheduler = new Scheduler('UTC', new InMemoryTransport(new InMemoryConfiguration(), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher()); + ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher(), new LockFactory(new InMemoryStore())); $lazyScheduler = new LazyScheduler($scheduler); self::assertFalse($lazyScheduler->isInitialized()); @@ -459,7 +460,7 @@ public function testSchedulerCanGetDueTasksLazily(): void { $scheduler = new Scheduler('UTC', new InMemoryTransport(new InMemoryConfiguration(), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher()); + ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher(), new LockFactory(new InMemoryStore())); $lazyScheduler = new LazyScheduler($scheduler); self::assertFalse($lazyScheduler->isInitialized()); @@ -481,7 +482,7 @@ public function testSchedulerCannotGetNextDueTasksLazilyWhenEmpty(): void { $scheduler = new Scheduler('UTC', new InMemoryTransport(new InMemoryConfiguration(), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher()); + ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher(), new LockFactory(new InMemoryStore())); $lazyScheduler = new LazyScheduler($scheduler); self::assertFalse($lazyScheduler->isInitialized()); @@ -500,7 +501,7 @@ public function testSchedulerCannotGetNextDueTasksLazilyWhenASingleTaskIsFound() { $scheduler = new Scheduler('UTC', new InMemoryTransport(new InMemoryConfiguration(), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher()); + ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher(), new LockFactory(new InMemoryStore())); $lazyScheduler = new LazyScheduler($scheduler); self::assertFalse($lazyScheduler->isInitialized()); @@ -522,7 +523,7 @@ public function testSchedulerCanGetNextDueTasksWhenSingleTaskFound(): void { $scheduler = new Scheduler('UTC', new InMemoryTransport(new InMemoryConfiguration(), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher()); + ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher(), new LockFactory(new InMemoryStore())); $lazyScheduler = new LazyScheduler($scheduler); self::assertFalse($lazyScheduler->isInitialized()); @@ -543,7 +544,7 @@ public function testSchedulerCanGetNextDueTasks(): void { $scheduler = new Scheduler('UTC', new InMemoryTransport(new InMemoryConfiguration(), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher()); + ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher(), new LockFactory(new InMemoryStore())); $lazyScheduler = new LazyScheduler($scheduler); self::assertFalse($lazyScheduler->isInitialized()); @@ -565,7 +566,7 @@ public function testSchedulerCanGetNextDueTasksLazily(): void { $scheduler = new Scheduler('UTC', new InMemoryTransport(new InMemoryConfiguration(), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher()); + ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher(), new LockFactory(new InMemoryStore())); $lazyScheduler = new LazyScheduler($scheduler); self::assertFalse($lazyScheduler->isInitialized()); @@ -594,7 +595,7 @@ public function testSchedulerCanRebootAndInitializeItselfWithEmptyTasks(): void { $lazyScheduler = new LazyScheduler(new Scheduler('UTC', new InMemoryTransport(new InMemoryConfiguration(), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher())); + ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher(), new LockFactory(new InMemoryStore()))); self::assertFalse($lazyScheduler->isInitialized()); $lazyScheduler->reboot(); @@ -610,7 +611,7 @@ public function testSchedulerCanRebootWithEmptyTasks(): void { $lazyScheduler = new LazyScheduler(new Scheduler('UTC', new InMemoryTransport(new InMemoryConfiguration(), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher())); + ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher(), new LockFactory(new InMemoryStore()))); self::assertFalse($lazyScheduler->isInitialized()); $lazyScheduler->schedule(new NullTask('bar')); @@ -630,7 +631,7 @@ public function testSchedulerCanReboot(): void { $lazyScheduler = new LazyScheduler(new Scheduler('UTC', new InMemoryTransport(new InMemoryConfiguration(), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher())); + ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher(), new LockFactory(new InMemoryStore()))); self::assertFalse($lazyScheduler->isInitialized()); $lazyScheduler->schedule(new NullTask('foo', [ @@ -652,7 +653,7 @@ public function testTimezoneCanBeReturned(): void { $scheduler = new Scheduler('UTC', new InMemoryTransport(new InMemoryConfiguration(), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher()); + ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher(), new LockFactory(new InMemoryStore())); $lazyScheduler = new LazyScheduler($scheduler); @@ -671,7 +672,7 @@ public function testSchedulerCannotPreemptEmptyDueTasks(): void $scheduler = new LazyScheduler(new Scheduler('UTC', new InMemoryTransport(new InMemoryConfiguration(), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher())); + ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher(), new LockFactory(new InMemoryStore()))); self::assertFalse($scheduler->isInitialized()); $scheduler->preempt('foo', static fn (TaskInterface $task): bool => $task->getName() === 'bar'); @@ -689,7 +690,7 @@ public function testSchedulerCannotPreemptEmptyToPreemptTasks(): void $scheduler = new LazyScheduler(new Scheduler('UTC', new InMemoryTransport(new InMemoryConfiguration(), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), $eventDispatcher)); + ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), $eventDispatcher, new LockFactory(new InMemoryStore()))); self::assertFalse($scheduler->isInitialized()); $scheduler->schedule(new NullTask('foo')); @@ -710,7 +711,7 @@ public function testSchedulerCanPreemptTasks(): void new FirstInFirstOutPolicy(), ])); - $scheduler = new LazyScheduler(new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(new MiddlewareRegistry([])), $eventDispatcher)); + $scheduler = new LazyScheduler(new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(new MiddlewareRegistry([])), $eventDispatcher, new LockFactory(new InMemoryStore()))); self::assertFalse($scheduler->isInitialized()); $scheduler->schedule(new NullTask('foo')); @@ -773,7 +774,7 @@ public function testTaskCanBeUpdated(TaskInterface $task): void 'execution_mode' => 'first_in_first_out', ]), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher(), $bus)); + ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher(), new LockFactory(new InMemoryStore()), new NullLogger(), $bus)); self::assertFalse($scheduler->isInitialized()); $scheduler->schedule($task); @@ -809,7 +810,7 @@ public function testTaskCanBeUpdatedAsynchronously(): void ])), ]); - $scheduler = new LazyScheduler(new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher(), $bus)); + $scheduler = new LazyScheduler(new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher(), new LockFactory(new InMemoryStore()), new NullLogger(), $bus)); self::assertFalse($scheduler->isInitialized()); $scheduler->schedule($task); @@ -835,7 +836,7 @@ public function testSchedulerCanReturnTheTimezone(): void 'execution_mode' => 'first_in_first_out', ]), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(), new EventDispatcher())); + ])), new SchedulerMiddlewareStack(), new EventDispatcher(), new LockFactory(new InMemoryStore()))); self::assertFalse($scheduler->isInitialized()); $timezone = $scheduler->getTimezone(); @@ -851,7 +852,7 @@ public function testSchedulerPoolConfigurationIsAvailable(): void { $scheduler = new LazyScheduler(new Scheduler('UTC', new InMemoryTransport(new InMemoryConfiguration(), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher())); + ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher(), new LockFactory(new InMemoryStore()))); $poolConfiguration = $scheduler->getPoolConfiguration(); diff --git a/tests/Messenger/TaskToExecuteMessageHandlerTest.php b/tests/Messenger/TaskToExecuteMessageHandlerTest.php index 70225fa6..c41df4ce 100644 --- a/tests/Messenger/TaskToExecuteMessageHandlerTest.php +++ b/tests/Messenger/TaskToExecuteMessageHandlerTest.php @@ -8,12 +8,31 @@ use DateTimeZone; use PHPUnit\Framework\TestCase; use Psr\Log\LoggerInterface; +use Psr\Log\NullLogger; use SchedulerBundle\Messenger\TaskToExecuteMessage; use SchedulerBundle\Messenger\TaskToExecuteMessageHandler; +use SchedulerBundle\Middleware\SchedulerMiddlewareStack; +use SchedulerBundle\Middleware\WorkerMiddlewareStack; +use SchedulerBundle\Runner\NullTaskRunner; +use SchedulerBundle\Runner\RunnerRegistry; +use SchedulerBundle\Runner\ShellTaskRunner; +use SchedulerBundle\SchedulePolicy\FirstInFirstOutPolicy; +use SchedulerBundle\SchedulePolicy\SchedulePolicyOrchestrator; +use SchedulerBundle\Scheduler; +use SchedulerBundle\Task\NullTask; use SchedulerBundle\Task\ShellTask; -use SchedulerBundle\Task\TaskInterface; +use SchedulerBundle\Task\TaskExecutionTracker; +use SchedulerBundle\Transport\Configuration\InMemoryConfiguration; +use SchedulerBundle\Transport\InMemoryTransport; +use SchedulerBundle\Worker\ExecutionPolicy\DefaultPolicy; +use SchedulerBundle\Worker\ExecutionPolicy\ExecutionPolicyRegistry; +use SchedulerBundle\Worker\Worker; use SchedulerBundle\Worker\WorkerConfiguration; use SchedulerBundle\Worker\WorkerInterface; +use Symfony\Component\EventDispatcher\EventDispatcher; +use Symfony\Component\Lock\LockFactory; +use Symfony\Component\Lock\Store\InMemoryStore; +use Symfony\Component\Stopwatch\Stopwatch; /** * @author Guillaume Loulier @@ -24,33 +43,63 @@ final class TaskToExecuteMessageHandlerTest extends TestCase { public function testHandlerCanRunDueTaskWithoutASpecificTimezone(): void { - $task = $this->createMock(TaskInterface::class); - $task->expects(self::once())->method('getExpression')->willReturn('* * * * *'); - $task->expects(self::once())->method('getTimezone')->willReturn(null); - - $worker = $this->createMock(WorkerInterface::class); - $worker->expects(self::once())->method('isRunning')->willReturn(false); - $worker->expects(self::once())->method('execute')->with(WorkerConfiguration::create(), $task); - - $taskMessageHandler = new TaskToExecuteMessageHandler($worker); - - ($taskMessageHandler)(new TaskToExecuteMessage($task)); + $task = new NullTask(name: 'foo', options: [ + 'timezone' => null, + ]); + + $worker = new Worker( + scheduler: new Scheduler(timezone: 'UTC', transport: new InMemoryTransport(configuration: new InMemoryConfiguration(), schedulePolicyOrchestrator: new SchedulePolicyOrchestrator(policies: [ + new FirstInFirstOutPolicy(), + ])), middlewareStack: new SchedulerMiddlewareStack([]), eventDispatcher: new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())), + runnerRegistry: new RunnerRegistry(runners: [ + new NullTaskRunner(), + ]), + executionPolicyRegistry: new ExecutionPolicyRegistry(policies: [ + new DefaultPolicy(), + ]), + taskExecutionTracker: new TaskExecutionTracker(watch: new Stopwatch()), + middlewareStack: new WorkerMiddlewareStack(), + eventDispatcher: new EventDispatcher(), + lockFactory: new LockFactory(store: new InMemoryStore()), + logger: new NullLogger() + ); + + $taskMessageHandler = new TaskToExecuteMessageHandler(worker: $worker); + + ($taskMessageHandler)(taskMessage: new TaskToExecuteMessage(task: $task)); + + self::assertInstanceOf(expected: DateTimeImmutable::class, actual: $task->getLastExecution()); } public function testHandlerCanRunDueTask(): void { - $shellTask = new ShellTask('foo', ['echo', 'Symfony']); - $shellTask->setScheduledAt(new DateTimeImmutable()); - $shellTask->setExpression('* * * * *'); - $shellTask->setTimezone(new DateTimeZone('UTC')); - - $worker = $this->createMock(WorkerInterface::class); - $worker->expects(self::once())->method('isRunning')->willReturn(false); - $worker->expects(self::once())->method('execute')->with(WorkerConfiguration::create(), $shellTask); - - $taskMessageHandler = new TaskToExecuteMessageHandler($worker); - - ($taskMessageHandler)(new TaskToExecuteMessage($shellTask)); + $shellTask = new ShellTask(name: 'foo', command: ['echo', 'Symfony']); + $shellTask->setScheduledAt(scheduledAt: new DateTimeImmutable()); + $shellTask->setExpression(expression: '* * * * *'); + $shellTask->setTimezone(dateTimeZone: new DateTimeZone(timezone: 'UTC')); + + $worker = new Worker( + scheduler: new Scheduler(timezone: 'UTC', transport: new InMemoryTransport(configuration: new InMemoryConfiguration(), schedulePolicyOrchestrator: new SchedulePolicyOrchestrator(policies: [ + new FirstInFirstOutPolicy(), + ])), middlewareStack: new SchedulerMiddlewareStack([]), eventDispatcher: new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())), + runnerRegistry: new RunnerRegistry(runners: [ + new ShellTaskRunner(), + ]), + executionPolicyRegistry: new ExecutionPolicyRegistry(policies: [ + new DefaultPolicy(), + ]), + taskExecutionTracker: new TaskExecutionTracker(watch: new Stopwatch()), + middlewareStack: new WorkerMiddlewareStack(), + eventDispatcher: new EventDispatcher(), + lockFactory: new LockFactory(store: new InMemoryStore()), + logger: new NullLogger() + ); + + $taskMessageHandler = new TaskToExecuteMessageHandler(worker: $worker); + + ($taskMessageHandler)(taskMessage: new TaskToExecuteMessage(task: $shellTask)); + + self::assertInstanceOf(expected: DateTimeImmutable::class, actual: $shellTask->getLastExecution()); } public function testHandlerCanWaitForAvailableWorker(): void @@ -67,8 +116,8 @@ public function testHandlerCanWaitForAvailableWorker(): void $worker->expects(self::exactly(3))->method('isRunning')->willReturnOnConsecutiveCalls(true, true, false); $worker->expects(self::once())->method('execute')->with(WorkerConfiguration::create(), $shellTask); - $taskMessageHandler = new TaskToExecuteMessageHandler($worker, $logger); + $taskMessageHandler = new TaskToExecuteMessageHandler(worker: $worker, logger: $logger); - ($taskMessageHandler)(new TaskToExecuteMessage($shellTask, 2)); + ($taskMessageHandler)(taskMessage: new TaskToExecuteMessage($shellTask, 2)); } } diff --git a/tests/Middleware/TaskLockBagMiddlewareTest.php b/tests/Middleware/TaskLockBagMiddlewareTest.php index 07fc2e10..bad5b2d3 100644 --- a/tests/Middleware/TaskLockBagMiddlewareTest.php +++ b/tests/Middleware/TaskLockBagMiddlewareTest.php @@ -8,6 +8,7 @@ use Psr\Log\LoggerInterface; use SchedulerBundle\Exception\RuntimeException; use SchedulerBundle\Middleware\PostExecutionMiddlewareInterface; +use SchedulerBundle\Middleware\PreExecutionMiddlewareInterface; use SchedulerBundle\Middleware\TaskLockBagMiddleware; use SchedulerBundle\SchedulerInterface; use SchedulerBundle\Task\NullTask; @@ -31,6 +32,20 @@ public function testMiddlewareIsConfigured(): void self::assertSame(5, $middleware->getPriority()); } + /** + * @throws Throwable {@see PreExecutionMiddlewareInterface::preExecute()} + */ + public function testMiddlewareCannotAddAccessLockBagWithoutAcquiringTheTask(): void + { + } + + /** + * @throws Throwable {@see PreExecutionMiddlewareInterface::preExecute()} + */ + public function testMiddlewareCanAddAccessLockBag(): void + { + } + /** * @throws Throwable {@see PostExecutionMiddlewareInterface::postExecute()} */ diff --git a/tests/Pool/SchedulerPoolTest.php b/tests/Pool/SchedulerPoolTest.php index fbdef07a..abfaebff 100644 --- a/tests/Pool/SchedulerPoolTest.php +++ b/tests/Pool/SchedulerPoolTest.php @@ -14,42 +14,51 @@ use SchedulerBundle\Transport\Configuration\InMemoryConfiguration; use SchedulerBundle\Transport\InMemoryTransport; use Symfony\Component\EventDispatcher\EventDispatcher; +use Symfony\Component\Lock\LockFactory; +use Symfony\Component\Lock\Store\InMemoryStore; +use Throwable; /** * @author Guillaume Loulier */ final class SchedulerPoolTest extends TestCase { + /** + * @throws Throwable {@see Scheduler::__construct()} + */ public function testPoolCanAddScheduler(): void { $pool = new SchedulerPool(); self::assertCount(0, $pool); - $pool->add('https://127.0.0.1:9090', new Scheduler('UTC', new InMemoryTransport(new InMemoryConfiguration([ + $pool->add(endpoint: 'https://127.0.0.1:9090', scheduler: new Scheduler(timezone: 'UTC', transport: new InMemoryTransport(configuration: new InMemoryConfiguration(options: [ 'execution_mode' => 'first_in_first_out', - ]), new SchedulePolicyOrchestrator([ + ]), schedulePolicyOrchestrator: new SchedulePolicyOrchestrator(policies: [ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher())); + ])), middlewareStack: new SchedulerMiddlewareStack(new MiddlewareRegistry([])), eventDispatcher: new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore()))); self::assertCount(1, $pool); } + /** + * @throws Throwable {@see Scheduler::__construct()} + */ public function testPoolCanAddSchedulerAndReturnIt(): void { $pool = new SchedulerPool(); self::assertCount(0, $pool); - $pool->add('https://127.0.0.1:9090', new Scheduler('UTC', new InMemoryTransport(new InMemoryConfiguration([ + $pool->add(endpoint: 'https://127.0.0.1:9090', scheduler: new Scheduler(timezone: 'UTC', transport: new InMemoryTransport(configuration: new InMemoryConfiguration(options: [ 'execution_mode' => 'first_in_first_out', - ]), new SchedulePolicyOrchestrator([ + ]), schedulePolicyOrchestrator: new SchedulePolicyOrchestrator(policies: [ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher())); + ])), middlewareStack: new SchedulerMiddlewareStack(new MiddlewareRegistry([])), eventDispatcher: new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore()))); self::assertCount(1, $pool); - $scheduler = $pool->get('https://127.0.0.1:9090'); + $scheduler = $pool->get(endpoint: 'https://127.0.0.1:9090'); self::assertCount(0, $scheduler->getTasks()); } } diff --git a/tests/SchedulerTest.php b/tests/SchedulerTest.php index 464b4089..e91d23eb 100644 --- a/tests/SchedulerTest.php +++ b/tests/SchedulerTest.php @@ -10,6 +10,7 @@ use Generator; use PDO; use Psr\Log\LoggerInterface; +use Psr\Log\NullLogger; use SchedulerBundle\Event\TaskScheduledEvent; use SchedulerBundle\Event\TaskUnscheduledEvent; use SchedulerBundle\Exception\RuntimeException; @@ -37,7 +38,6 @@ use SchedulerBundle\Serializer\AccessLockBagNormalizer; use SchedulerBundle\Serializer\NotificationTaskBagNormalizer; use SchedulerBundle\Serializer\TaskNormalizer; -use SchedulerBundle\Task\LazyTask; use SchedulerBundle\Task\LazyTaskList; use SchedulerBundle\Task\MessengerTask; use SchedulerBundle\Task\NullTask; @@ -94,7 +94,7 @@ protected function getScheduler(): SchedulerInterface|FiberScheduler|LazySchedul 'execution_mode' => 'first_in_first_out', ]), schedulePolicyOrchestrator: new SchedulePolicyOrchestrator(policies: [ new FirstInFirstOutPolicy(), - ])), middlewareStack: new SchedulerMiddlewareStack(stack: new MiddlewareRegistry([])), eventDispatcher: new EventDispatcher()); + ])), middlewareStack: new SchedulerMiddlewareStack(stack: new MiddlewareRegistry([])), eventDispatcher: new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())); } /** @@ -109,7 +109,7 @@ public function testSchedulerCannotScheduleTasksWithErroredBeforeCallback(): voi new FirstInFirstOutPolicy(), ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([ new TaskCallbackMiddleware(), - ])), new EventDispatcher()); + ])), new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())); self::expectException(RuntimeException::class); self::expectExceptionMessage('The task cannot be scheduled'); @@ -119,27 +119,6 @@ public function testSchedulerCannotScheduleTasksWithErroredBeforeCallback(): voi ])); } - /** - * @throws Exception {@see Scheduler::__construct()} - * @throws Throwable {@see SchedulerInterface::schedule()} - */ - public function testSchedulerCanScheduleTasksWithBeforeCallback(): void - { - $scheduler = new Scheduler('UTC', new InMemoryTransport(new InMemoryConfiguration([ - 'execution_mode' => 'first_in_first_out', - ]), new SchedulePolicyOrchestrator([ - new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([ - new TaskCallbackMiddleware(), - ])), new EventDispatcher()); - - $scheduler->schedule(new NullTask('foo', [ - 'before_scheduling' => static fn (): int => 1 + 1, - ])); - - self::assertCount(1, $scheduler->getTasks()); - } - /** * @throws Exception {@see Scheduler::__construct()} * @throws Throwable {@see SchedulerInterface::schedule()} @@ -154,17 +133,12 @@ public function testSchedulerCanScheduleTasksWithBeforeSchedulingNotificationAnd $scheduler = new Scheduler('UTC', new InMemoryTransport(new InMemoryConfiguration([ 'execution_mode' => 'first_in_first_out', - ]), new SchedulePolicyOrchestrator([ + ]), schedulePolicyOrchestrator: new SchedulePolicyOrchestrator(policies: [ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([ - new TaskCallbackMiddleware(), + ])), middlewareStack: new SchedulerMiddlewareStack(stack: [ new NotifierMiddleware(), - ])), new EventDispatcher()); - - $scheduler->schedule(new NullTask('foo', [ - 'before_scheduling_notification' => new NotificationTaskBag($notification, $recipient), - ])); - self::assertCount(1, $scheduler->getTasks()); + new TaskCallbackMiddleware(), + ]), eventDispatcher: new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())); } /** @@ -186,7 +160,7 @@ public function testSchedulerCanScheduleTasksWithBeforeSchedulingNotificationAnd ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([ new TaskCallbackMiddleware(), new NotifierMiddleware($notifier), - ])), new EventDispatcher()); + ])), new EventDispatcher(), new LockFactory(new InMemoryStore())); $scheduler->schedule(new NullTask('foo', [ 'before_scheduling_notification' => new NotificationTaskBag($notification, $recipient), @@ -213,7 +187,7 @@ public function testSchedulerCanScheduleTasksWithAfterSchedulingNotificationAndW ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([ new TaskCallbackMiddleware(), new NotifierMiddleware(), - ])), new EventDispatcher()); + ])), new EventDispatcher(), new LockFactory(new InMemoryStore())); $scheduler->schedule(new NullTask('foo', [ 'after_scheduling_notification' => new NotificationTaskBag($notification, $recipient), @@ -240,7 +214,7 @@ public function testSchedulerCanScheduleTasksWithAfterSchedulingNotificationAndW ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([ new TaskCallbackMiddleware(), new NotifierMiddleware($notifier), - ])), new EventDispatcher()); + ])), new EventDispatcher(), new LockFactory(new InMemoryStore())); $scheduler->schedule(new NullTask('foo', [ 'after_scheduling_notification' => new NotificationTaskBag($notification, $recipient), @@ -271,7 +245,7 @@ public function testSchedulerCannotScheduleTasksWithErroredAfterCallback(): void new FirstInFirstOutPolicy(), ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([ new TaskCallbackMiddleware(), - ])), $eventDispatcher); + ])), $eventDispatcher, new LockFactory(new InMemoryStore())); self::expectException(RuntimeException::class); self::expectExceptionMessage('The task has encountered an error after scheduling, it has been unscheduled'); @@ -296,7 +270,7 @@ public function testSchedulerCanScheduleTasksWithAfterCallback(): void new FirstInFirstOutPolicy(), ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([ new TaskCallbackMiddleware(), - ])), new EventDispatcher()); + ])), new EventDispatcher(), new LockFactory(new InMemoryStore())); $scheduler->schedule(task: $task); self::assertCount(1, $scheduler->getTasks()); @@ -320,7 +294,7 @@ public function testSchedulerCanScheduleTasksWithMessageBus(): void 'execution_mode' => 'first_in_first_out', ]), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher(), $bus); + ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher(), new LockFactory(new InMemoryStore()), new NullLogger(), $bus); $scheduler->schedule($task); } @@ -345,7 +319,7 @@ public function testTaskCanBeScheduledWithEventDispatcherAndMessageBus(TaskInter 'execution_mode' => 'first_in_first_out', ]), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), $eventDispatcher, $bus); + ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), $eventDispatcher, new LockFactory(new InMemoryStore()), new NullLogger(), $bus); $task->setQueued(true); $scheduler->schedule($task); @@ -364,7 +338,7 @@ public function testTaskCanBeScheduledWithEventDispatcherAndMessageBus(TaskInter */ public function testMessengerTaskCanBeScheduledWithMessageBus(TransportInterface $transport): void { - $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher(), new MessageBus()); + $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher(), new LockFactory(new InMemoryStore()), new NullLogger(), new MessageBus()); $scheduler->schedule(new MessengerTask('bar', new stdClass())); @@ -386,7 +360,7 @@ public function testTaskCannotBeScheduledTwice(): void 'execution_mode' => 'first_in_first_out', ]), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher()); + ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher(), new LockFactory(new InMemoryStore())); $scheduler->schedule(task: $task); $scheduler->schedule(task: $secondTask); @@ -408,7 +382,7 @@ public function testDueTasksCanBeReturned(TaskInterface $task): void 'execution_mode' => 'first_in_first_out', ]), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher()); + ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher(), new LockFactory(new InMemoryStore())); $scheduler->schedule($task); @@ -436,7 +410,8 @@ public function testDueTasksCanBeReturnedStrictly(TaskInterface $task): void new FirstInFirstOutPolicy(), ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), - new EventDispatcher() + new EventDispatcher(), + new LockFactory(new InMemoryStore()) ); $scheduler->schedule($task); @@ -463,7 +438,8 @@ public function testDueTasksCanBeReturnedUsingLazyLoad(TaskInterface $task): voi new FirstInFirstOutPolicy(), ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), - new EventDispatcher() + new EventDispatcher(), + new LockFactory(new InMemoryStore()) ); $scheduler->schedule($task); @@ -493,7 +469,8 @@ public function testDueTasksCanBeReturnedStrictlyUsingLazyLoad(TaskInterface $ta new FirstInFirstOutPolicy(), ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), - new EventDispatcher() + new EventDispatcher(), + new LockFactory(new InMemoryStore()) ); $scheduler->schedule($task); @@ -515,7 +492,7 @@ public function testDueTasksCanBeReturnedWithSpecificFilter(TaskInterface $task) 'execution_mode' => 'first_in_first_out', ]), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher()); + ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher(), new LockFactory(new InMemoryStore())); $scheduler->schedule($task); $filteredTasks = $scheduler->getTasks()->filter(fn (TaskInterface $task): bool => null !== $task->getTimezone() && 0 === $task->getPriority()); @@ -535,7 +512,7 @@ public function testLazyDueTasksCanBeReturnedWithSpecificFilter(TaskInterface $t 'execution_mode' => 'first_in_first_out', ]), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher()); + ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher(), new LockFactory(new InMemoryStore())); $scheduler->schedule($task); $dueTasks = $scheduler->getTasks(true); @@ -557,16 +534,11 @@ public function testNonExecutedDueTasksCanBeReturned(): void 'last_execution' => new DateTimeImmutable(), ]); - $scheduler = new Scheduler( - 'UTC', - new InMemoryTransport(new InMemoryConfiguration([ - 'execution_mode' => 'first_in_first_out', - ]), new SchedulePolicyOrchestrator([ - new FirstInFirstOutPolicy(), - ])), - new SchedulerMiddlewareStack(new MiddlewareRegistry([])), - new EventDispatcher() - ); + $scheduler = new Scheduler('UTC', new InMemoryTransport(new InMemoryConfiguration([ + 'execution_mode' => 'first_in_first_out', + ]), new SchedulePolicyOrchestrator([ + new FirstInFirstOutPolicy(), + ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher(), new LockFactory(new InMemoryStore())); $scheduler->schedule($task); $scheduler->schedule($secondTask); @@ -601,7 +573,8 @@ public function testNonExecutedDueTasksCanBeReturnedUsingLazyLoad(): void new FirstInFirstOutPolicy(), ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), - new EventDispatcher() + new EventDispatcher(), + new LockFactory(new InMemoryStore()) ); $scheduler->schedule($task); @@ -640,7 +613,8 @@ public function testCurentMinuteExecutedDueTasksCannotBeReturned(): void new FirstInFirstOutPolicy(), ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), - new EventDispatcher() + new EventDispatcher(), + new LockFactory(new InMemoryStore()) ); $scheduler->schedule($task); @@ -677,7 +651,8 @@ public function testCurentMinuteExecutedDueTasksCannotBeReturnedUsingLazyLoad(): new FirstInFirstOutPolicy(), ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), - new EventDispatcher() + new EventDispatcher(), + new LockFactory(new InMemoryStore()) ); $scheduler->schedule($task); @@ -704,7 +679,8 @@ public function testDueTasksCanBeReturnedWithCurrentExecutionStartDate(): void new FirstInFirstOutPolicy(), ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), - new EventDispatcher() + new EventDispatcher(), + new LockFactory(new InMemoryStore()) ); $scheduler->schedule(new NullTask('foo', [ @@ -733,7 +709,8 @@ public function testDueTasksCanBeReturnedWithPastExecutionStartDate(): void new FirstInFirstOutPolicy(), ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), - new EventDispatcher() + new EventDispatcher(), + new LockFactory(new InMemoryStore()) ); $scheduler->schedule(new NullTask('foo', [ @@ -762,7 +739,8 @@ public function testDueTasksCanBeReturnedWithPastExecutionStartDateLazily(): voi new FirstInFirstOutPolicy(), ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), - new EventDispatcher() + new EventDispatcher(), + new LockFactory(new InMemoryStore()) ); $scheduler->schedule(new NullTask('foo', [ @@ -789,7 +767,7 @@ public function testTaskCanBeUnScheduled(TaskInterface $task): void 'execution_mode' => 'first_in_first_out', ]), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher()); + ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher(), new LockFactory(new InMemoryStore())); $scheduler->schedule($task); self::assertCount(1, $scheduler->getTasks()); @@ -809,7 +787,7 @@ public function testTaskCanBeUnScheduledAndLazilyRetrieved(TaskInterface $task): 'execution_mode' => 'first_in_first_out', ]), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher()); + ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher(), new LockFactory(new InMemoryStore())); $scheduler->schedule($task); self::assertInstanceOf(LazyTaskList::class, $scheduler->getTasks(true)); @@ -833,7 +811,7 @@ public function testTaskCanBeUpdated(): void $scheduler = new Scheduler('UTC', new InMemoryTransport(new InMemoryConfiguration(), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher(), $bus); + ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher(), new LockFactory(new InMemoryStore()), new NullLogger(), $bus); $scheduler->schedule($task); self::assertCount(1, $scheduler->getTasks()); @@ -862,7 +840,7 @@ public function testTaskCanBeUpdatedAsynchronously(): void ])), ]); - $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher(), $bus); + $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher(), new LockFactory(new InMemoryStore()), new NullLogger(), $bus); $scheduler->schedule($task); self::assertCount(1, $scheduler->getTasks()); @@ -889,7 +867,7 @@ public function testTaskCanBeUpdatedThenRetrieved(TaskInterface $task): void 'execution_mode' => 'first_in_first_out', ]), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher(), $bus); + ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher(), new LockFactory(new InMemoryStore()), new NullLogger(), $bus); $scheduler->schedule($task); self::assertCount(1, $scheduler->getTasks()->toArray()); @@ -915,7 +893,7 @@ public function testTaskCanBeUpdatedThenLazilyRetrieved(TaskInterface $task): vo 'execution_mode' => 'first_in_first_out', ]), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher(), $bus); + ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher(), new LockFactory(new InMemoryStore()), new NullLogger(), $bus); $scheduler->schedule($task); self::assertInstanceOf(LazyTaskList::class, $scheduler->getTasks(true)); @@ -943,7 +921,7 @@ public function testTaskCanBePausedAndResumed(TaskInterface $task): void 'execution_mode' => 'first_in_first_out', ]), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher(), $bus); + ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher(), new LockFactory(new InMemoryStore()), new NullLogger(), $bus); $scheduler->schedule($task); self::assertCount(1, $scheduler->getTasks()); @@ -968,7 +946,7 @@ public function testSchedulerCanPauseTaskWithoutMessageBus(): void $bus = $this->createMock(MessageBusInterface::class); $bus->expects(self::never())->method('dispatch'); - $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher()); + $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher(), new LockFactory(new InMemoryStore())); $scheduler->pause('foo', true); } @@ -986,7 +964,7 @@ public function testSchedulerCanPauseTaskWithMessageBus(): void ->willReturn(new Envelope(new stdClass())) ; - $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher(), $bus); + $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher(), new LockFactory(new InMemoryStore()), new NullLogger(), $bus); $scheduler->pause('foo', true); } @@ -1008,7 +986,7 @@ public function testDueTasksCanBeReturnedWithStartAndEndDate(): void 'execution_mode' => 'first_in_first_out', ]), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher()); + ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher(), new LockFactory(new InMemoryStore())); $scheduler->schedule($task); self::assertCount(1, $scheduler->getDueTasks()); @@ -1031,7 +1009,7 @@ public function testDueTasksCanBeReturnedWithStartAndEndDateUsingLazyLoad(): voi 'execution_mode' => 'first_in_first_out', ]), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher()); + ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher(), new LockFactory(new InMemoryStore())); $scheduler->schedule($task); @@ -1056,7 +1034,7 @@ public function testDueTasksCanBeReturnedWithCurrentStartDate(): void 'execution_mode' => 'first_in_first_out', ]), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher()); + ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher(), new LockFactory(new InMemoryStore())); $scheduler->schedule($task); self::assertCount(1, $scheduler->getDueTasks()); @@ -1078,7 +1056,7 @@ public function testDueTasksCanBeReturnedWithPreviousStartDate(): void 'execution_mode' => 'first_in_first_out', ]), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher()); + ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher(), new LockFactory(new InMemoryStore())); $scheduler->schedule($task); self::assertCount(1, $scheduler->getDueTasks()); @@ -1099,7 +1077,7 @@ public function testDueTasksCanBeReturnedWithPreviousStartDateUsingLazyLoad(): v 'execution_mode' => 'first_in_first_out', ]), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher()); + ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher(), new LockFactory(new InMemoryStore())); $scheduler->schedule($task); @@ -1124,7 +1102,7 @@ public function testDueTasksCanBeReturnedWithEndDate(): void 'execution_mode' => 'first_in_first_out', ]), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher()); + ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher(), new LockFactory(new InMemoryStore())); $scheduler->schedule($task); @@ -1146,7 +1124,7 @@ public function testDueTasksCanBeReturnedWithEndDateUsingLazyLoad(): void 'execution_mode' => 'first_in_first_out', ]), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher()); + ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher(), new LockFactory(new InMemoryStore())); $scheduler->schedule($task); @@ -1172,7 +1150,7 @@ public function testDueTasksCanBeReturnedWithCurrentStartDateAndFutureEndDate(): 'execution_mode' => 'first_in_first_out', ]), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher()); + ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher(), new LockFactory(new InMemoryStore())); $scheduler->schedule($task); @@ -1197,7 +1175,7 @@ public function testDueTasksCannotBeReturnedWithPreviousStartDateAndCurrentEndDa 'execution_mode' => 'first_in_first_out', ]), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher()); + ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher(), new LockFactory(new InMemoryStore())); $scheduler->schedule($task); @@ -1222,7 +1200,7 @@ public function testDueTasksCannotBeReturnedWithPreviousStartDateAndCurrentEndDa 'execution_mode' => 'first_in_first_out', ]), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher()); + ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher(), new LockFactory(new InMemoryStore())); $scheduler->schedule($task); @@ -1247,7 +1225,7 @@ public function testDueTasksCanBeReturnedWithPreviousStartDateAndFutureEndDate() 'execution_mode' => 'first_in_first_out', ]), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher()); + ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher(), new LockFactory(new InMemoryStore())); $scheduler->schedule($task); @@ -1272,7 +1250,7 @@ public function testDueTasksCannotBeReturnedWithFutureStartDateAndFutureEndDate( 'execution_mode' => 'first_in_first_out', ]), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher()); + ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher(), new LockFactory(new InMemoryStore())); $scheduler->schedule($task); @@ -1297,7 +1275,7 @@ public function testDueTasksCannotBeReturnedWithFutureStartDateAndFutureEndDateU 'execution_mode' => 'first_in_first_out', ]), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher()); + ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher(), new LockFactory(new InMemoryStore())); $scheduler->schedule($task); @@ -1322,7 +1300,7 @@ public function testSchedulerCanYieldTask(): void 'execution_mode' => 'first_in_first_out', ]), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher(), $bus); + ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher(), lockFactory: new LockFactory(new InMemoryStore()), bus: $bus); $scheduler->schedule($task); $scheduler->yieldTask(name: 'foo'); @@ -1347,7 +1325,7 @@ public function testSchedulerCannotYieldTaskAsynchronouslyWithoutMessageBus(): v 'execution_mode' => 'first_in_first_out', ]), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher()); + ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher(), lockFactory: new LockFactory(new InMemoryStore())); $scheduler->schedule(task: $task); $scheduler->yieldTask(name: 'foo', async: true); @@ -1376,7 +1354,7 @@ public function testSchedulerCannotYieldTaskAsynchronouslyWithMessageBus(): void $scheduler = new Scheduler('UTC', new InMemoryTransport(new InMemoryConfiguration(), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher(), $bus); + ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher(), new LockFactory(new InMemoryStore()), new NullLogger(), $bus); $scheduler->yieldTask('foo', true); self::assertCount(0, $scheduler->getDueTasks()); @@ -1413,7 +1391,7 @@ public function testSchedulerCanLockTaskWithInvalidLockFactory(): void 'execution_mode' => 'first_in_first_out', ]), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher()); + ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher(), new LockFactory(new InMemoryStore())); $scheduler->schedule(new NullTask('foo')); @@ -1459,7 +1437,7 @@ public function testSchedulerCanLockTaskWithValidLockFactory(): void $scheduler = new Scheduler('UTC', new InMemoryTransport(new InMemoryConfiguration(), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher()); + ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher(), new LockFactory(new InMemoryStore())); $scheduler->schedule(new NullTask('foo')); @@ -1479,7 +1457,7 @@ public function testSchedulerCannotReturnNextDueTaskWhenEmpty(): void { $scheduler = new Scheduler('UTC', new InMemoryTransport(new InMemoryConfiguration(), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher()); + ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher(), new LockFactory(new InMemoryStore())); self::assertCount(0, $scheduler->getDueTasks()); @@ -1498,7 +1476,7 @@ public function testSchedulerCannotReturnNextDueTaskWhenASingleTaskIsFound(): vo { $scheduler = new Scheduler('UTC', new InMemoryTransport(new InMemoryConfiguration(), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher()); + ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher(), new LockFactory(new InMemoryStore())); self::assertCount(0, $scheduler->getDueTasks()); @@ -1511,103 +1489,6 @@ public function testSchedulerCannotReturnNextDueTaskWhenASingleTaskIsFound(): vo $scheduler->next(); } - /** - * @throws Throwable {@see Scheduler::__construct()} - * @throws Throwable {@see SchedulerInterface::schedule()} - * @throws Throwable {@see SchedulerInterface::getDueTasks()} - */ - public function testSchedulerCanReturnNextDueTask(): void - { - $scheduler = new Scheduler('UTC', new InMemoryTransport(new InMemoryConfiguration(), new SchedulePolicyOrchestrator([ - new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher()); - - $scheduler->schedule(new NullTask('foo')); - $scheduler->schedule(new NullTask('bar')); - - self::assertCount(2, $scheduler->getDueTasks()); - - $nextDueTask = $scheduler->next(); - self::assertInstanceOf(NullTask::class, $nextDueTask); - self::assertSame('bar', $nextDueTask->getName()); - } - - /** - * @throws Throwable {@see Scheduler::__construct()} - * @throws Throwable {@see SchedulerInterface::schedule()} - * @throws Throwable {@see SchedulerInterface::getDueTasks()} - */ - public function testSchedulerCanReturnNextDueTaskAsynchronously(): void - { - $scheduler = new Scheduler('UTC', new InMemoryTransport(new InMemoryConfiguration(), new SchedulePolicyOrchestrator([ - new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher()); - - $scheduler->schedule(new NullTask('foo')); - $scheduler->schedule(new NullTask('bar')); - - $nextDueTask = $scheduler->next(true); - self::assertInstanceOf(LazyTask::class, $nextDueTask); - self::assertFalse($nextDueTask->isInitialized()); - self::assertSame('bar.lazy', $nextDueTask->getName()); - - $task = $nextDueTask->getTask(); - self::assertTrue($nextDueTask->isInitialized()); - self::assertInstanceOf(NullTask::class, $task); - self::assertSame('bar', $task->getName()); - } - - /** - * @throws Throwable {@see Scheduler::__construct()} - */ - public function testSchedulerCanRebootWithEmptyTasks(): void - { - $scheduler = new Scheduler('UTC', new InMemoryTransport(new InMemoryConfiguration(), new SchedulePolicyOrchestrator([ - new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher()); - - $scheduler->schedule(new NullTask('bar')); - self::assertCount(1, $scheduler->getTasks()); - - $scheduler->reboot(); - self::assertCount(0, $scheduler->getTasks()); - } - - /** - * @throws Throwable {@see Scheduler::__construct()} - */ - public function testSchedulerCanReboot(): void - { - $scheduler = new Scheduler('UTC', new InMemoryTransport(new InMemoryConfiguration(), new SchedulePolicyOrchestrator([ - new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher()); - - $scheduler->schedule(new NullTask('foo', [ - 'expression' => '@reboot', - ])); - $scheduler->schedule(new NullTask('bar')); - self::assertCount(2, $scheduler->getTasks()); - - $scheduler->reboot(); - self::assertCount(1, $scheduler->getTasks()); - } - - /** - * @throws Throwable {@see Scheduler::__construct()} - * @throws Throwable {@see SchedulerInterface::schedule()} - */ - public function testSchedulerCannotPreemptEmptyDueTasks(): void - { - $task = new NullTask('foo'); - - $scheduler = new Scheduler('UTC', new InMemoryTransport(new InMemoryConfiguration(), new SchedulePolicyOrchestrator([ - new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), new EventDispatcher()); - - $scheduler->preempt('foo', fn (TaskInterface $task): bool => $task->getName() === 'bar'); - self::assertNotSame(TaskInterface::READY_TO_EXECUTE, $task->getState()); - } - /** * @throws Throwable {@see Scheduler::__construct()} * @throws Throwable {@see SchedulerInterface::getDueTasks()} @@ -1619,10 +1500,10 @@ public function testSchedulerCannotPreemptEmptyToPreemptTasks(): void $scheduler = new Scheduler('UTC', new InMemoryTransport(new InMemoryConfiguration(), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), $eventDispatcher); + ])), new SchedulerMiddlewareStack(new MiddlewareRegistry([])), $eventDispatcher, new LockFactory(new InMemoryStore())); $scheduler->schedule(new NullTask('foo')); - $scheduler->preempt('foo', fn (TaskInterface $task): bool => $task->getName() === 'bar'); + $scheduler->preempt('foo', static fn (TaskInterface $task): bool => $task->getName() === 'bar'); } /** @@ -1639,12 +1520,12 @@ public function testSchedulerCanPreemptTasks(): void new FirstInFirstOutPolicy(), ])); - $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(new MiddlewareRegistry([])), $eventDispatcher); + $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(new MiddlewareRegistry([])), $eventDispatcher, new LockFactory(new InMemoryStore())); $scheduler->schedule(new NullTask('foo')); $scheduler->schedule(new NullTask('bar')); $scheduler->schedule(new NullTask('reboot')); - $scheduler->preempt('foo', fn (TaskInterface $task): bool => $task->getName() === 'reboot'); + $scheduler->preempt('foo', static fn (TaskInterface $task): bool => $task->getName() === 'reboot'); $lockFactory = new LockFactory(new InMemoryStore()); @@ -1690,8 +1571,8 @@ public function testSchedulerCanPreemptTasks(): void public function provideTasks(): Generator { yield 'Shell tasks' => [ - new ShellTask('Bar', ['echo', 'Symfony']), - new ShellTask('Foo', ['echo', 'Symfony']), + new ShellTask(name: 'Bar', command: ['echo', 'Symfony']), + new ShellTask(name: 'Foo', command: ['echo', 'Symfony']), ]; } diff --git a/tests/Task/AbstractTaskListTest.php b/tests/Task/AbstractTaskListTest.php new file mode 100644 index 00000000..ade1c8aa --- /dev/null +++ b/tests/Task/AbstractTaskListTest.php @@ -0,0 +1,64 @@ + + */ +abstract class AbstractTaskListTest extends TestCase +{ + abstract public function getTaskList(): TaskListInterface|LockedTaskList|LazyTaskList; + + public function testListCanBeCreatedWithEmptyTasks(): void + { + $taskList = $this->getTaskList(); + + self::assertCount(expectedCount: 0, haystack: $taskList); + } + + public function testListCanBeHydrated(): void + { + $taskList = $this->getTaskList(); + $taskList->add(task: new NullTask(name: 'foo')); + + self::assertNotEmpty(actual: $taskList); + self::assertSame(expected: 1, actual: $taskList->count()); + } + + public function testListCanBeHydratedWithMultipleTasks(): void + { + $taskList = $this->getTaskList(); + + $taskList->add( + new NullTask(name: 'foo'), + new NullTask(name: 'bar') + ); + + self::assertNotEmpty(actual: $taskList); + self::assertSame(expected: 2, actual: $taskList->count()); + } + + /** + * @throws Throwable {@see TaskListInterface::offsetSet()} + */ + public function testListCannotBeHydratedUsingInvalidOffset(): void + { + $taskList = $this->getTaskList(); + + self::expectException(exception: InvalidArgumentException::class); + self::expectExceptionMessage(message: 'A task must be given, received "object"'); + self::expectExceptionCode(code: 0); + $taskList->offsetSet(offset: 'foo', value: new stdClass()); + } +} diff --git a/tests/Task/LockedTaskListTest.php b/tests/Task/LockedTaskListTest.php new file mode 100644 index 00000000..a1f2cfe2 --- /dev/null +++ b/tests/Task/LockedTaskListTest.php @@ -0,0 +1,14 @@ + + */ +final class LockedTaskListTest extends TestCase +{ +} diff --git a/tests/Task/TaskListTest.php b/tests/Task/TaskListTest.php index 38271877..bf897661 100644 --- a/tests/Task/TaskListTest.php +++ b/tests/Task/TaskListTest.php @@ -5,27 +5,25 @@ namespace Tests\SchedulerBundle\Task; use DateTimeImmutable; -use PHPUnit\Framework\TestCase; use SchedulerBundle\Exception\InvalidArgumentException; use SchedulerBundle\Exception\RuntimeException; use SchedulerBundle\Task\LazyTask; +use SchedulerBundle\Task\LazyTaskList; +use SchedulerBundle\Task\LockedTaskList; use SchedulerBundle\Task\NullTask; use SchedulerBundle\Task\TaskInterface; use SchedulerBundle\Task\TaskList; use SchedulerBundle\Task\TaskListInterface; -use stdClass; use Throwable; /** * @author Guillaume Loulier */ -final class TaskListTest extends TestCase +final class TaskListTest extends AbstractTaskListTest { - public function testListCanBeCreatedWithEmptyTasks(): void + public function getTaskList(): TaskListInterface|LockedTaskList|LazyTaskList { - $taskList = new TaskList(); - - self::assertCount(expectedCount: 0, haystack: $taskList); + return new TaskList(); } public function testListCanBeCreatedWithTasks(): void @@ -37,45 +35,6 @@ public function testListCanBeCreatedWithTasks(): void self::assertSame(expected: 1, actual: $taskList->count()); } - public function testListCanBeHydrated(): void - { - $task = $this->createMock(TaskInterface::class); - $taskList = new TaskList(); - - $task->expects(self::once())->method('getName')->willReturn('foo'); - $taskList->add($task); - - self::assertNotEmpty($taskList); - self::assertSame(1, $taskList->count()); - } - - public function testListCanBeHydratedWithMultipleTasks(): void - { - $task = $this->createMock(TaskInterface::class); - $secondTask = $this->createMock(TaskInterface::class); - - $taskList = new TaskList(); - - $task->expects(self::once())->method('getName')->willReturn('foo'); - $taskList->add($task, $secondTask); - - self::assertNotEmpty($taskList); - self::assertSame(2, $taskList->count()); - } - - /** - * @throws Throwable {@see TaskListInterface::offsetSet()} - */ - public function testListCannotBeHydratedUsingInvalidOffset(): void - { - $taskList = new TaskList(); - - self::expectException(InvalidArgumentException::class); - self::expectExceptionMessage('A task must be given, received "object"'); - self::expectExceptionCode(0); - $taskList->offsetSet('foo', new stdClass()); - } - /** * @throws Throwable {@see TaskListInterface::offsetSet()} */ diff --git a/tests/Worker/AbstractWorkerTestCase.php b/tests/Worker/AbstractWorkerTestCase.php new file mode 100644 index 00000000..0d13cbb8 --- /dev/null +++ b/tests/Worker/AbstractWorkerTestCase.php @@ -0,0 +1,36 @@ + + */ +abstract class AbstractWorkerTestCase extends TestCase +{ + /** + * @throws Throwable {@see Scheduler::__construct()} + */ + abstract protected function getWorker(): WorkerInterface; + + /** + * @throws Throwable {@see Scheduler::__construct()} + */ + public function testTaskCannotBeExecutedWithoutRunner(): void + { + $worker = $this->getWorker(); + + self::expectException(UndefinedRunnerException::class); + self::expectExceptionMessage('No runner found'); + self::expectExceptionCode(0); + $worker->execute(WorkerConfiguration::create()); + } +} diff --git a/tests/Worker/ExecutionPolicy/DefaultPolicyTest.php b/tests/Worker/ExecutionPolicy/DefaultPolicyTest.php index 58041d45..faa884ac 100644 --- a/tests/Worker/ExecutionPolicy/DefaultPolicyTest.php +++ b/tests/Worker/ExecutionPolicy/DefaultPolicyTest.php @@ -16,7 +16,7 @@ public function testPolicySupport(): void { $policy = new DefaultPolicy(); - self::assertTrue($policy->support('default')); - self::assertFalse($policy->support('foo')); + self::assertTrue(condition: $policy->support(policy: 'default')); + self::assertFalse(condition: $policy->support(policy: 'foo')); } } diff --git a/tests/Worker/ExecutionPolicy/ExecutionPolicyRegistryTest.php b/tests/Worker/ExecutionPolicy/ExecutionPolicyRegistryTest.php index d60ad777..ca175f2f 100644 --- a/tests/Worker/ExecutionPolicy/ExecutionPolicyRegistryTest.php +++ b/tests/Worker/ExecutionPolicy/ExecutionPolicyRegistryTest.php @@ -16,46 +16,46 @@ final class ExecutionPolicyRegistryTest extends TestCase { public function testRegistryCanCount(): void { - $registry = new ExecutionPolicyRegistry([]); + $registry = new ExecutionPolicyRegistry(policies: []); - self::assertCount(0, $registry); + self::assertCount(expectedCount: 0, haystack: $registry); } public function testRegistryCannotReturnInvalidPolicy(): void { - $registry = new ExecutionPolicyRegistry([ + $registry = new ExecutionPolicyRegistry(policies: [ new DefaultPolicy(), ]); - self::assertCount(1, $registry); + self::assertCount(expectedCount: 1, haystack: $registry); - self::expectException(InvalidArgumentException::class); - self::expectExceptionMessage('No policy found for "foo"'); - self::expectExceptionCode(0); - $registry->find('foo'); + self::expectException(exception: InvalidArgumentException::class); + self::expectExceptionMessage(message: 'No policy found for "foo"'); + self::expectExceptionCode(code: 0); + $registry->find(policy: 'foo'); } public function testRegistryCannotReturnMultiplePolicies(): void { - $registry = new ExecutionPolicyRegistry([ + $registry = new ExecutionPolicyRegistry(policies: [ new DefaultPolicy(), new DefaultPolicy(), ]); - self::assertCount(2, $registry); + self::assertCount(expectedCount: 2, haystack: $registry); - self::expectException(InvalidArgumentException::class); - self::expectExceptionMessage('More than one policy found, consider improving the policy(es)'); - self::expectExceptionCode(0); - $registry->find('default'); + self::expectException(exception: InvalidArgumentException::class); + self::expectExceptionMessage(message: 'More than one policy found, consider improving the policy(es)'); + self::expectExceptionCode(code: 0); + $registry->find(policy: 'default'); } public function testRegistryCanReturnPolicy(): void { - $registry = new ExecutionPolicyRegistry([ + $registry = new ExecutionPolicyRegistry(policies: [ new DefaultPolicy(), ]); - self::assertCount(1, $registry); + self::assertCount(expectedCount: 1, haystack: $registry); - $policy = $registry->find('default'); - self::assertInstanceOf(DefaultPolicy::class, $policy); + $policy = $registry->find(policy: 'default'); + self::assertInstanceOf(expected: DefaultPolicy::class, actual: $policy); } } diff --git a/tests/Worker/ExecutionPolicy/FiberPolicyTest.php b/tests/Worker/ExecutionPolicy/FiberPolicyTest.php index 87e40fe0..3f1dcb67 100644 --- a/tests/Worker/ExecutionPolicy/FiberPolicyTest.php +++ b/tests/Worker/ExecutionPolicy/FiberPolicyTest.php @@ -16,7 +16,7 @@ public function testPolicySupport(): void { $policy = new FiberPolicy(); - self::assertTrue($policy->support('fiber')); - self::assertFalse($policy->support('foo')); + self::assertTrue(condition: $policy->support(policy: 'fiber')); + self::assertFalse(condition: $policy->support(policy: 'foo')); } } diff --git a/tests/Worker/FiberWorkerTest.php b/tests/Worker/FiberWorkerTest.php index 2a362e6b..93432a45 100644 --- a/tests/Worker/FiberWorkerTest.php +++ b/tests/Worker/FiberWorkerTest.php @@ -5,14 +5,12 @@ namespace Tests\SchedulerBundle\Worker; use DateTimeImmutable; -use PHPUnit\Framework\TestCase; use Psr\Log\LoggerInterface; use Psr\Log\NullLogger; use RuntimeException; use SchedulerBundle\Event\WorkerPausedEvent; use SchedulerBundle\Event\WorkerRunningEvent; use SchedulerBundle\EventListener\StopWorkerOnTaskLimitSubscriber; -use SchedulerBundle\Exception\UndefinedRunnerException; use SchedulerBundle\Middleware\MaxExecutionMiddleware; use SchedulerBundle\Middleware\NotifierMiddleware; use SchedulerBundle\Middleware\SchedulerMiddlewareStack; @@ -51,6 +49,7 @@ use SchedulerBundle\Worker\ExecutionPolicy\FiberPolicy; use SchedulerBundle\Worker\Worker; use SchedulerBundle\Worker\WorkerConfiguration; +use SchedulerBundle\Worker\WorkerInterface; use Symfony\Component\Console\Application; use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\EventDispatcher\EventDispatcherInterface; @@ -71,34 +70,22 @@ * * @author Guillaume Loulier */ -final class FiberWorkerTest extends TestCase +final class FiberWorkerTest extends AbstractWorkerTestCase { - /** - * @throws Throwable - */ - public function testTaskCannotBeExecutedWithoutRunner(): void + protected function getWorker(): WorkerInterface { - $eventDispatcher = $this->createMock(EventDispatcherInterface::class); - $watcher = $this->createMock(TaskExecutionTrackerInterface::class); - $logger = $this->createMock(LoggerInterface::class); - - $worker = new Worker( + return new Worker( new Scheduler('UTC', new InMemoryTransport(new InMemoryConfiguration(), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack([]), new EventDispatcher()), + ])), new SchedulerMiddlewareStack([]), new EventDispatcher(), new LockFactory(new InMemoryStore())), new RunnerRegistry([]), new ExecutionPolicyRegistry([]), - $watcher, + new TaskExecutionTracker(new Stopwatch()), new WorkerMiddlewareStack(), - $eventDispatcher, + new EventDispatcher(), new LockFactory(new InMemoryStore()), - $logger + new NullLogger() ); - - self::expectException(UndefinedRunnerException::class); - self::expectExceptionMessage('No runner found'); - self::expectExceptionCode(0); - $worker->execute(WorkerConfiguration::create()); } /** @@ -106,22 +93,19 @@ public function testTaskCannotBeExecutedWithoutRunner(): void */ public function testWorkerCanBeConfigured(): void { - $runner = $this->createMock(RunnerInterface::class); - $eventDispatcher = $this->createMock(EventDispatcherInterface::class); - $watcher = $this->createMock(TaskExecutionTrackerInterface::class); $logger = $this->createMock(LoggerInterface::class); $lockFactory = new LockFactory(new InMemoryStore()); $worker = new Worker(new Scheduler('UTC', new InMemoryTransport(new InMemoryConfiguration(), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(), new EventDispatcher()), new RunnerRegistry([ - $runner, + ])), new SchedulerMiddlewareStack(), new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())), new RunnerRegistry([ + new NullTaskRunner(), ]), new ExecutionPolicyRegistry([ new FiberPolicy(), - ]), $watcher, new WorkerMiddlewareStack([ + ]), new TaskExecutionTracker(new Stopwatch()), new WorkerMiddlewareStack([ new TaskLockBagMiddleware($lockFactory), - ]), $eventDispatcher, $lockFactory, $logger); + ]), new EventDispatcher(), $lockFactory, $logger); $configuration = WorkerConfiguration::create(); $configuration->setExecutionPolicy('fiber'); @@ -157,7 +141,7 @@ public function testWorkerCanBeForked(): void $worker = new Worker(new Scheduler('UTC', new InMemoryTransport(new InMemoryConfiguration(), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack([]), $eventDispatcher), new RunnerRegistry([ + ])), new SchedulerMiddlewareStack([]), $eventDispatcher, lockFactory: new LockFactory(store: new InMemoryStore())), new RunnerRegistry([ new NullTaskRunner(), ]), new ExecutionPolicyRegistry([ new FiberPolicy(), @@ -198,7 +182,7 @@ public function testTaskCannotBeExecutedWithoutSupportingRunner(): void new FirstInFirstOutPolicy(), ])); - $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack([]), new EventDispatcher()); + $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack([]), new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())); $scheduler->schedule(new NullTask('foo')); $eventDispatcher = $this->createMock(EventDispatcherInterface::class); @@ -248,7 +232,7 @@ public function testTaskCannotBeExecutedWhileWorkerIsStopped(): void new FirstInFirstOutPolicy(), ])); - $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack([]), new EventDispatcher()); + $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack([]), new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())); $lockFactory = new LockFactory(new InMemoryStore()); @@ -300,7 +284,7 @@ public function testTaskCannotBeExecutedWhilePaused(): void new FirstInFirstOutPolicy(), ])); - $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack([]), new EventDispatcher()); + $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack([]), new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())); $scheduler->schedule($task); $scheduler->schedule($secondTask); @@ -350,7 +334,7 @@ public function testTaskCannotBeExecutedWithAnExecutionDelay(): void new FirstInFirstOutPolicy(), ])); - $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher()); + $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())); $scheduler->schedule($task); $eventDispatcher = new EventDispatcher(); @@ -394,7 +378,7 @@ public function testTaskCannotBeExecutedWithErroredBeforeExecutionCallback(): vo new FirstInFirstOutPolicy(), ])); - $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher()); + $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())); $scheduler->schedule($task); $eventDispatcher = new EventDispatcher(); @@ -444,7 +428,7 @@ public function testTaskCanBeExecutedWithErroredBeforeExecutionCallback(): void new FirstInFirstOutPolicy(), ])); - $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher()); + $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())); $scheduler->schedule($task); $scheduler->schedule($validTask); @@ -493,7 +477,7 @@ public function testTaskCanBeExecutedWithBeforeExecutionCallback(): void new FirstInFirstOutPolicy(), ])); - $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher()); + $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())); $scheduler->schedule($task); $eventDispatcher = new EventDispatcher(); @@ -525,11 +509,11 @@ public function testTaskCanBeExecutedWithBeforeExecutionCallback(): void public function testTaskCanBeExecutedWithErroredAfterExecutionCallback(): void { $task = new NullTask('foo', [ - 'after_executing' => fn (): bool => false, + 'after_executing' => static fn (): bool => false, ]); $validTask = new NullTask('bar', [ - 'after_executing' => fn (): bool => true, + 'after_executing' => static fn (): bool => true, ]); $logger = $this->createMock(LoggerInterface::class); @@ -543,7 +527,7 @@ public function testTaskCanBeExecutedWithErroredAfterExecutionCallback(): void new FirstInFirstOutPolicy(), ])); - $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher()); + $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())); $scheduler->schedule($task); $scheduler->schedule($validTask); @@ -592,7 +576,7 @@ public function testTaskCanBeExecutedWithAfterExecutionCallback(): void new FirstInFirstOutPolicy(), ])); - $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher()); + $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())); $scheduler->schedule($task); $eventDispatcher = new EventDispatcher(); @@ -635,7 +619,7 @@ public function testTaskCanBeExecutedWithRunner(): void $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack([ new TaskLockBagMiddleware(new LockFactory(new InMemoryStore())), - ]), $eventDispatcher); + ]), $eventDispatcher, lockFactory: new LockFactory(store: new InMemoryStore())); $scheduler->schedule(new NullTask('foo')); $lockFactory = new LockFactory(new InMemoryStore()); @@ -687,7 +671,7 @@ public function testEmptyTaskCannotBeExecuted(): void $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack([ new TaskLockBagMiddleware(new LockFactory(new InMemoryStore())), - ]), $eventDispatcher); + ]), $eventDispatcher, lockFactory: new LockFactory(store: new InMemoryStore())); $lockFactory = new LockFactory(new InMemoryStore()); @@ -731,7 +715,7 @@ public function testTaskCanBeExecutedAndTheWorkerCanReturnTheLastExecutedTask(): new FirstInFirstOutPolicy(), ])); - $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher()); + $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())); $scheduler->schedule($task); $eventDispatcher = new EventDispatcher(); @@ -779,7 +763,7 @@ public function testTaskCannotBeExecutedTwiceAsSingleRunTask(): void new FirstInFirstOutPolicy(), ])); - $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher()); + $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())); $scheduler->schedule($shellTask); $eventDispatcher = new EventDispatcher(); @@ -823,7 +807,7 @@ public function testWorkerCanHandleFailedTask(): void $scheduler = new Scheduler('UTC', new InMemoryTransport(new InMemoryConfiguration(), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(), new EventDispatcher()); + ])), new SchedulerMiddlewareStack(), new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())); $scheduler->schedule($task); $eventDispatcher = new EventDispatcher(); @@ -875,7 +859,7 @@ public function testTaskCanBeExecutedWithoutBeforeExecutionNotificationAndNotifi new FirstInFirstOutPolicy(), ])); - $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher()); + $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())); $scheduler->schedule($task); $eventDispatcher = new EventDispatcher(); @@ -928,7 +912,7 @@ public function testTaskCanBeExecutedWithBeforeExecutionNotificationAndNotifier( new FirstInFirstOutPolicy(), ])); - $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher()); + $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())); $scheduler->schedule($task); $eventDispatcher = new EventDispatcher(); @@ -976,7 +960,7 @@ public function testTaskCanBeExecutedWithoutAfterExecutionNotificationAndNotifie new FirstInFirstOutPolicy(), ])); - $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher()); + $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())); $scheduler->schedule($task); $eventDispatcher = new EventDispatcher(); @@ -1029,7 +1013,7 @@ public function testTaskCanBeExecutedWithAfterExecutionNotificationAndNotifier() new FirstInFirstOutPolicy(), ])); - $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher()); + $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())); $scheduler->schedule($task); $eventDispatcher = new EventDispatcher(); @@ -1074,7 +1058,7 @@ public function testWorkerCannotReserveMaxExecutionTokensWithoutRateLimiter(): v new FirstInFirstOutPolicy(), ])); - $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher()); + $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())); $scheduler->schedule($task); $eventDispatcher = new EventDispatcher(); @@ -1119,7 +1103,7 @@ public function testWorkerCannotReserveMaxExecutionTokensWithoutMaxExecutionLimi new FirstInFirstOutPolicy(), ])); - $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher()); + $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())); $scheduler->schedule($task); $eventDispatcher = new EventDispatcher(); @@ -1171,7 +1155,7 @@ public function testWorkerCanReserveMaxExecutionTokensAndLimitTaskExecutionThenS new FirstInFirstOutPolicy(), ])); - $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher()); + $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())); $scheduler->schedule($task); $eventDispatcher = new EventDispatcher(); @@ -1227,7 +1211,7 @@ public function testWorkerCanStopWhenTaskAreConsumedAndWithoutDaemonEnabled(): v new FirstInFirstOutPolicy(), ])); - $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack([]), new EventDispatcher()); + $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack([]), new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())); $eventDispatcher = $this->createMock(EventDispatcherInterface::class); $eventDispatcher->expects(self::exactly(7))->method('dispatch'); @@ -1273,7 +1257,7 @@ public function testWorkerCanStopWhenTaskAreConsumedWithError(): void new FirstInFirstOutPolicy(), ])); - $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher()); + $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())); $eventDispatcher = $this->createMock(EventDispatcherInterface::class); $eventDispatcher->expects(self::exactly(7))->method('dispatch'); @@ -1325,7 +1309,7 @@ public function testPausedTaskIsNotExecutedIfListContainsASingleTask(): void new FirstInFirstOutPolicy(), ])); - $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher()); + $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())); $scheduler->schedule(new NullTask('bar', [ 'access_lock_bag' => new AccessLockBag(new Key('bar')), @@ -1376,7 +1360,7 @@ public function testWorkerCanExecuteChainedTasks(): void new FirstInFirstOutPolicy(), ])); - $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher()); + $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())); $scheduler->schedule($chainedTask); $scheduler->schedule($shellTask); @@ -1439,7 +1423,7 @@ public function testWorkerCanRetrieveTasksLazily(): void new FirstInFirstOutPolicy(), ])); - $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher()); + $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())); $scheduler->schedule($chainedTask); $scheduler->schedule($shellTask); @@ -1508,7 +1492,7 @@ public function testWorkerCanExecuteLongRunningTask(): void new FirstInFirstOutPolicy(), ])); - $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher()); + $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())); $scheduler->schedule($task); $lockFactory = new LockFactory(new InMemoryStore()); @@ -1552,7 +1536,7 @@ public function testWorkerCanExecuteTaskWithExecutionDelay(): void new FirstInFirstOutPolicy(), ])); - $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher()); + $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())); $scheduler->schedule($task); $lockFactory = new LockFactory(new InMemoryStore()); @@ -1590,7 +1574,7 @@ public function testWorkerCanStopWithEmptyTaskList(): void new FirstInFirstOutPolicy(), ])); - $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher()); + $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())); $lockFactory = new LockFactory(new InMemoryStore()); @@ -1628,7 +1612,7 @@ public function testWorkerCanStopWithoutExecutedTasks(): void new FirstInFirstOutPolicy(), ])); - $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher()); + $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())); $scheduler->schedule(new NullTask('foo')); $lockFactory = new LockFactory(new InMemoryStore()); @@ -1665,7 +1649,7 @@ public function testWorkerCanStopWhenTasksAreExecutedAndWithoutSleepOptionTwice( new FirstInFirstOutPolicy(), ])); - $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher()); + $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())); $scheduler->schedule(new NullTask('foo')); $lockFactory = new LockFactory(new InMemoryStore()); @@ -1712,7 +1696,7 @@ public function testWorkerCanBePaused(): void new FirstInFirstOutPolicy(), ])); - $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher()); + $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())); $scheduler->schedule(new NullTask('foo')); $eventDispatcher = new EventDispatcher(); @@ -1768,7 +1752,7 @@ public function testWorkerCanBeRestarted(): void new FirstInFirstOutPolicy(), ])); - $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher()); + $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())); $scheduler->schedule(new NullTask('foo')); $eventDispatcher = new EventDispatcher(); @@ -1819,7 +1803,7 @@ public function testWorkerCanPreempt(): void new FirstInFirstOutPolicy(), ])); - $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher()); + $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())); $lockFactory = new LockFactory(new InMemoryStore()); @@ -1862,13 +1846,12 @@ public function testWorkerCanPreempt(): void public function testWorkerCannotPreemptEmptyList(): void { $logger = $this->createMock(LoggerInterface::class); - $tracker = $this->createMock(TaskExecutionTrackerInterface::class); $transport = new InMemoryTransport(new InMemoryConfiguration(), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), ])); - $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher()); + $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())); $lockFactory = new LockFactory(new InMemoryStore()); @@ -1877,7 +1860,7 @@ public function testWorkerCannotPreemptEmptyList(): void ]), new ExecutionPolicyRegistry([ new DefaultPolicy(), new FiberPolicy(), - ]), $tracker, new WorkerMiddlewareStack([ + ]), new TaskExecutionTracker(new Stopwatch()), new WorkerMiddlewareStack([ new SingleRunTaskMiddleware($transport), new TaskUpdateMiddleware($transport), new TaskLockBagMiddleware($lockFactory), diff --git a/tests/Worker/WorkerConfigurationTest.php b/tests/Worker/WorkerConfigurationTest.php index 284ce800..ab3d1e83 100644 --- a/tests/Worker/WorkerConfigurationTest.php +++ b/tests/Worker/WorkerConfigurationTest.php @@ -105,6 +105,15 @@ public function testConfigurationCanDefineToStrictlyCheckDate(): void self::assertTrue($configuration->isStrictlyCheckingDate()); } + public function testConfigurationCanDefineToLockTasks(): void + { + $configuration = WorkerConfiguration::create(); + self::assertFalse($configuration->shouldLockTasks()); + + $configuration->lockTask(true); + self::assertTrue($configuration->shouldLockTasks()); + } + public function testConfigurationCanDefineSleepDurationDelay(): void { $configuration = WorkerConfiguration::create(); diff --git a/tests/Worker/WorkerRegistryTest.php b/tests/Worker/WorkerRegistryTest.php index e745f022..ac817b8f 100644 --- a/tests/Worker/WorkerRegistryTest.php +++ b/tests/Worker/WorkerRegistryTest.php @@ -4,34 +4,74 @@ namespace Tests\SchedulerBundle\Worker; +use Exception; use PHPUnit\Framework\TestCase; -use SchedulerBundle\Worker\WorkerInterface; +use Psr\Log\NullLogger; +use SchedulerBundle\Middleware\SchedulerMiddlewareStack; +use SchedulerBundle\Middleware\WorkerMiddlewareStack; +use SchedulerBundle\Runner\RunnerRegistry; +use SchedulerBundle\SchedulePolicy\FirstInFirstOutPolicy; +use SchedulerBundle\SchedulePolicy\SchedulePolicyOrchestrator; +use SchedulerBundle\Scheduler; +use SchedulerBundle\Task\TaskExecutionTracker; +use SchedulerBundle\Transport\Configuration\InMemoryConfiguration; +use SchedulerBundle\Transport\InMemoryTransport; +use SchedulerBundle\Worker\ExecutionPolicy\ExecutionPolicyRegistry; +use SchedulerBundle\Worker\Worker; use SchedulerBundle\Worker\WorkerRegistry; +use Symfony\Component\EventDispatcher\EventDispatcher; +use Symfony\Component\Lock\LockFactory; +use Symfony\Component\Lock\Store\InMemoryStore; +use Symfony\Component\Stopwatch\Stopwatch; /** * @author Guillaume Loulier */ final class WorkerRegistryTest extends TestCase { + /** + * @throws Exception {@see Scheduler::__construct()} + */ public function testRegistryCanCount(): void { - $worker = $this->createMock(WorkerInterface::class); - - $pool = new WorkerRegistry([ - $worker, + $registry = new WorkerRegistry(workers: [ + new Worker( + scheduler: new Scheduler(timezone: 'UTC', transport: new InMemoryTransport(configuration: new InMemoryConfiguration(), schedulePolicyOrchestrator: new SchedulePolicyOrchestrator(policies: [ + new FirstInFirstOutPolicy(), + ])), middlewareStack: new SchedulerMiddlewareStack([]), eventDispatcher: new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())), + runnerRegistry: new RunnerRegistry([]), + executionPolicyRegistry: new ExecutionPolicyRegistry([]), + taskExecutionTracker: new TaskExecutionTracker(new Stopwatch()), + middlewareStack: new WorkerMiddlewareStack(), + eventDispatcher: new EventDispatcher(), + lockFactory: new LockFactory(new InMemoryStore()), + logger: new NullLogger() + ), ]); - self::assertCount(1, $pool); + self::assertCount(expectedCount: 1, haystack: $registry); } + /** + * @throws Exception {@see Scheduler::__construct()} + */ public function testRegistryCanReturnWorkers(): void { - $worker = $this->createMock(WorkerInterface::class); - - $pool = new WorkerRegistry([ - $worker, + $registry = new WorkerRegistry(workers: [ + new Worker( + scheduler: new Scheduler(timezone: 'UTC', transport: new InMemoryTransport(configuration: new InMemoryConfiguration(), schedulePolicyOrchestrator: new SchedulePolicyOrchestrator(policies: [ + new FirstInFirstOutPolicy(), + ])), middlewareStack: new SchedulerMiddlewareStack([]), eventDispatcher: new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())), + runnerRegistry: new RunnerRegistry([]), + executionPolicyRegistry: new ExecutionPolicyRegistry([]), + taskExecutionTracker: new TaskExecutionTracker(new Stopwatch()), + middlewareStack: new WorkerMiddlewareStack(), + eventDispatcher: new EventDispatcher(), + lockFactory: new LockFactory(new InMemoryStore()), + logger: new NullLogger() + ), ]); - self::assertCount(1, $pool->getWorkers()); + self::assertCount(expectedCount: 1, haystack: $registry->getWorkers()); } } diff --git a/tests/Worker/WorkerTest.php b/tests/Worker/WorkerTest.php index 67f9b891..39ab88de 100644 --- a/tests/Worker/WorkerTest.php +++ b/tests/Worker/WorkerTest.php @@ -5,7 +5,6 @@ namespace Tests\SchedulerBundle\Worker; use DateTimeImmutable; -use PHPUnit\Framework\TestCase; use Psr\Log\LoggerInterface; use Psr\Log\NullLogger; use RuntimeException; @@ -47,11 +46,9 @@ use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use SchedulerBundle\EventListener\StopWorkerOnTaskLimitSubscriber; -use SchedulerBundle\Exception\UndefinedRunnerException; use SchedulerBundle\Runner\RunnerInterface; use SchedulerBundle\Task\Output; use SchedulerBundle\Task\ShellTask; -use SchedulerBundle\Task\TaskExecutionTrackerInterface; use SchedulerBundle\Task\TaskInterface; use SchedulerBundle\Task\TaskList; use SchedulerBundle\Worker\Worker; @@ -70,32 +67,25 @@ /** * @author Guillaume Loulier */ -final class WorkerTest extends TestCase +final class WorkerTest extends AbstractWorkerTestCase { /** - * @throws Throwable + * {@inheritdoc} */ - public function testTaskCannotBeExecutedWithoutRunner(): void + protected function getWorker(): WorkerInterface { - $watcher = $this->createMock(TaskExecutionTrackerInterface::class); - - $worker = new Worker( - new Scheduler('UTC', new InMemoryTransport(new InMemoryConfiguration(), new SchedulePolicyOrchestrator([ + return new Worker( + scheduler: new Scheduler(timezone: 'UTC', transport: new InMemoryTransport(configuration: new InMemoryConfiguration(), schedulePolicyOrchestrator: new SchedulePolicyOrchestrator(policies: [ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack([]), new EventDispatcher()), - new RunnerRegistry([]), - new ExecutionPolicyRegistry([]), - $watcher, - new WorkerMiddlewareStack(), - new EventDispatcher(), - new LockFactory(new InMemoryStore()), - new NullLogger() + ])), middlewareStack: new SchedulerMiddlewareStack([]), eventDispatcher: new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())), + runnerRegistry: new RunnerRegistry(runners: []), + executionPolicyRegistry: new ExecutionPolicyRegistry(policies: []), + taskExecutionTracker: new TaskExecutionTracker(watch: new Stopwatch()), + middlewareStack: new WorkerMiddlewareStack(), + eventDispatcher: new EventDispatcher(), + lockFactory: new LockFactory(store: new InMemoryStore()), + logger: new NullLogger() ); - - self::expectException(UndefinedRunnerException::class); - self::expectExceptionMessage('No runner found'); - self::expectExceptionCode(0); - $worker->execute(WorkerConfiguration::create()); } /** @@ -103,17 +93,15 @@ public function testTaskCannotBeExecutedWithoutRunner(): void */ public function testWorkerCanBeConfigured(): void { - $watcher = $this->createMock(TaskExecutionTrackerInterface::class); - $lockFactory = new LockFactory(new InMemoryStore()); $worker = new Worker(new Scheduler('UTC', new InMemoryTransport(new InMemoryConfiguration(), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(), new EventDispatcher()), new RunnerRegistry([ + ])), new SchedulerMiddlewareStack(), new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())), new RunnerRegistry([ new NullTaskRunner(), ]), new ExecutionPolicyRegistry([ new DefaultPolicy(), - ]), $watcher, new WorkerMiddlewareStack([ + ]), new TaskExecutionTracker(new Stopwatch()), new WorkerMiddlewareStack([ new TaskLockBagMiddleware($lockFactory), ]), new EventDispatcher(), $lockFactory, new NullLogger()); @@ -141,8 +129,6 @@ public function testWorkerCanBeConfigured(): void */ public function testWorkerCanBeForked(): void { - $watcher = $this->createMock(TaskExecutionTrackerInterface::class); - $eventDispatcher = $this->createMock(EventDispatcherInterface::class); $eventDispatcher->expects(self::exactly(3))->method('dispatch'); @@ -150,11 +136,11 @@ public function testWorkerCanBeForked(): void $worker = new Worker(new Scheduler('UTC', new InMemoryTransport(new InMemoryConfiguration(), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack([]), $eventDispatcher), new RunnerRegistry([ + ])), new SchedulerMiddlewareStack([]), $eventDispatcher, lockFactory: new LockFactory(store: new InMemoryStore())), new RunnerRegistry([ new NullTaskRunner(), ]), new ExecutionPolicyRegistry([ new DefaultPolicy(), - ]), $watcher, new WorkerMiddlewareStack([ + ]), new TaskExecutionTracker(new Stopwatch()), new WorkerMiddlewareStack([ new TaskLockBagMiddleware($lockFactory), ]), $eventDispatcher, $lockFactory, new NullLogger()); @@ -183,14 +169,13 @@ public function testWorkerCanBeForked(): void */ public function testTaskCannotBeExecutedWithoutSupportingRunner(): void { - $watcher = $this->createMock(TaskExecutionTrackerInterface::class); $logger = $this->createMock(LoggerInterface::class); $transport = new InMemoryTransport(new InMemoryConfiguration(), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), ])); - $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack([]), new EventDispatcher()); + $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack([]), new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())); $scheduler->schedule(new NullTask('foo')); $eventDispatcher = $this->createMock(EventDispatcherInterface::class); @@ -203,7 +188,7 @@ public function testTaskCannotBeExecutedWithoutSupportingRunner(): void new ShellTaskRunner(), ]), new ExecutionPolicyRegistry([ new DefaultPolicy(), - ]), $watcher, new WorkerMiddlewareStack([ + ]), new TaskExecutionTracker(new Stopwatch()), new WorkerMiddlewareStack([ new TaskUpdateMiddleware($transport), new TaskLockBagMiddleware($lockFactory), ]), $eventDispatcher, $lockFactory, $logger); @@ -229,14 +214,13 @@ public function testTaskCannotBeExecutedWhileWorkerIsStopped(): void $eventDispatcher = $this->createMock(EventDispatcherInterface::class); $eventDispatcher->expects(self::exactly(2))->method('dispatch'); - $watcher = $this->createMock(TaskExecutionTrackerInterface::class); $logger = $this->createMock(LoggerInterface::class); $transport = new InMemoryTransport(new InMemoryConfiguration(), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), ])); - $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack([]), new EventDispatcher()); + $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack([]), new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())); $lockFactory = new LockFactory(new InMemoryStore()); @@ -244,7 +228,7 @@ public function testTaskCannotBeExecutedWhileWorkerIsStopped(): void new NullTaskRunner(), ]), new ExecutionPolicyRegistry([ new DefaultPolicy(), - ]), $watcher, new WorkerMiddlewareStack([ + ]), new TaskExecutionTracker(new Stopwatch()), new WorkerMiddlewareStack([ new TaskUpdateMiddleware($transport), new TaskLockBagMiddleware($lockFactory), ]), $eventDispatcher, $lockFactory, $logger); @@ -279,15 +263,11 @@ public function testTaskCannotBeExecutedWhilePaused(): void ] ); - $tracker = $this->createMock(TaskExecutionTrackerInterface::class); - $tracker->expects(self::once())->method('startTracking')->with(self::equalTo($secondTask)); - $tracker->expects(self::once())->method('endTracking')->with(self::equalTo($secondTask)); - $transport = new InMemoryTransport(new InMemoryConfiguration(), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), ])); - $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack([]), new EventDispatcher()); + $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack([]), new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())); $scheduler->schedule($task); $scheduler->schedule($secondTask); @@ -300,7 +280,7 @@ public function testTaskCannotBeExecutedWhilePaused(): void new NullTaskRunner(), ]), new ExecutionPolicyRegistry([ new DefaultPolicy(), - ]), $tracker, new WorkerMiddlewareStack([ + ]), new TaskExecutionTracker(new Stopwatch()), new WorkerMiddlewareStack([ new SingleRunTaskMiddleware($transport), new TaskUpdateMiddleware($transport), new TaskLockBagMiddleware($lockFactory), @@ -326,15 +306,11 @@ public function testTaskCannotBeExecutedWithAnExecutionDelay(): void $logger = $this->createMock(LoggerInterface::class); $logger->expects(self::never())->method('info'); - $tracker = $this->createMock(TaskExecutionTrackerInterface::class); - $tracker->expects(self::once())->method('startTracking'); - $tracker->expects(self::once())->method('endTracking'); - $transport = new InMemoryTransport(new InMemoryConfiguration(), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), ])); - $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher()); + $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())); $scheduler->schedule($task); $eventDispatcher = new EventDispatcher(); @@ -346,7 +322,7 @@ public function testTaskCannotBeExecutedWithAnExecutionDelay(): void new NullTaskRunner(), ]), new ExecutionPolicyRegistry([ new DefaultPolicy(), - ]), $tracker, new WorkerMiddlewareStack([ + ]), new TaskExecutionTracker(new Stopwatch()), new WorkerMiddlewareStack([ new SingleRunTaskMiddleware($transport), new TaskLockBagMiddleware($lockFactory), ]), $eventDispatcher, $lockFactory, $logger); @@ -367,15 +343,11 @@ public function testTaskCannotBeExecutedWithErroredBeforeExecutionCallback(): vo $logger = $this->createMock(LoggerInterface::class); $logger->expects(self::never())->method('info'); - $tracker = $this->createMock(TaskExecutionTrackerInterface::class); - $tracker->expects(self::never())->method('startTracking')->with(self::equalTo($task)); - $tracker->expects(self::never())->method('endTracking')->with(self::equalTo($task)); - $transport = new InMemoryTransport(new InMemoryConfiguration(), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), ])); - $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher()); + $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())); $scheduler->schedule($task); $eventDispatcher = new EventDispatcher(); @@ -387,7 +359,7 @@ public function testTaskCannotBeExecutedWithErroredBeforeExecutionCallback(): vo new NullTaskRunner(), ]), new ExecutionPolicyRegistry([ new DefaultPolicy(), - ]), $tracker, new WorkerMiddlewareStack([ + ]), new TaskExecutionTracker(new Stopwatch()), new WorkerMiddlewareStack([ new SingleRunTaskMiddleware($transport), new TaskCallbackMiddleware(), new TaskLockBagMiddleware($lockFactory), @@ -414,15 +386,11 @@ public function testTaskCanBeExecutedWithErroredBeforeExecutionCallback(): void $logger = $this->createMock(LoggerInterface::class); $logger->expects(self::never())->method('info'); - $tracker = $this->createMock(TaskExecutionTrackerInterface::class); - $tracker->expects(self::once())->method('startTracking')->with(self::equalTo($validTask)); - $tracker->expects(self::once())->method('endTracking')->with(self::equalTo($validTask)); - $transport = new InMemoryTransport(new InMemoryConfiguration(), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), ])); - $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher()); + $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())); $scheduler->schedule($task); $scheduler->schedule($validTask); @@ -435,7 +403,7 @@ public function testTaskCanBeExecutedWithErroredBeforeExecutionCallback(): void new NullTaskRunner(), ]), new ExecutionPolicyRegistry([ new DefaultPolicy(), - ]), $tracker, new WorkerMiddlewareStack([ + ]), new TaskExecutionTracker(new Stopwatch()), new WorkerMiddlewareStack([ new SingleRunTaskMiddleware($transport), new TaskCallbackMiddleware(), new TaskLockBagMiddleware($lockFactory), @@ -460,15 +428,11 @@ public function testTaskCanBeExecutedWithBeforeExecutionCallback(): void $logger = $this->createMock(LoggerInterface::class); $logger->expects(self::never())->method('info'); - $tracker = $this->createMock(TaskExecutionTrackerInterface::class); - $tracker->expects(self::once())->method('startTracking')->with(self::equalTo($task)); - $tracker->expects(self::once())->method('endTracking')->with(self::equalTo($task)); - $transport = new InMemoryTransport(new InMemoryConfiguration(), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), ])); - $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher()); + $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())); $scheduler->schedule($task); $eventDispatcher = new EventDispatcher(); @@ -480,7 +444,7 @@ public function testTaskCanBeExecutedWithBeforeExecutionCallback(): void new NullTaskRunner(), ]), new ExecutionPolicyRegistry([ new DefaultPolicy(), - ]), $tracker, new WorkerMiddlewareStack([ + ]), new TaskExecutionTracker(new Stopwatch()), new WorkerMiddlewareStack([ new SingleRunTaskMiddleware($transport), new TaskCallbackMiddleware(), new TaskLockBagMiddleware($lockFactory), @@ -497,25 +461,21 @@ public function testTaskCanBeExecutedWithBeforeExecutionCallback(): void public function testTaskCanBeExecutedWithErroredAfterExecutionCallback(): void { $task = new NullTask('foo', [ - 'after_executing' => fn (): bool => false, + 'after_executing' => static fn (): bool => false, ]); $validTask = new NullTask('bar', [ - 'after_executing' => fn (): bool => true, + 'after_executing' => static fn (): bool => true, ]); $logger = $this->createMock(LoggerInterface::class); $logger->expects(self::never())->method('info'); - $tracker = $this->createMock(TaskExecutionTrackerInterface::class); - $tracker->expects(self::exactly(2))->method('startTracking')->withConsecutive([$task], [$validTask]); - $tracker->expects(self::exactly(2))->method('endTracking')->withConsecutive([$task], [$validTask]); - $transport = new InMemoryTransport(new InMemoryConfiguration(), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), ])); - $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher()); + $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())); $scheduler->schedule($task); $scheduler->schedule($validTask); @@ -528,7 +488,7 @@ public function testTaskCanBeExecutedWithErroredAfterExecutionCallback(): void new NullTaskRunner(), ]), new ExecutionPolicyRegistry([ new DefaultPolicy(), - ]), $tracker, new WorkerMiddlewareStack([ + ]), new TaskExecutionTracker(new Stopwatch()), new WorkerMiddlewareStack([ new SingleRunTaskMiddleware($transport), new TaskCallbackMiddleware(), new TaskLockBagMiddleware($lockFactory), @@ -553,15 +513,11 @@ public function testTaskCanBeExecutedWithAfterExecutionCallback(): void $logger = $this->createMock(LoggerInterface::class); $logger->expects(self::never())->method('info'); - $tracker = $this->createMock(TaskExecutionTrackerInterface::class); - $tracker->expects(self::once())->method('startTracking'); - $tracker->expects(self::once())->method('endTracking'); - $transport = new InMemoryTransport(new InMemoryConfiguration(), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), ])); - $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher()); + $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())); $scheduler->schedule($task); $eventDispatcher = new EventDispatcher(); @@ -573,7 +529,7 @@ public function testTaskCanBeExecutedWithAfterExecutionCallback(): void new NullTaskRunner(), ]), new ExecutionPolicyRegistry([ new DefaultPolicy(), - ]), $tracker, new WorkerMiddlewareStack([ + ]), new TaskExecutionTracker(new Stopwatch()), new WorkerMiddlewareStack([ new SingleRunTaskMiddleware($transport), new TaskCallbackMiddleware(), new TaskLockBagMiddleware($lockFactory), @@ -601,7 +557,7 @@ public function testTaskCanBeExecutedWithRunner(): void $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack([ new TaskLockBagMiddleware(new LockFactory(new InMemoryStore())), - ]), $eventDispatcher); + ]), $eventDispatcher, lockFactory: new LockFactory(store: new InMemoryStore())); $scheduler->schedule(new NullTask('foo')); $lockFactory = new LockFactory(new InMemoryStore()); @@ -650,7 +606,7 @@ public function testEmptyTaskCannotBeExecuted(): void $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack([ new TaskLockBagMiddleware(new LockFactory(new InMemoryStore())), - ]), $eventDispatcher); + ]), $eventDispatcher, lockFactory: new LockFactory(store: new InMemoryStore())); $lockFactory = new LockFactory(new InMemoryStore()); @@ -683,15 +639,11 @@ public function testTaskCanBeExecutedAndTheWorkerCanReturnTheLastExecutedTask(): $logger = $this->createMock(LoggerInterface::class); $logger->expects(self::never())->method('info'); - $tracker = $this->createMock(TaskExecutionTrackerInterface::class); - $tracker->expects(self::once())->method('startTracking'); - $tracker->expects(self::once())->method('endTracking'); - $transport = new InMemoryTransport(new InMemoryConfiguration(), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), ])); - $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher()); + $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())); $scheduler->schedule($task); $eventDispatcher = new EventDispatcher(); @@ -703,7 +655,7 @@ public function testTaskCanBeExecutedAndTheWorkerCanReturnTheLastExecutedTask(): new NullTaskRunner(), ]), new ExecutionPolicyRegistry([ new DefaultPolicy(), - ]), $tracker, new WorkerMiddlewareStack([ + ]), new TaskExecutionTracker(new Stopwatch()), new WorkerMiddlewareStack([ new SingleRunTaskMiddleware($transport), new TaskLockBagMiddleware($lockFactory), ]), $eventDispatcher, $lockFactory, $logger); @@ -718,7 +670,6 @@ public function testTaskCanBeExecutedAndTheWorkerCanReturnTheLastExecutedTask(): public function testTaskCannotBeExecutedTwiceAsSingleRunTask(): void { $logger = $this->createMock(LoggerInterface::class); - $tracker = $this->createMock(TaskExecutionTrackerInterface::class); $shellTask = new ShellTask('foo', ['echo', 'Symfony']); $shellTask->setExpression('* * * * *'); @@ -736,7 +687,7 @@ public function testTaskCannotBeExecutedTwiceAsSingleRunTask(): void new FirstInFirstOutPolicy(), ])); - $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher()); + $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())); $scheduler->schedule($shellTask); $eventDispatcher = new EventDispatcher(); @@ -749,7 +700,7 @@ public function testTaskCannotBeExecutedTwiceAsSingleRunTask(): void $secondRunner, ]), new ExecutionPolicyRegistry([ new DefaultPolicy(), - ]), $tracker, new WorkerMiddlewareStack([ + ]), new TaskExecutionTracker(new Stopwatch()), new WorkerMiddlewareStack([ new SingleRunTaskMiddleware($transport), new TaskLockBagMiddleware($lockFactory), ]), $eventDispatcher, $lockFactory, $logger); @@ -771,13 +722,9 @@ public function testWorkerCanHandleFailedTask(): void $runner->expects(self::once())->method('support')->willReturn(true); $runner->expects(self::once())->method('run')->willThrowException(new RuntimeException('Random error occurred')); - $tracker = $this->createMock(TaskExecutionTrackerInterface::class); - $tracker->expects(self::once())->method('startTracking')->with(self::equalTo($task)); - $tracker->expects(self::never())->method('endTracking'); - $scheduler = new Scheduler('UTC', new InMemoryTransport(new InMemoryConfiguration(), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), - ])), new SchedulerMiddlewareStack(), new EventDispatcher()); + ])), new SchedulerMiddlewareStack(), new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())); $scheduler->schedule($task); $eventDispatcher = new EventDispatcher(); @@ -789,7 +736,7 @@ public function testWorkerCanHandleFailedTask(): void $runner, ]), new ExecutionPolicyRegistry([ new DefaultPolicy(), - ]), $tracker, new WorkerMiddlewareStack([ + ]), new TaskExecutionTracker(new Stopwatch()), new WorkerMiddlewareStack([ new TaskLockBagMiddleware($lockFactory), ]), $eventDispatcher, $lockFactory, $logger); $worker->execute(WorkerConfiguration::create()); @@ -818,15 +765,11 @@ public function testTaskCanBeExecutedWithoutBeforeExecutionNotificationAndNotifi $notifier = $this->createMock(NotifierInterface::class); $notifier->expects(self::never())->method('send'); - $tracker = $this->createMock(TaskExecutionTrackerInterface::class); - $tracker->expects(self::once())->method('startTracking'); - $tracker->expects(self::once())->method('endTracking'); - $transport = new InMemoryTransport(new InMemoryConfiguration(), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), ])); - $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher()); + $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())); $scheduler->schedule($task); $eventDispatcher = new EventDispatcher(); @@ -838,7 +781,7 @@ public function testTaskCanBeExecutedWithoutBeforeExecutionNotificationAndNotifi new NullTaskRunner(), ]), new ExecutionPolicyRegistry([ new DefaultPolicy(), - ]), $tracker, new WorkerMiddlewareStack([ + ]), new TaskExecutionTracker(new Stopwatch()), new WorkerMiddlewareStack([ new SingleRunTaskMiddleware($transport), new TaskCallbackMiddleware(), new NotifierMiddleware($notifier), @@ -868,15 +811,11 @@ public function testTaskCanBeExecutedWithBeforeExecutionNotificationAndNotifier( $notifier = $this->createMock(NotifierInterface::class); $notifier->expects(self::once())->method('send')->with(self::equalTo($notification), $recipient); - $tracker = $this->createMock(TaskExecutionTrackerInterface::class); - $tracker->expects(self::once())->method('startTracking'); - $tracker->expects(self::once())->method('endTracking'); - $transport = new InMemoryTransport(new InMemoryConfiguration(), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), ])); - $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher()); + $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())); $scheduler->schedule($task); $eventDispatcher = new EventDispatcher(); @@ -888,7 +827,7 @@ public function testTaskCanBeExecutedWithBeforeExecutionNotificationAndNotifier( new NullTaskRunner(), ]), new ExecutionPolicyRegistry([ new DefaultPolicy(), - ]), $tracker, new WorkerMiddlewareStack([ + ]), new TaskExecutionTracker(new Stopwatch()), new WorkerMiddlewareStack([ new SingleRunTaskMiddleware($transport), new TaskCallbackMiddleware(), new NotifierMiddleware($notifier), @@ -913,15 +852,11 @@ public function testTaskCanBeExecutedWithoutAfterExecutionNotificationAndNotifie $notifier = $this->createMock(NotifierInterface::class); $notifier->expects(self::never())->method('send'); - $tracker = $this->createMock(TaskExecutionTrackerInterface::class); - $tracker->expects(self::once())->method('startTracking'); - $tracker->expects(self::once())->method('endTracking'); - $transport = new InMemoryTransport(new InMemoryConfiguration(), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), ])); - $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher()); + $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())); $scheduler->schedule($task); $eventDispatcher = new EventDispatcher(); @@ -933,7 +868,7 @@ public function testTaskCanBeExecutedWithoutAfterExecutionNotificationAndNotifie new NullTaskRunner(), ]), new ExecutionPolicyRegistry([ new DefaultPolicy(), - ]), $tracker, new WorkerMiddlewareStack([ + ]), new TaskExecutionTracker(new Stopwatch()), new WorkerMiddlewareStack([ new SingleRunTaskMiddleware($transport), new TaskCallbackMiddleware(), new NotifierMiddleware($notifier), @@ -963,15 +898,11 @@ public function testTaskCanBeExecutedWithAfterExecutionNotificationAndNotifier() $notifier = $this->createMock(NotifierInterface::class); $notifier->expects(self::once())->method('send')->with(self::equalTo($notification), $recipient); - $tracker = $this->createMock(TaskExecutionTrackerInterface::class); - $tracker->expects(self::once())->method('startTracking'); - $tracker->expects(self::once())->method('endTracking'); - $transport = new InMemoryTransport(new InMemoryConfiguration(), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), ])); - $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher()); + $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())); $scheduler->schedule($task); $eventDispatcher = new EventDispatcher(); @@ -983,7 +914,7 @@ public function testTaskCanBeExecutedWithAfterExecutionNotificationAndNotifier() new NullTaskRunner(), ]), new ExecutionPolicyRegistry([ new DefaultPolicy(), - ]), $tracker, new WorkerMiddlewareStack([ + ]), new TaskExecutionTracker(new Stopwatch()), new WorkerMiddlewareStack([ new SingleRunTaskMiddleware($transport), new TaskCallbackMiddleware(), new NotifierMiddleware($notifier), @@ -1005,15 +936,11 @@ public function testWorkerCannotReserveMaxExecutionTokensWithoutRateLimiter(): v $logger = $this->createMock(LoggerInterface::class); $logger->expects(self::never())->method('info'); - $tracker = $this->createMock(TaskExecutionTrackerInterface::class); - $tracker->expects(self::once())->method('startTracking'); - $tracker->expects(self::once())->method('endTracking'); - $transport = new InMemoryTransport(new InMemoryConfiguration(), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), ])); - $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher()); + $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())); $scheduler->schedule($task); $eventDispatcher = new EventDispatcher(); @@ -1025,7 +952,7 @@ public function testWorkerCannotReserveMaxExecutionTokensWithoutRateLimiter(): v new NullTaskRunner(), ]), new ExecutionPolicyRegistry([ new DefaultPolicy(), - ]), $tracker, new WorkerMiddlewareStack([ + ]), new TaskExecutionTracker(new Stopwatch()), new WorkerMiddlewareStack([ new MaxExecutionMiddleware(), new SingleRunTaskMiddleware($transport), new TaskLockBagMiddleware($lockFactory), @@ -1047,15 +974,11 @@ public function testWorkerCannotReserveMaxExecutionTokensWithoutMaxExecutionLimi $logger = $this->createMock(LoggerInterface::class); $logger->expects(self::never())->method('info'); - $tracker = $this->createMock(TaskExecutionTrackerInterface::class); - $tracker->expects(self::once())->method('startTracking')->with(self::equalTo($task)); - $tracker->expects(self::once())->method('endTracking')->with(self::equalTo($task)); - $transport = new InMemoryTransport(new InMemoryConfiguration(), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), ])); - $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher()); + $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())); $scheduler->schedule($task); $eventDispatcher = new EventDispatcher(); @@ -1067,7 +990,7 @@ public function testWorkerCannotReserveMaxExecutionTokensWithoutMaxExecutionLimi new NullTaskRunner(), ]), new ExecutionPolicyRegistry([ new DefaultPolicy(), - ]), $tracker, new WorkerMiddlewareStack([ + ]), new TaskExecutionTracker(new Stopwatch()), new WorkerMiddlewareStack([ new MaxExecutionMiddleware(new RateLimiterFactory([ 'id' => 'foo', 'policy' => 'token_bucket', @@ -1096,15 +1019,11 @@ public function testWorkerCanReserveMaxExecutionTokensAndLimitTaskExecutionThenS $logger = $this->createMock(LoggerInterface::class); $logger->expects(self::never())->method('info'); - $tracker = $this->createMock(TaskExecutionTrackerInterface::class); - $tracker->expects(self::once())->method('startTracking')->with(self::equalTo($task)); - $tracker->expects(self::once())->method('endTracking')->with(self::equalTo($task)); - $transport = new InMemoryTransport(new InMemoryConfiguration(), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), ])); - $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher()); + $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())); $scheduler->schedule($task); $eventDispatcher = new EventDispatcher(); @@ -1116,7 +1035,7 @@ public function testWorkerCanReserveMaxExecutionTokensAndLimitTaskExecutionThenS new NullTaskRunner(), ]), new ExecutionPolicyRegistry([ new DefaultPolicy(), - ]), $tracker, new WorkerMiddlewareStack([ + ]), new TaskExecutionTracker(new Stopwatch()), new WorkerMiddlewareStack([ new MaxExecutionMiddleware(new RateLimiterFactory([ 'id' => 'foo', 'policy' => 'token_bucket', @@ -1150,15 +1069,11 @@ public function testWorkerCanStopWhenTaskAreConsumedAndWithoutDaemonEnabled(): v $logger = $this->createMock(LoggerInterface::class); $logger->expects(self::never())->method('info'); - $tracker = $this->createMock(TaskExecutionTrackerInterface::class); - $tracker->expects(self::once())->method('startTracking')->with(self::equalTo($task)); - $tracker->expects(self::once())->method('endTracking')->with(self::equalTo($task)); - $transport = new InMemoryTransport(new InMemoryConfiguration(), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), ])); - $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack([]), new EventDispatcher()); + $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack([]), new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())); $eventDispatcher = $this->createMock(EventDispatcherInterface::class); $eventDispatcher->expects(self::exactly(7))->method('dispatch'); @@ -1169,7 +1084,7 @@ public function testWorkerCanStopWhenTaskAreConsumedAndWithoutDaemonEnabled(): v new NullTaskRunner(), ]), new ExecutionPolicyRegistry([ new DefaultPolicy(), - ]), $tracker, new WorkerMiddlewareStack([ + ]), new TaskExecutionTracker(new Stopwatch()), new WorkerMiddlewareStack([ new SingleRunTaskMiddleware($transport), new TaskLockBagMiddleware($lockFactory), ]), $eventDispatcher, $lockFactory, $logger); @@ -1189,10 +1104,6 @@ public function testWorkerCanStopWhenTaskAreConsumedWithError(): void $logger = $this->createMock(LoggerInterface::class); $logger->expects(self::never())->method('info'); - $tracker = $this->createMock(TaskExecutionTrackerInterface::class); - $tracker->expects(self::once())->method('startTracking')->with(self::equalTo($task)); - $tracker->expects(self::never())->method('endTracking'); - $runner = $this->createMock(RunnerInterface::class); $runner->expects(self::once())->method('support')->with($task)->willReturn(true); $runner->expects(self::once())->method('run')->with($task)->willThrowException(new RuntimeException('An error occurred')); @@ -1201,7 +1112,7 @@ public function testWorkerCanStopWhenTaskAreConsumedWithError(): void new FirstInFirstOutPolicy(), ])); - $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher()); + $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())); $eventDispatcher = $this->createMock(EventDispatcherInterface::class); $eventDispatcher->expects(self::exactly(7))->method('dispatch'); @@ -1212,7 +1123,7 @@ public function testWorkerCanStopWhenTaskAreConsumedWithError(): void $runner, ]), new ExecutionPolicyRegistry([ new DefaultPolicy(), - ]), $tracker, new WorkerMiddlewareStack([ + ]), new TaskExecutionTracker(new Stopwatch()), new WorkerMiddlewareStack([ new SingleRunTaskMiddleware($transport), new TaskLockBagMiddleware($lockFactory), ]), $eventDispatcher, $lockFactory, $logger); @@ -1228,8 +1139,6 @@ public function testWorkerCanStopWhenTaskAreConsumedWithError(): void */ public function testPausedTaskIsNotExecutedIfListContainsASingleTask(): void { - $tracker = $this->createMock(TaskExecutionTrackerInterface::class); - $logger = $this->createMock(LoggerInterface::class); $logger->expects(self::exactly(2))->method('info')->withConsecutive([ self::equalTo('The following task "bar" is paused|disabled, consider enable it if it should be executed!'), @@ -1251,7 +1160,7 @@ public function testPausedTaskIsNotExecutedIfListContainsASingleTask(): void new FirstInFirstOutPolicy(), ])); - $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher()); + $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())); $scheduler->schedule(new NullTask('bar', [ 'access_lock_bag' => new AccessLockBag(new Key('bar')), @@ -1271,7 +1180,7 @@ public function testPausedTaskIsNotExecutedIfListContainsASingleTask(): void new NullTaskRunner(), ]), new ExecutionPolicyRegistry([ new DefaultPolicy(), - ]), $tracker, new WorkerMiddlewareStack([ + ]), new TaskExecutionTracker(new Stopwatch()), new WorkerMiddlewareStack([ new SingleRunTaskMiddleware($transport), new TaskUpdateMiddleware($transport), new TaskLockBagMiddleware($lockFactory), @@ -1299,7 +1208,7 @@ public function testWorkerCanExecuteChainedTasks(): void new FirstInFirstOutPolicy(), ])); - $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher()); + $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())); $scheduler->schedule($chainedTask); $scheduler->schedule($shellTask); @@ -1358,7 +1267,7 @@ public function testWorkerCanRetrieveTasksLazily(): void new FirstInFirstOutPolicy(), ])); - $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher()); + $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())); $scheduler->schedule($chainedTask); $scheduler->schedule($shellTask); @@ -1410,7 +1319,6 @@ public function testWorkerCanRetrieveTasksLazily(): void */ public function testWorkerCanExecuteLongRunningTask(): void { - $tracker = $this->createMock(TaskExecutionTrackerInterface::class); $logger = $this->createMock(LoggerInterface::class); $application = new Application(); @@ -1426,7 +1334,7 @@ public function testWorkerCanExecuteLongRunningTask(): void new FirstInFirstOutPolicy(), ])); - $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher()); + $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())); $scheduler->schedule($task); $lockFactory = new LockFactory(new InMemoryStore()); @@ -1435,7 +1343,7 @@ public function testWorkerCanExecuteLongRunningTask(): void new CommandTaskRunner($application), ]), new ExecutionPolicyRegistry([ new DefaultPolicy(), - ]), $tracker, new WorkerMiddlewareStack([ + ]), new TaskExecutionTracker(new Stopwatch()), new WorkerMiddlewareStack([ new SingleRunTaskMiddleware($transport), new TaskUpdateMiddleware($transport), new TaskLockBagMiddleware($lockFactory), @@ -1456,7 +1364,6 @@ public function testWorkerCanExecuteLongRunningTask(): void */ public function testWorkerCanExecuteTaskWithExecutionDelay(): void { - $tracker = $this->createMock(TaskExecutionTrackerInterface::class); $logger = $this->createMock(LoggerInterface::class); $task = new NullTask('foo', [ @@ -1468,7 +1375,7 @@ public function testWorkerCanExecuteTaskWithExecutionDelay(): void new FirstInFirstOutPolicy(), ])); - $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher()); + $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())); $scheduler->schedule($task); $lockFactory = new LockFactory(new InMemoryStore()); @@ -1477,7 +1384,7 @@ public function testWorkerCanExecuteTaskWithExecutionDelay(): void new NullTaskRunner(), ]), new ExecutionPolicyRegistry([ new DefaultPolicy(), - ]), $tracker, new WorkerMiddlewareStack([ + ]), new TaskExecutionTracker(new Stopwatch()), new WorkerMiddlewareStack([ new SingleRunTaskMiddleware($transport), new TaskUpdateMiddleware($transport), new TaskLockBagMiddleware($lockFactory), @@ -1497,14 +1404,13 @@ public function testWorkerCanExecuteTaskWithExecutionDelay(): void */ public function testWorkerCanStopWithEmptyTaskList(): void { - $tracker = $this->createMock(TaskExecutionTrackerInterface::class); $logger = $this->createMock(LoggerInterface::class); $transport = new InMemoryTransport(new InMemoryConfiguration(), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), ])); - $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher()); + $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())); $lockFactory = new LockFactory(new InMemoryStore()); @@ -1512,7 +1418,7 @@ public function testWorkerCanStopWithEmptyTaskList(): void new NullTaskRunner(), ]), new ExecutionPolicyRegistry([ new DefaultPolicy(), - ]), $tracker, new WorkerMiddlewareStack([ + ]), new TaskExecutionTracker(new Stopwatch()), new WorkerMiddlewareStack([ new SingleRunTaskMiddleware($transport), new TaskUpdateMiddleware($transport), new TaskLockBagMiddleware($lockFactory), @@ -1533,14 +1439,13 @@ public function testWorkerCanStopWithEmptyTaskList(): void */ public function testWorkerCanStopWithoutExecutedTasks(): void { - $tracker = $this->createMock(TaskExecutionTrackerInterface::class); $logger = $this->createMock(LoggerInterface::class); $transport = new InMemoryTransport(new InMemoryConfiguration(), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), ])); - $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher()); + $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())); $scheduler->schedule(new NullTask('foo')); $lockFactory = new LockFactory(new InMemoryStore()); @@ -1549,7 +1454,7 @@ public function testWorkerCanStopWithoutExecutedTasks(): void new ShellTaskRunner(), ]), new ExecutionPolicyRegistry([ new DefaultPolicy(), - ]), $tracker, new WorkerMiddlewareStack([ + ]), new TaskExecutionTracker(new Stopwatch()), new WorkerMiddlewareStack([ new SingleRunTaskMiddleware($transport), new TaskUpdateMiddleware($transport), new TaskLockBagMiddleware($lockFactory), @@ -1568,14 +1473,13 @@ public function testWorkerCanStopWithoutExecutedTasks(): void */ public function testWorkerCanStopWhenTasksAreExecutedAndWithoutSleepOptionTwice(): void { - $tracker = $this->createMock(TaskExecutionTrackerInterface::class); $logger = $this->createMock(LoggerInterface::class); $transport = new InMemoryTransport(new InMemoryConfiguration(), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), ])); - $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher()); + $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())); $scheduler->schedule(new NullTask('foo')); $lockFactory = new LockFactory(new InMemoryStore()); @@ -1584,7 +1488,7 @@ public function testWorkerCanStopWhenTasksAreExecutedAndWithoutSleepOptionTwice( new NullTaskRunner(), ]), new ExecutionPolicyRegistry([ new DefaultPolicy(), - ]), $tracker, new WorkerMiddlewareStack([ + ]), new TaskExecutionTracker(new Stopwatch()), new WorkerMiddlewareStack([ new SingleRunTaskMiddleware($transport), new TaskUpdateMiddleware($transport), new TaskLockBagMiddleware($lockFactory), @@ -1612,13 +1516,12 @@ public function testWorkerCanStopWhenTasksAreExecutedAndWithoutSleepOptionTwice( public function testWorkerCanBePaused(): void { $logger = $this->createMock(LoggerInterface::class); - $tracker = $this->createMock(TaskExecutionTrackerInterface::class); $transport = new InMemoryTransport(new InMemoryConfiguration(), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), ])); - $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher()); + $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())); $scheduler->schedule(new NullTask('foo')); $eventDispatcher = new EventDispatcher(); @@ -1645,7 +1548,7 @@ public function testWorkerCanBePaused(): void new NullTaskRunner(), ]), new ExecutionPolicyRegistry([ new DefaultPolicy(), - ]), $tracker, new WorkerMiddlewareStack([ + ]), new TaskExecutionTracker(new Stopwatch()), new WorkerMiddlewareStack([ new SingleRunTaskMiddleware($transport), new TaskUpdateMiddleware($transport), new TaskLockBagMiddleware($lockFactory), @@ -1665,13 +1568,12 @@ public function testWorkerCanBePaused(): void public function testWorkerCanBeRestarted(): void { $logger = $this->createMock(LoggerInterface::class); - $tracker = $this->createMock(TaskExecutionTrackerInterface::class); $transport = new InMemoryTransport(new InMemoryConfiguration(), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), ])); - $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher()); + $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())); $scheduler->schedule(new NullTask('foo')); $eventDispatcher = new EventDispatcher(); @@ -1692,7 +1594,7 @@ public function testWorkerCanBeRestarted(): void new NullTaskRunner(), ]), new ExecutionPolicyRegistry([ new DefaultPolicy(), - ]), $tracker, new WorkerMiddlewareStack([ + ]), new TaskExecutionTracker(new Stopwatch()), new WorkerMiddlewareStack([ new SingleRunTaskMiddleware($transport), new TaskUpdateMiddleware($transport), new TaskLockBagMiddleware($lockFactory), @@ -1714,13 +1616,12 @@ public function testWorkerCanBeRestarted(): void public function testWorkerCanPreempt(): void { $logger = $this->createMock(LoggerInterface::class); - $tracker = $this->createMock(TaskExecutionTrackerInterface::class); $transport = new InMemoryTransport(new InMemoryConfiguration(), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), ])); - $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher()); + $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())); $lockFactory = new LockFactory(new InMemoryStore()); @@ -1728,7 +1629,7 @@ public function testWorkerCanPreempt(): void new NullTaskRunner(), ]), new ExecutionPolicyRegistry([ new DefaultPolicy(), - ]), $tracker, new WorkerMiddlewareStack([ + ]), new TaskExecutionTracker(new Stopwatch()), new WorkerMiddlewareStack([ new SingleRunTaskMiddleware($transport), new TaskUpdateMiddleware($transport), new TaskLockBagMiddleware($lockFactory), @@ -1761,13 +1662,12 @@ public function testWorkerCanPreempt(): void public function testWorkerCannotPreemptEmptyList(): void { $logger = $this->createMock(LoggerInterface::class); - $tracker = $this->createMock(TaskExecutionTrackerInterface::class); $transport = new InMemoryTransport(new InMemoryConfiguration(), new SchedulePolicyOrchestrator([ new FirstInFirstOutPolicy(), ])); - $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher()); + $scheduler = new Scheduler('UTC', $transport, new SchedulerMiddlewareStack(), new EventDispatcher(), lockFactory: new LockFactory(store: new InMemoryStore())); $lockFactory = new LockFactory(new InMemoryStore()); @@ -1775,7 +1675,7 @@ public function testWorkerCannotPreemptEmptyList(): void new NullTaskRunner(), ]), new ExecutionPolicyRegistry([ new DefaultPolicy(), - ]), $tracker, new WorkerMiddlewareStack([ + ]), new TaskExecutionTracker(new Stopwatch()), new WorkerMiddlewareStack([ new SingleRunTaskMiddleware($transport), new TaskUpdateMiddleware($transport), new TaskLockBagMiddleware($lockFactory),