Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature review for various features. #290

Closed
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
70 changes: 70 additions & 0 deletions src/Queue/Admin/DataExtension.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<?php

namespace App\Queue\Admin;

use SilverStripe\Forms\FieldList;
use SilverStripe\Forms\LiteralField;
use SilverStripe\Forms\TextareaField;
use SilverStripe\ORM\DataExtension as BaseDataExtension;
use Symbiote\QueuedJobs\DataObjects\QueuedJobDescriptor;

/**
* Class DataExtension
*
* @property QueuedJobDescriptor|$this $owner
* @package App\Queue\Admin
*/
class DataExtension extends BaseDataExtension
{

/**
* @param FieldList $fields
*/
public function updateCMSFields(FieldList $fields): void
{
$owner = $this->owner;

$fields->addFieldsToTab('Root.JobData', [
$jobDataPreview = TextareaField::create('SavedJobDataPreview', 'Job Data'),
]);

if (strlen($owner->getMessagesRaw()) > 0) {
$fields->addFieldToTab(
'Root.MessagesRaw',
$messagesRaw = LiteralField::create('MessagesRaw', $owner->getMessagesRaw())
);
}

$jobDataPreview->setReadonly(true);
}

/**
* @return string|null
*/
public function getSavedJobDataPreview(): ?string
{
return $this->owner->SavedJobData;
}

/**
* @return string|null
*/
public function getMessagesRaw(): ?string
{
return $this->owner->SavedJobMessages;
}

/**
* @return string
*/
public function getImplementationSummary(): string
{
$segments = explode('\\', $this->owner->Implementation);

while (count($segments) > 2) {
array_shift($segments);
}

return implode('\\', $segments);
}
}
222 changes: 222 additions & 0 deletions src/Queue/Admin/Extension.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,222 @@
<?php

namespace App\Queue\Admin;

use SilverStripe\Core\Extension as BaseExtension;
use SilverStripe\Forms\DropdownField;
use SilverStripe\Forms\Form;
use SilverStripe\Forms\GridField\GridField;
use SilverStripe\Forms\GridField\GridFieldConfig;
use SilverStripe\Forms\GridField\GridFieldDataColumns;
use SilverStripe\Forms\GridField\GridFieldFilterHeader;
use SilverStripe\Forms\GridField\GridFieldPaginator;
use SilverStripe\ORM\DataList;
use SilverStripe\ORM\FieldType\DBDatetime;
use Symbiote\QueuedJobs\Controllers\QueuedJobsAdmin;
use Symbiote\QueuedJobs\DataObjects\QueuedJobDescriptor;
use Terraformers\RichFilterHeader\Form\GridField\RichFilterHeader;

/**
* Class Extension
*
* @property QueuedJobsAdmin|$this $owner
* @package App\Queue\Admin
*/
class Extension extends BaseExtension
{

private const SCHEDULED_FILTER_FUTURE = 'future';
private const SCHEDULED_FILTER_PAST = 'past';

/**
* @param Form $form
*/
public function updateEditForm(Form $form): void
{
$fields = $form->Fields();

// there are multiple fields that need to be updated
$fieldNames = [
'QueuedJobDescriptor',
$this->encodeClassName(QueuedJobDescriptor::class),
];

foreach ($fieldNames as $fieldName) {
/** @var GridField $gridField */
$gridField = $fields->fieldByName($fieldName);

if (!$gridField) {
continue;
}

$config = $gridField->getConfig();

// apply custom filters
$this->customiseFilters($config);
}
}

/**
* Customise queued jobs filters UI
*
* @param GridFieldConfig $config
*/
private function customiseFilters(GridFieldConfig $config): void
{
/** @var GridFieldDataColumns $gridFieldColumns */
$gridFieldColumns = $config->getComponentByType(GridFieldDataColumns::class);

$gridFieldColumns->setDisplayFields([
'getImplementationSummary' => 'Type',
'JobTypeString' => 'Queue',
'JobStatus' => 'Status',
'JobTitle' => 'Description',
'Created' => 'Added',
'StartAfter' => 'Scheduled',
'JobFinished' => 'Finished',
]);

$config->removeComponentsByType(GridFieldFilterHeader::class);

$filter = new RichFilterHeader();
$filter
->setFilterConfig([
'getImplementationSummary' => 'Implementation',
'Description' => 'JobTitle',
'Status' => [
'title' => 'JobStatus',
'filter' => 'ExactMatchFilter',
],
'JobTypeString' => [
'title' => 'JobType',
'filter' => 'ExactMatchFilter',
],
'Created' => 'Added',
'StartAfter' => 'Scheduled',
])
->setFilterFields([
'JobType' => $queueType = DropdownField::create(
'',
'',
$this->getQueueTypes()
),
'JobStatus' => $jobStatus = DropdownField::create(
'',
'',
$this->getJobStatuses()
),
'Added' => $added = DropdownField::create(
'',
'',
$this->getAddedDates()
),
'Scheduled' => $scheduled = DropdownField::create(
'',
'',
[
self::SCHEDULED_FILTER_FUTURE => self::SCHEDULED_FILTER_FUTURE,
self::SCHEDULED_FILTER_PAST => self::SCHEDULED_FILTER_PAST,
]
),
])
->setFilterMethods([
'Added' => static function (DataList $list, $name, $value): DataList {
if ($value) {
$added = DBDatetime::now()->modify($value);

return $list->filter(['Created:LessThanOrEqual' => $added->Rfc2822()]);
}

return $list;
},
'Scheduled' => static function (DataList $list, $name, $value): DataList {
if ($value === static::SCHEDULED_FILTER_FUTURE) {
return $list->filter([
'StartAfter:GreaterThan' => DBDatetime::now()->Rfc2822(),
]);
}

if ($value === static::SCHEDULED_FILTER_PAST) {
return $list->filter([
'StartAfter:LessThanOrEqual' => DBDatetime::now()->Rfc2822(),
]);
}

return $list;
},
]);

foreach ([$jobStatus, $queueType, $added, $scheduled] as $dropDownField) {
/** @var DropdownField $dropDownField */
$dropDownField->setEmptyString('-- select --');
}

$config->addComponent($filter, GridFieldPaginator::class);
}

/**
* Queue types options for drop down field
*
* @return array
*/
private function getQueueTypes(): array
{
/** @var QueuedJobDescriptor $job */
$job = QueuedJobDescriptor::singleton();
$map = $job->getJobTypeValues();
$values = array_values($map);
$keys = [];

foreach (array_keys($map) as $key) {
$keys[] = (int) $key;
}

return array_combine($keys, $values);
}

/**
* All possible job statuses (this list is not exposed by the module)
* intended to be used in a drop down field
*
* @return array
*/
private function getJobStatuses(): array
{
/** @var QueuedJobDescriptor $job */
$job = QueuedJobDescriptor::singleton();
$statuses = $job->getJobStatusValues();

sort($statuses, SORT_STRING);

$statuses = array_combine($statuses, $statuses);

return $statuses;
}

/**
* Encode class name to match the matching CMS field name
*
* @param string $className
* @return string
*/
private function encodeClassName(string $className): string
{
return str_replace('\\', '-', $className);
}

/**
* Date options for added dates drop down field
*
* @return array
*/
private function getAddedDates(): array
{
return [
'-1 day' => '1 day or older',
'-3 day' => '3 days or older',
'-7 day' => '7 days or older',
'-14 day' => '14 days or older',
'-1 month' => '1 month or older',
];
}
}
63 changes: 63 additions & 0 deletions src/Queue/Cleanup/Task.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<?php

namespace App\Queue\Cleanup;

use SilverStripe\Control\HTTPRequest;
use SilverStripe\Dev\BuildTask;
use SilverStripe\ORM\DB;
use SilverStripe\ORM\FieldType\DBDatetime;
use Symbiote\QueuedJobs\DataObjects\QueuedJobDescriptor;
use Symbiote\QueuedJobs\Services\QueuedJob;
use Symbiote\QueuedJobs\Services\QueuedJobService;

/**
* Class Task
*
* Delete all expired completed jobs
*
* @package App\Queue\Cleanup
*/
class Task extends BuildTask
{

private const EXPIRY_HOURS = 24;
private const EXPIRY_LIMIT = 10000;

/**
* @var string
*/
private static $segment = 'queued-jobs-cleanup';

/**
* @var string
*/
protected $description = 'Delete job descriptors that are older than the configured expiry';

/**
* @param HTTPRequest $request
*/
public function run($request): void // phpcs:ignore SlevomatCodingStandard.TypeHints
{
if (QueuedJobService::singleton()->isMaintenanceLockActive()) {
return;
}

$table = QueuedJobDescriptor::config()->get('table_name');

// determine expiry
$expired = DBDatetime::now()->modify(sprintf('-%s hours', self::EXPIRY_HOURS))->Rfc2822();

// Format query
$query = sprintf(
"DELETE FROM `%s` WHERE `JobStatus` = '%s' AND (`JobFinished` <= '%s' OR `JobFinished` IS NULL) LIMIT %d",
$table,
QueuedJob::STATUS_COMPLETE,
$expired,
self::EXPIRY_LIMIT
);

DB::query($query);

echo sprintf('%d job descriptors deleted.', (int) DB::affected_rows());
}
}
Loading