Skip to content

Commit

Permalink
added lock to config
Browse files Browse the repository at this point in the history
  • Loading branch information
wachterjohannes committed May 15, 2017
1 parent 3f1f0dd commit 7c037c4
Show file tree
Hide file tree
Showing 12 changed files with 210 additions and 14 deletions.
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,10 @@
],
"require": {
"php": "~5.5 || ~7.0",
"php-task/php-task": "^1.0",
"php-task/php-task": "dev-feature/lock",
"symfony/http-kernel": "^2.6 || ^3.0",
"symfony/dependency-injection": "^2.6 || ^3.0",
"symfony/expression-language": "^2.6 || ^3.0",
"symfony/config": "^2.6 || ^3.0",
"symfony/console": "^2.6 || ^3.0",
"doctrine/orm": "^2.5"
Expand Down
50 changes: 47 additions & 3 deletions src/DependencyInjection/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,19 @@
*/
class Configuration implements ConfigurationInterface
{
/**
* @var string[]
*/
private $lockingStorageAliases = [];

/**
* @param \string[] $lockingStorageAliases
*/
public function __construct(array $lockingStorageAliases)
{
$this->lockingStorageAliases = $lockingStorageAliases;
}

/**
* {@inheritdoc}
*/
Expand All @@ -43,14 +56,45 @@ public function getConfigTreeBuilder()
->arrayNode('run')
->addDefaultsIfNotSet()
->children()
->enumNode('mode')
->values(['off', 'listener'])
->defaultValue('off')
->enumNode('mode')->values(['off', 'listener'])->defaultValue('off')->end()
->end()
->end()
->arrayNode('locking')
->canBeEnabled()
->addDefaultsIfNotSet()
->children()
->enumNode('storage')
->values(array_keys($this->lockingStorageAliases))
->defaultValue('file')
->end()
->arrayNode('storages')
->addDefaultsIfNotSet()
->children()
->arrayNode('file')
->addDefaultsIfNotSet()
->children()
->scalarNode('directory')->defaultValue(sys_get_temp_dir() . '/task')->end()
->end()
->end()
->end()
->end()
->enumNode('mode')->values(['off', 'listener'])->defaultValue('off')->end()
->end()
->end()
->end();

return $treeBuilder;
}

/**
* Returns id for given storage-alias.
*
* @param string $alias
*
* @return string
*/
public function getLockingStorageId($alias)
{
return $this->lockingStorageAliases[$alias];
}
}
58 changes: 57 additions & 1 deletion src/DependencyInjection/TaskExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
namespace Task\TaskBundle\DependencyInjection;

use Symfony\Component\Config\FileLocator;
use Symfony\Component\Config\Loader\LoaderInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Definition;
Expand All @@ -31,20 +32,28 @@ class TaskExtension extends Extension
*/
public function load(array $configs, ContainerBuilder $container)
{
$configuration = new Configuration();
$configuration = $this->getConfiguration($configs, $container);
$config = $this->processConfiguration($configuration, $configs);

$container->setAlias('task.lock.storage', $configuration->getLockingStorageId($config['locking']['storage']));

foreach (array_keys($config['locking']['storages']) as $key) {
$container->setParameter('task.lock.storages.' . $key, $config['locking']['storages'][$key]);
}

$loader = new Loader\XmlFileLoader($container, new FileLocator(__DIR__ . '/../Resources/config'));
$loader->load(sprintf('storage/%s.xml', $config['storage']));
$loader->load('task_event_listener.xml');
$loader->load('scheduler.xml');
$loader->load('command.xml');

$loader->load('locking/services.xml');
if ($config['run']['mode'] === 'listener') {
$loader->load('listener.xml');
}

$this->loadDoctrineAdapter($config['adapters']['doctrine'], $container);
$this->loadLockingComponent($config['locking'], $loader);
}

/**
Expand All @@ -67,4 +76,51 @@ private function loadDoctrineAdapter(array $config, ContainerBuilder $container)
$container->setDefinition('task.adapter.doctrine.execution_listener', $definition);
}
}

/**
* Load services for locking component.
*
* @param array $config
* @param LoaderInterface $loader
*/
private function loadLockingComponent(array $config, LoaderInterface $loader)
{
if (!$config['enabled']) {
return $loader->load('locking/null.xml');
}

$loader->load('locking/services.xml');
}

/**
* Find storage aliases and related ids.
*
* @param ContainerBuilder $container
*
* @return array
*/
private function getLockingStorageAliases(ContainerBuilder $container)
{
$taggedServices = $container->findTaggedServiceIds('task.lock.storage');

$result = [];
foreach ($taggedServices as $id => $tags) {
foreach ($tags as $tag) {
$result[$tag['alias']] = $id;
}
}

return $result;
}

/**
* {@inheritdoc}
*/
public function getConfiguration(array $config, ContainerBuilder $container)
{
$loader = new Loader\XmlFileLoader($container, new FileLocator(__DIR__ . '/../Resources/config'));
$loader->load('locking/storages.xml');

return new Configuration($this->getLockingStorageAliases($container));
}
}
6 changes: 5 additions & 1 deletion src/Entity/TaskExecutionRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,10 @@ public function findNextScheduled(\DateTime $dateTime = null)
->setMaxResults(1)
->getQuery();

return $query->getResult();
try {
return $query->getSingleResult();
} catch (NoResultException $exception) {
return null;
}
}
}
53 changes: 53 additions & 0 deletions src/Locking/NullLock.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?php

/*
* This file is part of php-task library.
*
* (c) php-task
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/

namespace Task\TaskBundle\Locking;

use Task\Execution\TaskExecutionInterface;
use Task\Lock\LockInterface;

/**
* Implements LockInterface which does nothing.
*/
class NullLock implements LockInterface
{
/**
* {@inheritdoc}
*/
public function acquire(TaskExecutionInterface $execution)
{
return true;
}

/**
* {@inheritdoc}
*/
public function refresh(TaskExecutionInterface $execution)
{
return true;
}

/**
* {@inheritdoc}
*/
public function release(TaskExecutionInterface $execution)
{
return true;
}

/**
* {@inheritdoc}
*/
public function isAcquired(TaskExecutionInterface $execution)
{
return false;
}
}
8 changes: 8 additions & 0 deletions src/Resources/config/locking/null.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" ?>
<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>
<service id="task.lock" class="Task\TaskBundle\Locking\NullLock"/>
</services>
</container>
13 changes: 13 additions & 0 deletions src/Resources/config/locking/services.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?xml version="1.0" ?>
<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>
<service id="task.lock.strategy" class="Task\Lock\Strategy\HandlerClassStrategy"/>

<service id="task.lock" class="Task\Lock\Lock">
<argument type="service" id="task.lock.strategy"/>
<argument type="service" id="task.lock.storage"/>
</service>
</services>
</container>
12 changes: 12 additions & 0 deletions src/Resources/config/locking/storages.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?xml version="1.0" ?>
<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>
<service id="task.lock.storage.file" class="Task\Lock\Storage\FileLock">
<argument type="expression">parameter('task.lock.storages.file')['directory']</argument>

<tag name="task.lock.storage" alias="file"/>
</service>
</services>
</container>
1 change: 1 addition & 0 deletions src/Resources/config/scheduler.xml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
<service id="task.runner" class="Task\Runner\TaskRunner">
<argument type="service" id="task.storage.task_execution"/>
<argument type="service" id="task.handler.factory"/>
<argument type="service" id="task.lock"/>
<argument type="service" id="event_dispatcher"/>
</service>
</services>
Expand Down
8 changes: 3 additions & 5 deletions tests/Functional/Entity/TaskExecutionRepositoryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -156,10 +156,8 @@ public function testFindScheduledPast()

$execution = $this->save($task, new \DateTime('-1 hour'));

$result = $this->taskExecutionRepository->findScheduled();

$this->assertCount(1, $result);
$this->assertEquals($execution->getUuid(), $result[0]->getUuid());
$result = $this->taskExecutionRepository->findNextScheduled();
$this->assertEquals($execution->getUuid(), $result->getUuid());
}

public function testFindScheduledFuture()
Expand All @@ -169,7 +167,7 @@ public function testFindScheduledFuture()

$this->save($task, new \DateTime('+1 hour'));

$this->assertEmpty($this->taskExecutionRepository->findScheduled());
$this->assertNull($this->taskExecutionRepository->findNextScheduled());
}

/**
Expand Down
6 changes: 3 additions & 3 deletions tests/Functional/Handler/TaskHandlerFactoryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
namespace Task\TaskBundle\Tests\Functional\Handler;

use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
use Task\Handler\TaskHandlerNotExistsException;
use Task\TaskBundle\Handler\TaskHandlerFactory;
use Task\TaskBundle\Tests\Functional\TestHandler;

Expand All @@ -39,10 +38,11 @@ public function testCreate()
$this->assertInstanceOf(TestHandler::class, $this->taskHandlerFactory->create(TestHandler::class));
}

/**
* @expectedException \Task\Handler\TaskHandlerNotExistsException
*/
public function testCreateNotExists()
{
$this->setExpectedException(TaskHandlerNotExistsException::class);

$this->taskHandlerFactory->create(\stdClass::class);
}
}
6 changes: 6 additions & 0 deletions tests/app/config/config.yml
Original file line number Diff line number Diff line change
@@ -1,2 +1,8 @@
parameters:
kernel.secret: 12345

task:
locking:
storages:
file:
directory: %kernel.cache_dir%/locks

0 comments on commit 7c037c4

Please sign in to comment.