diff --git a/src/Attributes/Queueable.php b/src/Attributes/Queueable.php new file mode 100644 index 0000000..056d6be --- /dev/null +++ b/src/Attributes/Queueable.php @@ -0,0 +1,22 @@ +executeWithTiming(function () { - $name = $this->argument('name'); - $parts = explode('/', $name); - $className = array_pop($parts); - - // Ensure class name ends with Job - if (!str_ends_with($className, 'Job')) { - $className .= 'Job'; - } - - $namespace = 'App\\Jobs' . (count($parts) > 0 ? '\\' . implode('\\', $parts) : ''); - $filePath = base_path('app/Jobs/' . str_replace('/', DIRECTORY_SEPARATOR, $name) . '.php'); - - // Check if Job already exists - if (file_exists($filePath)) { - $this->displayError('Job already exists at:'); - $this->line('' . str_replace(base_path(), '', $filePath) . ''); - return Command::FAILURE; - } - - // Create directory if needed - $directoryPath = dirname($filePath); - if (!is_dir($directoryPath)) { - mkdir($directoryPath, 0755, true); - } - - // Generate and save Job class - $content = $this->generateJobContent($namespace, $className); - file_put_contents($filePath, $content); - - $this->displaySuccess('Job created successfully'); - $this->line('📦 File: ' . str_replace(base_path(), '', $filePath) . ''); - $this->newLine(); - $this->line('⚙️ Class: ' . $className . ''); - - return Command::SUCCESS; - }); - } - - /** - * Generate Job class content. - */ - protected function generateJobContent(string $namespace, string $className): string - { - return <<dispatch(); + } + + /** + * Dispatch the job synchronously with the given arguments. + * + * @param mixed ...$args + * @return void + */ + public static function queueAsSync(...$args): void + { + (new static(...$args))->handle(); + } + + /** + * Dispatch the job after a delay with the given arguments. + * + * @param int $delay + * @param mixed ...$args + * @return string Job ID + */ + public static function queueAfter(int $delay, ...$args): string + { + return (new static(...$args))->delayFor($delay)->forceQueue(); + } + + /** + * Dispatch the job to a specific queue with the given arguments. + * + * @param string $queue + * @param mixed ...$args + * @return string Job ID + */ + public static function queueOn(string $queue, ...$args): string + { + return (new static(...$args))->onQueue($queue)->forceQueue(); + } +} diff --git a/src/InteractsWithQueueableAttributes.php b/src/InteractsWithQueueableAttributes.php new file mode 100644 index 0000000..f3400b3 --- /dev/null +++ b/src/InteractsWithQueueableAttributes.php @@ -0,0 +1,52 @@ +getAttributes(Queueable::class); + + return !empty($attributes); + } + + /** + * Apply the Queueable attribute settings to the job. + * + * @return void + */ + protected function applyQueueableAttributes(): void + { + $reflection = new \ReflectionClass($this); + $attributes = $reflection->getAttributes(Queueable::class); + + if (!empty($attributes)) { + $attribute = $attributes[0]->newInstance(); + + if ($attribute->tries !== null) { + $this->tries = $attribute->tries; + } + + if ($attribute->retryAfter !== null) { + $this->retryAfter = $attribute->retryAfter; + } + + if ($attribute->delayFor !== null) { + $this->jobDelay = $attribute->delayFor; + } + + if ($attribute->onQueue !== null) { + $this->queueName = $attribute->onQueue; + } + } + } +} \ No newline at end of file diff --git a/src/Job.php b/src/Job.php index bc187df..d5525d8 100644 --- a/src/Job.php +++ b/src/Job.php @@ -7,6 +7,8 @@ abstract class Job implements JobInterface { + use InteractsWithQueueableAttributes; + /** * The number of times the job may be attempted. * @@ -150,11 +152,19 @@ public function delayFor(int $delay): self /** * Dispatch the job to the queue. * - * @return string Job ID + * @return string|null */ - public function dispatch(): string + public function dispatch(): ?string { - return Queue::push($this); + $this->applyQueueableAttributes(); + + if ($this->shouldQueue()) { + return Queue::push($this); + } + + $this->handle(); + + return null; } /** @@ -167,6 +177,8 @@ public function dispatchAfter(int $delay): string { $this->delayFor($delay); + $this->applyQueueableAttributes(); + return $this->dispatch(); } @@ -180,6 +192,8 @@ public function dispatchOn(string $queue): string { $this->onQueue($queue); + $this->applyQueueableAttributes(); + return $this->dispatch(); } @@ -195,4 +209,29 @@ public static function dispatchNow(...$args): string return $job->dispatch(); } + + /** + * Dispatch the job synchronously + * + * @param mixed ...$args + * @return void + */ + public static function dispatchSync(...$args): void + { + $job = new static(...$args); + + $job->handle(); + } + + /** + * Force the job to be queued even without Queueable attribute. + * + * @return string Job ID + */ + public function forceQueue(): string + { + $this->applyQueueableAttributes(); + + return Queue::push($this); + } } diff --git a/src/QueueServiceProvider.php b/src/QueueServiceProvider.php index e6e5408..8f42c75 100644 --- a/src/QueueServiceProvider.php +++ b/src/QueueServiceProvider.php @@ -8,7 +8,6 @@ use Doppar\Queue\Commands\QueueRetryCommand; use Doppar\Queue\Commands\QueueFlushCommand; use Doppar\Queue\Commands\QueueFailedCommand; -use Doppar\Queue\Commands\MakeJobCommand; use Doppar\Queue\Commands\QueueMonitorCommand; class QueueServiceProvider extends ServiceProvider @@ -39,7 +38,6 @@ public function boot(): void $this->commands([ QueueRunCommand::class, QueueRetryCommand::class, - MakeJobCommand::class, QueueFlushCommand::class, QueueFailedCommand::class, QueueMonitorCommand::class