Skip to content

Commit

Permalink
fix bug #28 : replace cache storage with custom adapters #28
Browse files Browse the repository at this point in the history
  • Loading branch information
nicoren-tangkoko committed Mar 17, 2022
1 parent ccf7a2e commit 54fdcde
Show file tree
Hide file tree
Showing 13 changed files with 219 additions and 35 deletions.
38 changes: 11 additions & 27 deletions src/Crontab/Runner.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
use Doctrine\Common\Collections\ArrayCollection;
use Nicoren\CronBundle\Doctrine\JobManagerInterface;
use Nicoren\CronBundle\Model\JobInterface;
use Nicoren\CronBundle\Storage\Adapter\AdapterInterface;
use Nicoren\CronBundle\Storage\Adapter\PoolInterface;
use Symfony\Component\Cache\CacheItem;
use Symfony\Component\Process\Process;
use Symfony\Contracts\Cache\CacheInterface;
Expand All @@ -38,9 +40,9 @@ class Runner implements RunnerInterface

/**
*
* @var CacheInterface
* @var AdapterInterface
*/
protected $cache;
protected $adapter;

/**
*
Expand All @@ -49,13 +51,13 @@ class Runner implements RunnerInterface
public function __construct(
JobManagerInterface $jobManager,
SchedulerInterface $scheduler,
CacheInterface $cache
AdapterInterface $adapter

) {
$this->jobManager = $jobManager;
$this->processes = new ArrayCollection();
$this->scheduler = $scheduler;
$this->cache = $cache;
$this->adapter = $adapter;
}

/**
Expand All @@ -66,7 +68,7 @@ public function __construct(
*/
protected function canRunProcess(JobInterface $job): bool
{
$processes = $this->getCacheItem()->get();
$processes = $this->adapter->get();
//job not already start
if (!isset($processes[$job->getId()])) {
return true;
Expand All @@ -90,20 +92,6 @@ protected function canRunProcess(JobInterface $job): bool
return false;
}

/**
* Return cached running process
*
* @return CacheItem
*/
protected function getCacheItem(): CacheItem
{
/**
* @var CacheItem
*/
$cacheItem = $this->cache->getItem(static::CACHE_KEY);

return $cacheItem;
}

/**
* Return true if job can be runned
Expand All @@ -113,8 +101,7 @@ protected function getCacheItem(): CacheItem
*/
protected function cacheProcess(JobInterface $job, Process $process): void
{
$cacheItem = $this->getCacheItem();
$runningProcesses = $cacheItem->get();
$runningProcesses = $this->adapter->get();
if (!$runningProcesses) {
$runningProcesses = [];
}
Expand All @@ -123,8 +110,7 @@ protected function cacheProcess(JobInterface $job, Process $process): void
$runningProcesses[$job->getId()] = [];
}
$runningProcesses[$job->getId()][] = $process->getPid();
$cacheItem->set($runningProcesses);
$this->cache->save($cacheItem);
$this->adapter->set($runningProcesses);
}

/**
Expand All @@ -135,14 +121,12 @@ protected function cacheProcess(JobInterface $job, Process $process): void
*/
protected function uncacheProcess(JobInterface $job, int $pid): void
{
$cacheItem = $this->getCacheItem();
$runningProcesses = $cacheItem->get();
$runningProcesses = $this->adapter->get();
if (isset($runningProcesses[$job->getId()])) {
if (($key = array_search($pid, $runningProcesses[$job->getId()])) !== false) {
unset($runningProcesses[$job->getId()][$key]);
}
$cacheItem->set($runningProcesses);
$this->cache->save($cacheItem);
$this->adapter->set($runningProcesses);
}
}

Expand Down
32 changes: 32 additions & 0 deletions src/DependencyInjection/Compiler/StorageAdapterCompilerPass.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

/**
* Created on Wed Mar 16 2022
* @author : Nicolas RENAULT <[email protected]>
* @copyright (c) 2022 Tangkoko
**/

namespace Nicoren\CronBundle\DependencyInjection\Compiler;

use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\Alias;

class StorageAdapterCompilerPass implements CompilerPassInterface
{
public function process(ContainerBuilder $container)
{
$pool = $container->getDefinition('nicoren_cron.storage.adapter.pool');

$adapters = [];
foreach ($container->findTaggedServiceIds('nicoren_cron.storage_adapter') as $id => $tags) {
$adapters[$tags[0]["alias"]] = new Reference($id);
if ($container->getParameter('nicoren_cron.storage.adapter_code') == $tags[0]["alias"]) {

$container->setAlias('nicoren_cron.storage.adapter', new Alias($id, false));
}
}
$pool->setArgument(0, $adapters);
}
}
20 changes: 19 additions & 1 deletion src/DependencyInjection/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,25 @@ public function getConfigTreeBuilder()
->end()
->scalarNode('job_class')->isRequired()->defaultValue(Job::class)->end()
->scalarNode('timezone')->isRequired()->defaultValue(\DateTimeZone::UTC)->end()
->scalarNode('model_manager_name')->defaultNull()->end();
->scalarNode('model_manager_name')->defaultNull()->end()
->arrayNode('storage')
->info('Adapter configuration to store running pids')
->addDefaultsIfNotSet()
->children()
->scalarNode('adapter')
->info('Cron storage configuration')
->defaultValue('nicoren_cron.storage.adapter.filesystem')
->end()
->arrayNode('redis')
->info('Cron redis options')
->children()
->scalarNode('type')->isRequired()->end()
->scalarNode('dns')->isRequired()->end()
->end()
->end()
->end()
->end();

$rootNode
->addDefaultsIfNotSet()
->children()
Expand Down
6 changes: 4 additions & 2 deletions src/DependencyInjection/NicorenCronExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
use Symfony\Component\DependencyInjection\Loader;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\HttpKernel\KernelInterface;

/**
* This is the class that loads and manages your bundle configuration
Expand All @@ -27,7 +28,6 @@
*/
class NicorenCronExtension extends Extension
{

/**
* @var array
*/
Expand Down Expand Up @@ -71,9 +71,11 @@ public function load(array $configs, ContainerBuilder $container)
'db_driver' => 'nicoren_cron.storage',
'model_manager_name' => 'nicoren_cron.model_manager_name',
'job_class' => 'nicoren_cron.model.job.class',
'timezone' => 'nicoren_cron.timezone'
'timezone' => 'nicoren_cron.timezone',
],
]);

$container->setParameter('nicoren_cron.storage.adapter_code', $config['storage']['adapter']);
}

protected function remapParameters(array $config, ContainerBuilder $container, array $map)
Expand Down
4 changes: 3 additions & 1 deletion src/NicorenCronBundle.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

use Doctrine\Bundle\DoctrineBundle\DependencyInjection\Compiler\DoctrineOrmMappingsPass;
use Doctrine\Bundle\MongoDBBundle\DependencyInjection\Compiler\DoctrineMongoDBMappingsPass;
use Nicoren\CronBundle\DependencyInjection\Compiler\StorageAdapterCompilerPass;
use Nicoren\CronBundle\DependencyInjection\Compiler\ValidationPass;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\HttpKernel\Bundle\Bundle;
Expand All @@ -19,7 +20,8 @@ class NicorenCronBundle extends Bundle
public function build(ContainerBuilder $container)
{
parent::build($container);
$container->addCompilerPass(new ValidationPass());
$container->addCompilerPass(new ValidationPass())
->addCompilerPass(new StorageAdapterCompilerPass());
$this->addRegisterMappingsPass($container);
}

Expand Down
4 changes: 2 additions & 2 deletions src/Resources/config/doctrine-mapping/Job.mongodb.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@
<field field-name="command" name="command" type="string" />
<field field-name="description" name="description" type="string" />
<field field-name="schedule" name="schedule" type="string" />
<field field-name="enabled" name="enabled" type="boolean" />
<field field-name="enabled" name="enabled" type="bool" />
<field field-name="createdAt" name="created_t" type="date" />
<field field-name="maxConcurrent" name="max_concurrent" type="integer" />
<field field-name="maxConcurrent" name="max_concurrent" type="int" />
<indexes>
<index unique="false">
<key name="name" order="desc"/>
Expand Down
2 changes: 1 addition & 1 deletion src/Resources/config/doctrine-mapping/Job.orm.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
<field name="command" column="command" type="string" length="255" />
<field name="description" column="description" type="text" nullable="true" />
<field name="schedule" column="schedule" type="string" length="20" />
<field name="enabled" column="enabled" type="boolean" nullable="false">
<field name="enabled" column="enabled" type="bool" nullable="false">
<options>
<option name="default">false</option>
</options>
Expand Down
5 changes: 4 additions & 1 deletion src/Resources/config/services.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">

<imports>
<import resource="services/*.xml" />
</imports>
<services>
<defaults autowire="true" autoconfigure="true"/>
<!-- JOb Manager service -->
Expand All @@ -19,6 +21,7 @@

<!-- Crontab runner service-->
<service id="nicoren_cron.crontab_runner.default" class="Nicoren\CronBundle\Crontab\Runner">
<argument key="$adapter" type="service" id="nicoren_cron.storage.adapter"></argument>
</service>
<service id="Nicoren\CronBundle\Crontab\RunnerInterface" alias="nicoren_cron.crontab_runner.default" public="false"/>

Expand Down
27 changes: 27 additions & 0 deletions src/Resources/config/services/adapters.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?xml version="1.0" ?>
<!--
Created on Mon Apr 12 2021
@author : Nicolas RENAULT <[email protected]>
@license MIT
-->
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">

<services>
<defaults autowire="true" autoconfigure="true"/>
<!-- Pool Adapter -->
<service id="nicoren_cron.storage.adapter.pool" class="Nicoren\CronBundle\Storage\Adapter\Pool">
<argument type="collection">
</argument>
</service>
<service id="Nicoren\CronBundle\Storage\Adapter\PoolInterface" alias="nicoren_cron.storage.adapter.pool" public="false"/>

<!-- Adapters -->
<service id="nicoren_cron.storage.adapter.filesystem" class="Nicoren\CronBundle\Storage\Adapter\Filesystem">
<argument>%kernel.project_dir%/var/cron/pids</argument>
<tag name="nicoren_cron.storage_adapter" alias="filesystem"/>
</service>
</services>
</container>

17 changes: 17 additions & 0 deletions src/Storage/Adapter/AdapterInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

namespace Nicoren\CronBundle\Storage\Adapter;

/**
* Created on Wed Mar 16 2022
* @author : Nicolas RENAULT <[email protected]>
* @copyright (c) 2022 Tangkoko
**/


interface AdapterInterface
{
public function get(): array;

public function set(array $value): self;
}
46 changes: 46 additions & 0 deletions src/Storage/Adapter/Filesystem.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?php

namespace Nicoren\CronBundle\Storage\Adapter;

use Symfony\Component\Filesystem\Exception\IOExceptionInterface;
use Symfony\Component\Filesystem\Filesystem as FilesystemClient;
use Symfony\Component\Filesystem\Path;
use Symfony\Component\Finder\SplFileInfo;



/**
* Created on Wed Mar 16 2022
* @author : Nicolas RENAULT <[email protected]>
* @copyright (c) 2022 Tangkoko
**/


class Filesystem implements AdapterInterface
{

private string $file;
private FilesystemClient $client;

public function __construct(string $file)
{
$this->file = $file;
$this->client = new FilesystemClient();
}

public function get(): array
{
$ids = [];
if ($this->client->exists($this->file)) {
$fileInfo = new SplFileInfo($this->file, '', '');
$ids = json_decode($fileInfo->getContents(), true);
}
return $ids;
}

public function set(array $value): self
{
$this->client->dumpFile($this->file, json_encode($value));
return $this;
}
}
35 changes: 35 additions & 0 deletions src/Storage/Adapter/Pool.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php

namespace Nicoren\CronBundle\Storage\Adapter;

/**
* Created on Wed Mar 16 2022
* @author : Nicolas RENAULT <[email protected]>
* @copyright (c) 2022 Tangkoko
**/


class Pool implements PoolInterface
{
/**
*
* @var array<AdapterInterface>
*/
private array $adapters = [];

public function __construct(?array $adapters = [])
{
var_dump($this->adapters);
$this->adapters = $adapters;
}

public function getAdapters(): array
{
return $this->adapters;
}

public function getAdapter(string $key): AdapterInterface
{
return $this->adapters[$key];
}
}
18 changes: 18 additions & 0 deletions src/Storage/Adapter/PoolInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

namespace Nicoren\CronBundle\Storage\Adapter;

/**
* Created on Wed Mar 16 2022
* @author : Nicolas RENAULT <[email protected]>
* @copyright (c) 2022 Tangkoko
**/


interface PoolInterface
{

public function getAdapters(): array;

public function getAdapter(string $key): AdapterInterface;
}

0 comments on commit 54fdcde

Please sign in to comment.