Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 9 additions & 8 deletions composer.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
{
"name": "doppar/guard",
"description": "A authorization package for doppar framework",
"name": "doppar/queue",
"description": "A lightweight queue management library for the Doppar framework.",
"type": "library",
"license": "MIT",
"support": {
"issues": "https://github.com/doppar/guard/issues",
"source": "https://github.com/doppar/guard"
"issues": "https://github.com/doppar/queue/issues",
"source": "https://github.com/doppar/queue"
},
"authors": [
{
Expand All @@ -15,16 +15,17 @@
],
"require-dev": {
"mockery/mockery": "^1.6",
"phpunit/phpunit": "^12.1.5"
"phpunit/phpunit": "^12.1.5",
"doppar/framework": "^3.0.0"
},
"autoload": {
"psr-4": {
"Doppar\\Authorizer\\": "src/"
"Doppar\\Queue\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"Doppar\\Authorizer\\Tests\\": "tests/"
"Doppar\\Queue\\Tests\\": "tests/"
}
},
"extra": {
Expand All @@ -33,7 +34,7 @@
},
"doppar": {
"providers": [
"Doppar\\Authorizer\\GuardServiceProvider"
"Doppar\\Queue\\QueueServiceProvider"
]
}
},
Expand Down
16 changes: 12 additions & 4 deletions phpunit.xml.dist
Original file line number Diff line number Diff line change
@@ -1,11 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit colors="true">
<phpunit backupGlobals="false" beStrictAboutTestsThatDoNotTestAnything="false" colors="true" processIsolation="false" stopOnError="false" stopOnFailure="false" cacheDirectory=".phpunit.cache" backupStaticProperties="false">
<testsuites>
<testsuite name="Unit">
<directory suffix="Test.php">./tests/Unit</directory>
<testsuite name="Doppar Test Suite">
<directory suffix="Test.php">./tests</directory>
</testsuite>
</testsuites>
<php>
<env name="APP_KEY" value="base64:7n/+NIB4i3LQ6+ZbrclxuwyEqG5Uprufs90NJGL2pls="/>
<ini name="date.timezone" value="UTC" />
<ini name="intl.default_locale" value="C.UTF-8" />
<ini name="memory_limit" value="2048M" />
<env name="DB_CONNECTION" value="testing" />
<!--
<env name="REDIS_CLIENT" value="phpredis" />
<env name="REDIS_HOST" value="127.0.0.1" />
<env name="REDIS_PORT" value="6379" />
-->
</php>
</phpunit>
9 changes: 9 additions & 0 deletions storage/logs/doppar.log
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[2025-11-14T08:38:24.717063+00:00] stack.ERROR: Failed to mark job as failed: Database connection [] not configured.
[2025-11-14T08:38:57.213083+00:00] stack.ERROR: Failed to mark job as failed: Database connection [] not configured.
[2025-11-14T08:39:33.718229+00:00] stack.ERROR: Failed to mark job as failed: Database connection [] not configured.
[2025-11-14T08:43:01.934544+00:00] stack.ERROR: Failed to mark job as failed: Database connection [] not configured.
[2025-11-14T08:44:10.792443+00:00] stack.ERROR: Failed to mark job as failed: Database connection [] not configured.
[2025-11-14T08:45:01.563845+00:00] stack.ERROR: Failed to mark job as failed: Database connection [] not configured.
[2025-11-14T08:45:05.456173+00:00] stack.ERROR: Failed to mark job as failed: Database connection [] not configured.
[2025-11-14T08:45:57.038190+00:00] stack.ERROR: Failed to mark job as failed: Database connection [] not configured.
[2025-11-14T08:47:51.149909+00:00] stack.ERROR: Failed to mark job as failed: Database connection [] not configured.
22 changes: 22 additions & 0 deletions tests/Mock/Jobs/TestComplexDataJob.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

namespace Doppar\Queue\Tests\Mock\Jobs;

use Doppar\Queue\Job;

class TestComplexDataJob extends Job
{
public $data;

public function __construct(array $data)
{
$this->data = $data;
}

public function handle(): void
{
if (empty($this->data)) {
throw new \RuntimeException('No data provided');
}
}
}
15 changes: 15 additions & 0 deletions tests/Mock/Jobs/TestCounterJob.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

namespace Doppar\Queue\Tests\Mock\Jobs;

use Doppar\Queue\Job;

class TestCounterJob extends Job
{
public $counter = 0;

public function handle(): void
{
$this->counter++;
}
}
27 changes: 27 additions & 0 deletions tests/Mock/Jobs/TestEmailJob.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

namespace Doppar\Queue\Tests\Mock\Jobs;

use Doppar\Queue\Job;

class TestEmailJob extends Job
{
public $tries = 3;
public $retryAfter = 60;
public $to;
public $subject;

public function __construct(string $to, string $subject)
{
$this->to = $to;
$this->subject = $subject;
}

public function handle(): void
{
// Simulate sending email
if (empty($this->to) || empty($this->subject)) {
throw new \RuntimeException('Invalid email data');
}
}
}
16 changes: 16 additions & 0 deletions tests/Mock/Jobs/TestFailingJob.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

namespace Doppar\Queue\Tests\Mock\Jobs;

use Doppar\Queue\Job;

class TestFailingJob extends Job
{
public $tries = 3;
public $retryAfter = 60;

public function handle(): void
{
throw new \RuntimeException('Test failure');
}
}
24 changes: 24 additions & 0 deletions tests/Mock/Jobs/TestImageJob.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

namespace Doppar\Queue\Tests\Mock\Jobs;

use Doppar\Queue\Job;

class TestImageJob extends Job
{
public $tries = 3;
public $retryAfter = 120;
public $imagePath;

public function __construct(string $imagePath)
{
$this->imagePath = $imagePath;
}

public function handle(): void
{
if (empty($this->imagePath)) {
throw new \RuntimeException('Invalid image path');
}
}
}
21 changes: 21 additions & 0 deletions tests/Mock/Jobs/TestJobWithFailedCallback.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

namespace Doppar\Queue\Tests\Mock\Jobs;

use Doppar\Queue\Job;

class TestJobWithFailedCallback extends Job
{
public $tries = 1;
public $failedCalled = false;

public function handle(): void
{
throw new \RuntimeException('Intentional failure');
}

public function failed(\Throwable $exception): void
{
$this->failedCalled = true;
}
}
24 changes: 24 additions & 0 deletions tests/Mock/Jobs/TestReportJob.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

namespace Doppar\Queue\Tests\Mock\Jobs;

use Doppar\Queue\Job;

class TestReportJob extends Job
{
public $tries = 2;
public $retryAfter = 300;
public $reportType;

public function __construct(string $reportType)
{
$this->reportType = $reportType;
}

public function handle(): void
{
if (empty($this->reportType)) {
throw new \RuntimeException('Invalid report type');
}
}
}
24 changes: 24 additions & 0 deletions tests/Mock/MockContainer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

namespace Doppar\Queue\Tests\Mock;

use Phaseolies\DI\Container;

class MockContainer extends Container
{
public function storagePath(string $path = ''): string
{
$base = sys_get_temp_dir() . '/phaseolies_storage';

if (!is_dir($base)) {
mkdir($base, 0777, true);
}

return $path ? $base . DIRECTORY_SEPARATOR . $path : $base;
}

public function runningInConsole(): bool
{
return true;
}
}
36 changes: 36 additions & 0 deletions tests/Mock/Models/MockFailedJob.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

namespace Doppar\Queue\Tests\Mock\Models;

use Phaseolies\Database\Entity\Model;

class MockFailedJob extends Model
{
/**
* The table associated with the model.
*
* @var string
*/
protected $table = 'failed_jobs';
protected $connection = 'default';

/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $creatable = [
'connection',
'queue',
'payload',
'exception',
'failed_at',
];

/**
* Indicates if the model should be timestamped.
*
* @var bool
*/
public $timeStamps = false;
}
93 changes: 93 additions & 0 deletions tests/Mock/Models/MockQueueJob.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
<?php

namespace Doppar\Queue\Tests\Mock\Models;

use Phaseolies\Database\Entity\Model;
use Phaseolies\Database\Entity\Builder;

class MockQueueJob extends Model
{
/**
* The table associated with the model.
*
* @var string
*/
protected $table = 'queue_jobs';
protected $connection = 'default';

/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $creatable = [
'queue',
'payload',
'attempts',
'reserved_at',
'available_at',
'created_at',
];

/**
* Indicates if the model should be timestamped.
*
* @var bool
*/
public $timeStamps = false;

/**
* Scope a query to only include available jobs.
*
* @param \Phaseolies\Database\Entity\Builder $query
* @param string $queue
* @return \Phaseolies\Database\Entity\Builder
*/
public function __available(Builder $query, string $queue = 'default'): Builder
{
return $query->where('queue', $queue)
->where(function ($q) {
$q->whereNull('reserved_at')
->orWhere('reserved_at', 0);
})
->where('available_at', '<=', time())
->orderBy('id', 'asc');
}

/**
* Mark the job as reserved.
*
* @return bool
*/
public function reserve(): bool
{
$this->reserved_at = time();
$this->attempts += 1;

return $this->save();
}

/**
* Release the job back to the queue.
*
* @param int $delay
* @return bool
*/
public function release(int $delay = 0): bool
{
$this->reserved_at = null;
$this->available_at = time() + $delay;

return $this->save();
}

/**
* Delete the job from the queue.
*
* @return bool|null
*/
public function deleteJob(): ?bool
{
return $this->delete();
}
}
Loading