Skip to content

Commit

Permalink
Codestyle fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
luzrain committed Feb 10, 2024
1 parent ef5be94 commit 1cde1a4
Show file tree
Hide file tree
Showing 12 changed files with 64 additions and 35 deletions.
3 changes: 0 additions & 3 deletions .php-cs-fixer.dist.php
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,6 @@
// Empty body of class, interface, trait, enum or function must be abbreviated as {} and placed on the same line
'single_line_empty_body' => false,

// Class DateTimeImmutable should be used instead of DateTime.
'date_time_immutable' => true,

// Functions should be used with $strict param set to true.
'strict_param' => true,

Expand Down
14 changes: 14 additions & 0 deletions psalm.xml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,20 @@
<directory name="src" />
<ignoreFiles>
<directory name="vendor" />
<file name="src/config/configuration.php" />
</ignoreFiles>
</projectFiles>

<issueHandlers>
<UnresolvableInclude>
<errorLevel type="suppress">
<directory name="src" />
</errorLevel>
</UnresolvableInclude>
<ForbiddenCode>
<errorLevel type="suppress">
<directory name="src" />
</errorLevel>
</ForbiddenCode>
</issueHandlers>
</psalm>
2 changes: 1 addition & 1 deletion src/Internal/Functions.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public static function cpuCount(): int
{
if (\PHP_VERSION_ID >= 80300) {
return \posix_sysconf(\POSIX_SC_NPROCESSORS_ONLN);

Check failure on line 19 in src/Internal/Functions.php

View workflow job for this annotation

GitHub Actions / ubuntu-latest - PHP 8.2

UndefinedFunction

src/Internal/Functions.php:19:20: UndefinedFunction: Function posix_sysconf does not exist (see https://psalm.dev/021)

Check failure on line 19 in src/Internal/Functions.php

View workflow job for this annotation

GitHub Actions / ubuntu-latest - PHP 8.2

UndefinedConstant

src/Internal/Functions.php:19:35: UndefinedConstant: Const POSIX_SC_NPROCESSORS_ONLN is not defined (see https://psalm.dev/020)
} else if (\DIRECTORY_SEPARATOR === '/' && \function_exists('shell_exec')) {
} elseif (\DIRECTORY_SEPARATOR === '/' && \function_exists('shell_exec')) {
return \strtolower(\PHP_OS) === 'darwin'
? (int) \shell_exec('sysctl -n machdep.cpu.core_count')
: (int) \shell_exec('nproc');
Expand Down
1 change: 1 addition & 0 deletions src/KernelFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
private bool $isDebug;
private string $projectDir;

/** @psalm-suppress InvalidPropertyAssignmentValue */
public function __construct(private \Closure $app, private array $args, array $options)
{
$this->projectDir = $options['project_dir'];
Expand Down
11 changes: 7 additions & 4 deletions src/Scheduler/Trigger/CronExpressionTrigger.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,23 @@

use Cron\CronExpression;

/**
* @psalm-suppress UndefinedClass
*/
final class CronExpressionTrigger implements TriggerInterface
{
private CronExpression $expression;

public function __construct(string $expression)
{
if (!class_exists(CronExpression::class)) {
throw new \LogicException(sprintf('You cannot use "%s" as the "cron expression" package is not installed. Try running "composer require dragonmantank/cron-expression".', __CLASS__));
if (!\class_exists(CronExpression::class)) {
throw new \LogicException(\sprintf('You cannot use "%s" as the "cron expression" package is not installed. Try running "composer require dragonmantank/cron-expression".', __CLASS__));
}

try {
$this->expression = new CronExpression($expression);
} catch (\InvalidArgumentException $e) {
throw new \InvalidArgumentException(sprintf('Invalid cron expression "%s"', $expression), 0, $e);
throw new \InvalidArgumentException(\sprintf('Invalid cron expression "%s"', $expression), 0, $e);
}
}

Expand All @@ -31,6 +34,6 @@ public function __toString(): string
public function getNextRunDate(\DateTimeImmutable $now): \DateTimeImmutable|null
{
$next = $this->expression->getNextRunDate($now);
return $next instanceof \Datetime ? \DateTimeImmutable::createFromMutable($next) : $next;
return $next instanceof \DateTime ? \DateTimeImmutable::createFromMutable($next) : $next;
}
}
6 changes: 3 additions & 3 deletions src/Scheduler/Trigger/DateTimeTrigger.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,15 @@ final class DateTimeTrigger implements TriggerInterface

public function __construct(string|\DateTimeImmutable $date)
{
if (is_string($date) && $iso8601Date = \DateTimeImmutable::createFromFormat(\DateTimeInterface::ATOM, $date)) {
if (\is_string($date) && $iso8601Date = \DateTimeImmutable::createFromFormat(\DateTimeInterface::ATOM, $date)) {
$date = $iso8601Date;
}

if (is_string($date)) {
if (\is_string($date)) {
try {
$this->date = new \DateTimeImmutable($date);
} catch (\Exception $e) {
throw new \InvalidArgumentException(sprintf('Invalid date string "%s": %s', $date, $e->getMessage()), 0, $e);
throw new \InvalidArgumentException(\sprintf('Invalid date string "%s": %s', $date, $e->getMessage()), 0, $e);
}
} else {
$this->date = $date;
Expand Down
8 changes: 6 additions & 2 deletions src/Scheduler/Trigger/JitterTrigger.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,15 @@ public function __construct(private readonly TriggerInterface $trigger, private

public function __toString(): string
{
return sprintf('%s with 0-%d second jitter', $this->trigger, $this->jitter);
return \sprintf('%s with 0-%d second jitter', $this->trigger, $this->jitter);
}

/**
* @psalm-suppress FalsableReturnStatement
* @psalm-suppress InvalidFalsableReturnType
*/
public function getNextRunDate(\DateTimeImmutable $now): \DateTimeImmutable|null
{
return $this->trigger->getNextRunDate($now)?->modify(sprintf('+%d seconds', random_int(0, $this->jitter)));
return $this->trigger->getNextRunDate($now)?->modify(\sprintf('+%d seconds', \random_int(0, $this->jitter)));
}
}
16 changes: 8 additions & 8 deletions src/Scheduler/Trigger/PeriodicalTrigger.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,22 +12,22 @@ final class PeriodicalTrigger implements TriggerInterface
public function __construct(string|int|\DateInterval $interval)
{
try {
if (is_numeric($interval)) {
$this->interval = \DateInterval::createFromDateString(sprintf('%d seconds', $interval));
$this->description = sprintf('every %s seconds', $interval);
} elseif (\is_string($interval) && str_starts_with($interval, 'P')) {
if (\is_numeric($interval)) {
$this->interval = \DateInterval::createFromDateString(\sprintf('%d seconds', $interval));
$this->description = \sprintf('every %s seconds', $interval);
} elseif (\is_string($interval) && \str_starts_with($interval, 'P')) {
$this->interval = new \DateInterval($interval);
$this->description = sprintf('DateInterval (%s)', $interval);
$this->description = \sprintf('DateInterval (%s)', $interval);
} elseif (\is_string($interval)) {
$this->interval = @\DateInterval::createFromDateString($interval);
$this->description = sprintf('every %s', $interval);
$this->description = \sprintf('every %s', $interval);
} else {
$this->interval = $interval;
$a = (array) $interval;
$this->description = isset($a['from_string']) ? sprintf('every %s', $a['date_string']) : 'DateInterval';
$this->description = isset($a['from_string']) ? \sprintf('every %s', $a['date_string']) : 'DateInterval';
}
} catch (\Throwable $e) {
throw new \InvalidArgumentException(sprintf('Invalid interval "%s": %s', $interval instanceof \DateInterval ? 'instance of \DateInterval' : $interval, $e->getMessage()), 0, $e);
throw new \InvalidArgumentException(\sprintf('Invalid interval "%s": %s', $interval instanceof \DateInterval ? 'instance of \DateInterval' : $interval, $e->getMessage()), 0, $e);
}
}

Expand Down
8 changes: 5 additions & 3 deletions src/Scheduler/Trigger/TriggerFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,14 @@ final class TriggerFactory
*/
public static function create(string|int|\DateInterval|\DateTimeImmutable $expression, int $jitter = 0): TriggerInterface
{
$expression = \DateTimeImmutable::createFromFormat(\DateTimeInterface::ATOM, $expression) ?: $expression;
if (\is_string($expression)) {
$expression = \DateTimeImmutable::createFromFormat(\DateTimeInterface::ATOM, $expression) ?: $expression;
}

$trigger = match (true) {
$expression instanceof \DateTimeImmutable => new DateTimeTrigger($expression),
count(explode(' ', $expression)) === 5 && str_contains($expression, '*'),
str_starts_with($expression, '@') => new CronExpressionTrigger($expression),
\is_string($expression) && \count(\explode(' ', $expression)) === 5 && \str_contains($expression, '*'),
\is_string($expression) && \str_starts_with($expression, '@') => new CronExpressionTrigger($expression),
default => new PeriodicalTrigger($expression),
};

Expand Down
2 changes: 0 additions & 2 deletions src/Worker/HttpServerWorker.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@
use Luzrain\PhpRunnerBundle\Event\HttpServerStartEvent;
use Luzrain\PhpRunnerBundle\KernelFactory;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Log\LoggerInterface;
use Symfony\Component\ErrorHandler\ErrorHandler;
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;

final class HttpServerWorker extends WorkerProcess
Expand Down
1 change: 1 addition & 0 deletions src/Worker/ProcessWorker.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ private function onStart(): void
/** @var Application $application */
$application = $kernel->getContainer()->get('phprunner.application');

/** @psalm-suppress RiskyTruthyFalsyComparison */
if ($application->has(\strstr($this->command, ' ', true) ?: $this->command)) {
$this->runSymfonyCommand($application, $this->command);
} else {
Expand Down
27 changes: 18 additions & 9 deletions src/Worker/SchedulerWorker.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public function __construct(
private readonly KernelFactory $kernelFactory,
string|null $user,
string|null $group,
/** @var array{name: string, schedule: string, jitter: int, command: string} $tasks */
/** @var array{name: string|null, schedule: string, jitter: int, command: string} */
private readonly array $tasks,
) {
parent::__construct(
Expand All @@ -41,16 +41,24 @@ private function onStart(): void
$this->kernel->boot();
$this->kernel->getContainer()->get('phprunner.worker_configurator')->configure($this);

/**
* @var string|null $name
* @var string $schedule
* @var int $jitter
* @var string $command
* @psalm-suppress InvalidArrayAccess
* @psalm-suppress InvalidArrayOffset
*/
foreach ($this->tasks as ['name' => $name, 'schedule' => $schedule, 'jitter' => $jitter, 'command' => $command]) {
$name ??= $command;
try {
$trigger = TriggerFactory::create($schedule, $jitter);
} catch (\InvalidArgumentException) {
$this->getLogger()->warning(sprintf('Task "%s" skipped. Schedule "%s" is incorrect', $name, $schedule));
$this->getLogger()->warning(\sprintf('Task "%s" skipped. Schedule "%s" is incorrect', $name, $schedule));
continue;
}

$this->getLogger()->info(sprintf('Task "%s" scheduled. Schedule: "%s"', $name, $trigger));
$this->getLogger()->info(\sprintf('Task "%s" scheduled. Schedule: "%s"', $name, $trigger));
$this->scheduleCommand($trigger, $name, $command);
}

Expand Down Expand Up @@ -88,34 +96,35 @@ private function scheduleCommand(TriggerInterface $trigger, string $name, string
$nextRunDate = $trigger->getNextRunDate($currentDate);
if ($nextRunDate !== null) {
$interval = $nextRunDate->getTimestamp() - $currentDate->getTimestamp();
$this->getEventLoop()->delay($interval, fn () => $this->runCommand($trigger, $name, $command));
$this->getEventLoop()->delay($interval, fn() => $this->runCommand($trigger, $name, $command));
}
}

private function runCommand(TriggerInterface $trigger, string $name, string $command): void
{
// Reschedule task without running it if previous task is still running
if (\in_array($taskHash = \hash('xxh64', $trigger . $name . $command), $this->runningTaskMap)) {
if (\in_array($taskHash = \hash('xxh64', $trigger . $name . $command), $this->runningTaskMap, true)) {
$this->scheduleCommand($trigger, $name, $command);
return;
}

/** @var Application $application */
$application = $this->kernel->getContainer()->get('phprunner.application');

/** @psalm-suppress RiskyTruthyFalsyComparison */
if ($application->has(\strstr($command, ' ', true) ?: $command)) {
// If command is symfony console command execute it in a forked process
if (-1 === $pid = $this->runSymfonyCommand($application, $command)) {
$this->getLogger()->error(sprintf('Task "%s" call error!', $name));
$this->getLogger()->error(\sprintf('Task "%s" call error!', $name));
} else {
$this->getLogger()->info(sprintf('Task "%s" called', $name));
$this->getLogger()->info(\sprintf('Task "%s" called', $name));
$this->runningTaskMap[$pid] = $taskHash;
$this->scheduleCommand($trigger, $name, $command);
}
} else {
$this->getLogger()->info(sprintf('Task "%s" called', $name));
$this->getLogger()->info(\sprintf('Task "%s" called', $name));
$pid = $this->runExternalCommand($command, function (string $error) use ($name) {
$this->getLogger()->error(sprintf('Task "%s" call error!', $name), ['error' => $error]);
$this->getLogger()->error(\sprintf('Task "%s" call error!', $name), ['error' => $error]);
});
$this->runningTaskMap[$pid] = $taskHash;
$this->scheduleCommand($trigger, $name, $command);
Expand Down

0 comments on commit 1cde1a4

Please sign in to comment.