first commit
This commit is contained in:
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* @file classes/job/casts/DatetimeToInt.php
|
||||
*
|
||||
* Copyright (c) 2014-2022 Simon Fraser University
|
||||
* Copyright (c) 2000-2022 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class DatetimeToInt
|
||||
*
|
||||
* @brief Cast timestamp/int to Carbon datetime
|
||||
*/
|
||||
|
||||
namespace PKP\job\casts;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
|
||||
|
||||
class DatetimeToInt implements CastsAttributes
|
||||
{
|
||||
/**
|
||||
* Cast the given value.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Model $model
|
||||
* @param string $key
|
||||
* @param array $attributes
|
||||
*
|
||||
* @return \Carbon\Carbon
|
||||
*/
|
||||
public function get($model, $key, $value, $attributes)
|
||||
{
|
||||
return Carbon::parse($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the given value for storage.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Model $model
|
||||
* @param string $key
|
||||
* @param string $value
|
||||
* @param array $attributes
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function set($model, $key, $value, $attributes)
|
||||
{
|
||||
if ($value instanceof Carbon) {
|
||||
return $value->timestamp;
|
||||
}
|
||||
|
||||
return Carbon::parse($value)->timestamp;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* @file classes/job/exceptions/JobException.php
|
||||
*
|
||||
* Copyright (c) 2014-2022 Simon Fraser University
|
||||
* Copyright (c) 2000-2022 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class JobException
|
||||
*
|
||||
*/
|
||||
|
||||
namespace PKP\job\exceptions;
|
||||
|
||||
use Exception;
|
||||
|
||||
class JobException extends Exception
|
||||
{
|
||||
public const INVALID_PAYLOAD = 'invalid.job.payload';
|
||||
|
||||
/**
|
||||
* Customize the class getMessage()
|
||||
*/
|
||||
public function __toString(): string
|
||||
{
|
||||
return self::class .
|
||||
": [{$this->getCode()}] in " .
|
||||
"{$this->getFile()} ({$this->getLine()}): " .
|
||||
"{$this->getMessage()}\n";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* @file classes/job/models/FailedJob.php
|
||||
*
|
||||
* Copyright (c) 2014-2022 Simon Fraser University
|
||||
* Copyright (c) 2000-2022 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class FailedJob
|
||||
*
|
||||
* @brief Laravel Eloquent model for Failed Jobs table
|
||||
*/
|
||||
|
||||
namespace PKP\job\models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use PKP\job\traits\Attributes;
|
||||
|
||||
class FailedJob extends Model
|
||||
{
|
||||
use Attributes;
|
||||
|
||||
/**
|
||||
* Model's database table
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $table = 'failed_jobs';
|
||||
|
||||
/**
|
||||
* Model's primary key
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $primaryKey = 'id';
|
||||
|
||||
/**
|
||||
* Model's timestamp fields
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public $timestamps = false;
|
||||
|
||||
/**
|
||||
* The attributes that are not mass assignable.
|
||||
*
|
||||
* @var string[]|bool
|
||||
*/
|
||||
protected $guarded = [];
|
||||
|
||||
/**
|
||||
* Casting attributes to their native types
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
protected $casts = [
|
||||
'connection' => 'string',
|
||||
'payload' => 'array',
|
||||
'queue' => 'string',
|
||||
'exception' => 'string',
|
||||
'failed_at' => 'datetime',
|
||||
];
|
||||
|
||||
/**
|
||||
* Add a local scope to handle jobs associated in a queue
|
||||
*/
|
||||
public function scopeQueuedAt(Builder $query, string $queue): Builder
|
||||
{
|
||||
return $query->where('queue', $queue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the core exception message without the full exception trace
|
||||
*/
|
||||
public function exceptionMessage(): string
|
||||
{
|
||||
if (isValidJson($this->exception)) {
|
||||
$exception = json_decode($this->exception);
|
||||
return $exception->message . ' in ' . $exception->file . ' at ' . $exception->line;
|
||||
}
|
||||
|
||||
return preg_replace('/\s+/', ' ', trim(explode('Stack trace', $this->exception)[0]));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,240 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* @file classes/job/models/Job.php
|
||||
*
|
||||
* Copyright (c) 2014-2022 Simon Fraser University
|
||||
* Copyright (c) 2000-2022 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class Job
|
||||
*
|
||||
* @brief Laravel Eloquent model for Jobs table
|
||||
*/
|
||||
|
||||
namespace PKP\job\models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\InteractsWithTime;
|
||||
use PKP\config\Config;
|
||||
use PKP\job\casts\DatetimeToInt;
|
||||
use PKP\job\traits\Attributes;
|
||||
|
||||
class Job extends Model
|
||||
{
|
||||
use Attributes;
|
||||
use InteractsWithTime;
|
||||
|
||||
protected const DEFAULT_MAX_ATTEMPTS = 3;
|
||||
|
||||
public const TESTING_QUEUE = 'queuedTestJob';
|
||||
|
||||
/**
|
||||
* Default queue
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $defaultQueue;
|
||||
|
||||
/**
|
||||
* Max Attempts
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $maxAttempts;
|
||||
|
||||
/**
|
||||
* Model's database table
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $table = 'jobs';
|
||||
|
||||
/**
|
||||
* Model's primary key
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $primaryKey = 'id';
|
||||
|
||||
/**
|
||||
* Model's timestamp fields
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public $timestamps = false;
|
||||
|
||||
/**
|
||||
* The attributes that are not mass assignable.
|
||||
*
|
||||
* @var string[]|bool
|
||||
*/
|
||||
protected $guarded = [];
|
||||
|
||||
/**
|
||||
* Casting attributes to their native types
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
protected $casts = [
|
||||
'queue' => 'string',
|
||||
'payload' => 'array',
|
||||
'attempts' => 'int',
|
||||
'reserved_at' => DatetimeToInt::class,
|
||||
'available_at' => DatetimeToInt::class,
|
||||
'created_at' => DatetimeToInt::class,
|
||||
];
|
||||
|
||||
/**
|
||||
* Instantiate the Job model
|
||||
*/
|
||||
public function __construct(array $attributes = [])
|
||||
{
|
||||
parent::__construct($attributes);
|
||||
|
||||
$this->setDefaultQueue(Config::getVar('queues', 'default_queue', 'queue'));
|
||||
$this->setMaxAttempts(self::DEFAULT_MAX_ATTEMPTS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the default queue
|
||||
*/
|
||||
public function setDefaultQueue(?string $value): self
|
||||
{
|
||||
$this->defaultQueue = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Queue name, in case of nullable value, will be the default one
|
||||
*/
|
||||
public function getQueue(?string $queue): string
|
||||
{
|
||||
return $queue ?: $this->defaultQueue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Job's max attempts
|
||||
*/
|
||||
public function setMaxAttempts(int $maxAttempts): self
|
||||
{
|
||||
$this->maxAttempts = $maxAttempts;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Job's max attempts
|
||||
*/
|
||||
public function getMaxAttempts(): int
|
||||
{
|
||||
return $this->maxAttempts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a local scope for not exceeded attempts
|
||||
*/
|
||||
public function scopeNotExceededAttempts(Builder $query): Builder
|
||||
{
|
||||
return $query->where('attempts', '<', $this->getMaxAttempts());
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a local scope to handle jobs associated in a queue
|
||||
*/
|
||||
public function scopeQueuedAt(
|
||||
Builder $query,
|
||||
?string $queue = null
|
||||
): Builder {
|
||||
return $query->where('queue', $this->getQueue($queue));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a local scope to get jobs with queue must defined
|
||||
*/
|
||||
public function scopeNonEmptyQueue(Builder $query): Builder
|
||||
{
|
||||
return $query->whereNotNull('queue');
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a local scope to filter jobs by not given queue
|
||||
*/
|
||||
public function scopeNotQueue(Builder $query, string $queue): Builder
|
||||
{
|
||||
return $query->where('queue', '!=', $queue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a local scope to filter jobs by given queue
|
||||
*/
|
||||
public function scopeOnQueue(Builder $query, string $queue): Builder
|
||||
{
|
||||
return $query->where('queue', '=', $queue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a local scope to filter jobs by non reserved
|
||||
*/
|
||||
public function scopeNonReserved(Builder $query): Builder
|
||||
{
|
||||
return $query->whereNull('reserved_at');
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve available jobs
|
||||
*/
|
||||
public function scopeIsAvailable(Builder $query): Builder
|
||||
{
|
||||
return $query->whereNull('reserved_at')
|
||||
->where('available_at', '<=', $this->currentTime());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get queue's size
|
||||
*/
|
||||
public function size(?string $queue = null): int
|
||||
{
|
||||
return $this->queuedAt($this->getQueue($queue))
|
||||
->count();
|
||||
}
|
||||
|
||||
/**
|
||||
* Increment the Job attempts
|
||||
*/
|
||||
public function incrementAttempts(): void
|
||||
{
|
||||
$this->increment('attempts');
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark a job as reserved to avoid being run by another process
|
||||
*/
|
||||
public function markJobAsReserved(): void
|
||||
{
|
||||
$this->update([
|
||||
'reserved_at' => $this->currentTime(),
|
||||
'attempts' => $this->attempts++,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the reserved_at attribute
|
||||
*/
|
||||
public function setReservedAtAttribute(int $value): self
|
||||
{
|
||||
if (!$value) {
|
||||
$this->attributes['reserved_at'] = null;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
$this->attributes['reserved_at'] = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* @file classes/job/repositories/BaseRepository.php
|
||||
*
|
||||
* Copyright (c) 2014-2022 Simon Fraser University
|
||||
* Copyright (c) 2000-2022 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class BaseRepository
|
||||
*
|
||||
* @brief Abstract class BaseRepository
|
||||
*/
|
||||
|
||||
namespace PKP\job\repositories;
|
||||
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
|
||||
abstract class BaseRepository
|
||||
{
|
||||
protected Model $model;
|
||||
protected int $perPage = 50;
|
||||
protected ?string $outputFormat;
|
||||
|
||||
public const OUTPUT_CLI = 'cli';
|
||||
public const OUTPUT_HTTP = 'http';
|
||||
|
||||
public function newQuery(): Builder
|
||||
{
|
||||
return $this->model->newQuery();
|
||||
}
|
||||
|
||||
public function all(array $columns = ['*']): Collection
|
||||
{
|
||||
return $this->model->all($columns);
|
||||
}
|
||||
|
||||
public function get(int $modelId): ?Model
|
||||
{
|
||||
return $this->model->find($modelId);
|
||||
}
|
||||
|
||||
public function add(array $attributes = []): ?Model
|
||||
{
|
||||
return $this->model->create($attributes);
|
||||
}
|
||||
|
||||
public function edit(int $modelId, array $data): bool
|
||||
{
|
||||
return $this->model->find($modelId)->update($data);
|
||||
}
|
||||
|
||||
public function delete(int $modelId): bool
|
||||
{
|
||||
return $this->model->find($modelId)->delete();
|
||||
}
|
||||
|
||||
public function total(): int
|
||||
{
|
||||
return $this->model->count();
|
||||
}
|
||||
|
||||
public function setOutputFormat(string $format): self
|
||||
{
|
||||
$this->outputFormat = $format;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setPage(int $page): self
|
||||
{
|
||||
LengthAwarePaginator::currentPageResolver(fn () => $page);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function perPage(int $perPage): self
|
||||
{
|
||||
$this->perPage = $perPage;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function deleteJobs(string $queue = null, array $ids = []): int
|
||||
{
|
||||
$query = $this->model->newQuery();
|
||||
|
||||
if ($queue) {
|
||||
$query = $query->queuedAt($queue);
|
||||
}
|
||||
|
||||
if (!empty($ids)) {
|
||||
$query = $query->whereIn('id', $ids);
|
||||
}
|
||||
|
||||
return $query->delete();
|
||||
}
|
||||
|
||||
/**
|
||||
* Show jobs
|
||||
*/
|
||||
abstract public function showJobs(): LengthAwarePaginator;
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* @file classes/job/repositories/Job.php
|
||||
*
|
||||
* Copyright (c) 2014-2022 Simon Fraser University
|
||||
* Copyright (c) 2000-2022 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class FailedJob
|
||||
*
|
||||
* @brief Job Repository
|
||||
*/
|
||||
|
||||
namespace PKP\job\repositories;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use PKP\facades\Repo;
|
||||
use PKP\job\models\FailedJob as PKPFailedJobModel;
|
||||
use PKP\job\resources\CLIFailedJobResource;
|
||||
use PKP\job\resources\HttpFailedJobResource;
|
||||
|
||||
class FailedJob extends BaseRepository
|
||||
{
|
||||
public function __construct(PKPFailedJobModel $model)
|
||||
{
|
||||
$this->model = $model;
|
||||
}
|
||||
|
||||
public function showJobs(): LengthAwarePaginator
|
||||
{
|
||||
$currentPage = LengthAwarePaginator::resolveCurrentPage();
|
||||
$sanitizedPage = $currentPage - 1;
|
||||
$offsetRows = $this->perPage * $sanitizedPage;
|
||||
|
||||
$total = $this->model->count();
|
||||
|
||||
$data = $this->model
|
||||
->skip($offsetRows)
|
||||
->take($this->perPage)
|
||||
->get();
|
||||
|
||||
return new LengthAwarePaginator(
|
||||
$this->getOutput($data),
|
||||
$total,
|
||||
$this->perPage
|
||||
);
|
||||
}
|
||||
|
||||
public function getRedispatchableJobsInQueue(string $queue = null, array $columns = ['*']): collection
|
||||
{
|
||||
$failedJobs = $this->newQuery()->select($columns);
|
||||
|
||||
if ($queue) {
|
||||
$failedJobs = $failedJobs->queuedAt($queue);
|
||||
}
|
||||
|
||||
return $failedJobs->where(
|
||||
fn ($query) => $query
|
||||
->whereNotNull('payload')
|
||||
->whereRaw("payload <> ''")
|
||||
)->get();
|
||||
}
|
||||
|
||||
public function redispatchToQueue(string $queue = null, array $failedIds = []): int
|
||||
{
|
||||
$failedJobs = $this->newQuery();
|
||||
|
||||
if ($queue) {
|
||||
$failedJobs = $failedJobs->queuedAt($queue);
|
||||
}
|
||||
|
||||
if (!empty($failedIds)) {
|
||||
$failedJobs = $failedJobs->whereIn('id', $failedIds);
|
||||
}
|
||||
|
||||
$failedJobs = $failedJobs->get();
|
||||
|
||||
DB::beginTransaction();
|
||||
|
||||
$failedJobs->each(fn ($failedJob) => Repo::job()->add([
|
||||
'queue' => $failedJob->queue,
|
||||
'payload' => $failedJob->payload,
|
||||
'attempts' => 0,
|
||||
'available_at' => Carbon::now()->timestamp,
|
||||
'created_at' => Carbon::now()->timestamp,
|
||||
]));
|
||||
|
||||
DB::commit();
|
||||
|
||||
return $failedJobs->toQuery()->delete();
|
||||
}
|
||||
|
||||
protected function getOutput(Collection $data)
|
||||
{
|
||||
if ($this->outputFormat === self::OUTPUT_CLI) {
|
||||
return CLIFailedJobResource::collection($data);
|
||||
}
|
||||
|
||||
return HttpFailedJobResource::collection($data);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* @file classes/job/repositories/Job.php
|
||||
*
|
||||
* Copyright (c) 2014-2022 Simon Fraser University
|
||||
* Copyright (c) 2000-2022 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class Job
|
||||
*
|
||||
* @brief Job Repository
|
||||
*/
|
||||
|
||||
namespace PKP\job\repositories;
|
||||
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
use Illuminate\Support\Collection;
|
||||
use PKP\job\models\Job as PKPJobModel;
|
||||
use PKP\job\resources\CLIJobResource;
|
||||
use PKP\job\resources\HttpJobResource;
|
||||
|
||||
class Job extends BaseRepository
|
||||
{
|
||||
public function __construct(PKPJobModel $model)
|
||||
{
|
||||
$this->model = $model;
|
||||
}
|
||||
|
||||
public function total(): int
|
||||
{
|
||||
return $this->model
|
||||
->nonEmptyQueue()
|
||||
->nonReserved()
|
||||
->count();
|
||||
}
|
||||
|
||||
public function showJobs(): LengthAwarePaginator
|
||||
{
|
||||
$currentPage = LengthAwarePaginator::resolveCurrentPage();
|
||||
$sanitizedPage = $currentPage - 1;
|
||||
$offsetRows = $this->perPage * $sanitizedPage;
|
||||
|
||||
$query = $this->model
|
||||
->nonEmptyQueue()
|
||||
->nonReserved();
|
||||
|
||||
$total = $query->count();
|
||||
|
||||
$data = $query
|
||||
->skip($offsetRows)
|
||||
->take($this->perPage)
|
||||
->get();
|
||||
|
||||
return new LengthAwarePaginator(
|
||||
$this->getOutput($data),
|
||||
$total,
|
||||
$this->perPage
|
||||
);
|
||||
}
|
||||
|
||||
protected function getOutput(Collection $data)
|
||||
{
|
||||
if ($this->outputFormat == self::OUTPUT_CLI) {
|
||||
return CLIJobResource::collection($data);
|
||||
}
|
||||
|
||||
return HttpJobResource::collection($data);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* @file classes/job/resources/CLIFailedJobResource.php
|
||||
*
|
||||
* Copyright (c) 2014-2022 Simon Fraser University
|
||||
* Copyright (c) 2000-2022 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class CLIFailedJobResource
|
||||
*
|
||||
* @brief Mapping class for CLI output values
|
||||
*/
|
||||
|
||||
namespace PKP\job\resources;
|
||||
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
use PKP\job\traits\JobResource;
|
||||
|
||||
class CLIFailedJobResource extends JsonResource
|
||||
{
|
||||
use JobResource;
|
||||
|
||||
/**
|
||||
* Transform the resource into an array.
|
||||
*/
|
||||
public function toArray($request): array
|
||||
{
|
||||
return [
|
||||
'id' => $this->getResource()->id,
|
||||
'queue' => $this->getResource()->queue,
|
||||
'displayName' => $this->getJobName(),
|
||||
'connection' => $this->getResource()->connection,
|
||||
'failed_at' => $this->getFailedAt(),
|
||||
'exception' => chunk_split($this->getResource()->exceptionMessage(), 50),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* @file classes/job/resources/CLIJobResource.php
|
||||
*
|
||||
* Copyright (c) 2014-2022 Simon Fraser University
|
||||
* Copyright (c) 2000-2022 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class CLIJobResource
|
||||
*
|
||||
* @brief Mapping class for CLI output values
|
||||
*/
|
||||
|
||||
namespace PKP\job\resources;
|
||||
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
use PKP\job\traits\JobResource;
|
||||
|
||||
class CLIJobResource extends JsonResource
|
||||
{
|
||||
use JobResource;
|
||||
|
||||
/**
|
||||
* Transform the resource into an array.
|
||||
*/
|
||||
public function toArray($request): array
|
||||
{
|
||||
return [
|
||||
'id' => $this->getResource()->id,
|
||||
'queue' => $this->getResource()->queue,
|
||||
'displayName' => $this->getJobName(),
|
||||
'attempts' => $this->getResource()->attempts,
|
||||
'reserved_at' => $this->getReservedAt(),
|
||||
'available_at' => $this->getAvailableAt(),
|
||||
'created_at' => $this->getCreatedAt(),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* @file classes/job/resources/HttpFailedJobResource.php
|
||||
*
|
||||
* Copyright (c) 2014-2022 Simon Fraser University
|
||||
* Copyright (c) 2000-2022 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class HttpFailedJobResource
|
||||
*
|
||||
* @brief Mapping class for HTTP Output values
|
||||
*/
|
||||
|
||||
namespace PKP\job\resources;
|
||||
|
||||
use APP\core\Application;
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
use PKP\job\traits\JobResource;
|
||||
|
||||
class HttpFailedJobResource extends JsonResource
|
||||
{
|
||||
use JobResource;
|
||||
|
||||
/**
|
||||
* Transform the resource into an array.
|
||||
*/
|
||||
public function toArray($request): array
|
||||
{
|
||||
return [
|
||||
'id' => $this->getResource()->id,
|
||||
'displayName' => $this->getJobName(),
|
||||
'queue' => $this->getResource()->queue,
|
||||
'connection' => $this->getResource()->connection,
|
||||
'failed_at' => $this->getFailedAt(),
|
||||
'payload' => $this->getResource()->payload,
|
||||
'exception' => $this->getResource()->exception,
|
||||
'_hrefs' => [
|
||||
'_details' => $request->getDispatcher()->url($request, Application::ROUTE_PAGE, 'index', 'admin', 'failedJobDetails', $this->getResource()->id),
|
||||
'_redispatch' => $request->getDispatcher()->url($request, Application::ROUTE_API, 'index', 'jobs/redispatch/' . $this->getResource()->id),
|
||||
'_delete' => $request->getDispatcher()->url($request, Application::ROUTE_API, 'index', 'jobs/failed/delete/' . $this->getResource()->id),
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* @file classes/job/resources/HttpJobResource.php
|
||||
*
|
||||
* Copyright (c) 2014-2022 Simon Fraser University
|
||||
* Copyright (c) 2000-2022 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class HttpJobResource
|
||||
*
|
||||
* @brief Mapping class for HTTP Output values
|
||||
*/
|
||||
|
||||
namespace PKP\job\resources;
|
||||
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
use PKP\job\traits\JobResource;
|
||||
|
||||
class HttpJobResource extends JsonResource
|
||||
{
|
||||
use JobResource;
|
||||
|
||||
/**
|
||||
* Transform the resource into an array.
|
||||
*/
|
||||
public function toArray($request): array
|
||||
{
|
||||
return [
|
||||
'id' => $this->getResource()->id,
|
||||
'queue' => $this->getResource()->queue,
|
||||
'displayName' => $this->getJobName(),
|
||||
'attempts' => $this->getResource()->attempts,
|
||||
'created_at' => __('admin.jobs.createdAt', ['createdAt' => $this->getCreatedAt()]),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* @file classes/job/traits/Attributes.php
|
||||
*
|
||||
* Copyright (c) 2014-2022 Simon Fraser University
|
||||
* Copyright (c) 2000-2022 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class Attributes
|
||||
*
|
||||
* @brief Attributes trait for Jobs model
|
||||
*/
|
||||
|
||||
namespace PKP\job\traits;
|
||||
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Support\Facades\Date;
|
||||
|
||||
/**
|
||||
* Those attributes become from payload array
|
||||
*/
|
||||
trait Attributes
|
||||
{
|
||||
/**
|
||||
* Return the job's display name value
|
||||
*
|
||||
*/
|
||||
public function getDisplayNameAttribute(): ?string
|
||||
{
|
||||
if (!$this->payload['displayName']) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $this->payload['displayName'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the job's max tries value
|
||||
*
|
||||
*/
|
||||
public function getMaxTriesAttribute(): ?string
|
||||
{
|
||||
if (!$this->payload['maxTries']) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $this->payload['maxTries'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the job's backoff value
|
||||
*
|
||||
*/
|
||||
public function getBackoffAttribute(): ?string
|
||||
{
|
||||
if (!$this->payload['backoff']) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $this->payload['backoff'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the job's timeout value
|
||||
*
|
||||
*/
|
||||
public function getTimeoutAttribute(): ?string
|
||||
{
|
||||
if (!$this->payload['timeout']) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $this->payload['timeout'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the job's timeout at value
|
||||
*
|
||||
*/
|
||||
public function getTimeoutAtAttribute(): ?string
|
||||
{
|
||||
if (!$this->payload['timeout_at']) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$obj = new Carbon($this->payload['timeout_at']);
|
||||
|
||||
return Date::instance($obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the job's command name value
|
||||
*
|
||||
*/
|
||||
public function getCommandNameAttribute(): ?string
|
||||
{
|
||||
if (!$this->payload['data']['commandName']) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $this->payload['data']['commandName'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the job's command value
|
||||
*
|
||||
*/
|
||||
public function getCommandAttribute(): array
|
||||
{
|
||||
if (!$this->payload['data']['command']) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return (array) unserialize($this->payload['data']['command']);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* @file classes/job/traits/JobResource.php
|
||||
*
|
||||
* Copyright (c) 2014-2022 Simon Fraser University
|
||||
* Copyright (c) 2000-2022 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class JobResource
|
||||
*
|
||||
* @brief JobResource trait
|
||||
*/
|
||||
|
||||
namespace PKP\job\traits;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use PKP\core\PKPRequest;
|
||||
|
||||
trait JobResource
|
||||
{
|
||||
protected string $dateFormat = 'Y-m-d G:i:s T Z';
|
||||
|
||||
public static function toResourceArray(Model $modelInstance): array
|
||||
{
|
||||
return (new static($modelInstance))->toArray(app()->get(PKPRequest::class));
|
||||
}
|
||||
|
||||
public function getResource(): mixed
|
||||
{
|
||||
return $this->resource;
|
||||
}
|
||||
|
||||
public function getCreatedAt(): string
|
||||
{
|
||||
if (!isset($this->getResource()->created_at)) {
|
||||
return '-';
|
||||
}
|
||||
|
||||
return $this->formatDate($this->getResource()->created_at);
|
||||
}
|
||||
|
||||
public function getReservedAt(): string
|
||||
{
|
||||
if (!isset($this->getResource()->reserved_at)) {
|
||||
return '-';
|
||||
}
|
||||
|
||||
return $this->formatDate($this->getResource()->reserved_at);
|
||||
}
|
||||
|
||||
public function getAvailableAt(): string
|
||||
{
|
||||
if (!isset($this->getResource()->available_at)) {
|
||||
return '-';
|
||||
}
|
||||
|
||||
return $this->formatDate($this->getResource()->available_at);
|
||||
}
|
||||
|
||||
public function getFailedAt(): string
|
||||
{
|
||||
if (!isset($this->getResource()->failed_at)) {
|
||||
return '-';
|
||||
}
|
||||
|
||||
return $this->formatDate($this->getResource()->failed_at);
|
||||
}
|
||||
|
||||
public function getJobName(): ?string
|
||||
{
|
||||
if (!isset($this->getResource()->payload)) {
|
||||
return '-';
|
||||
}
|
||||
|
||||
return $this->getResource()->payload['displayName'] ?? '-';
|
||||
}
|
||||
|
||||
protected function formatDate(Carbon $date): string
|
||||
{
|
||||
return $date->format($this->dateFormat);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user