Skip to content

Commit 3750531

Browse files
added lock to config
1 parent ca22c35 commit 3750531

File tree

12 files changed

+209
-15
lines changed

12 files changed

+209
-15
lines changed

composer.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,10 @@
1111
],
1212
"require": {
1313
"php": "~5.5 || ~7.0",
14-
"php-task/php-task": "dev-develop",
14+
"php-task/php-task": "dev-feature/lock",
1515
"symfony/http-kernel": "^2.6 || ^3.0",
1616
"symfony/dependency-injection": "^2.6 || ^3.0",
17+
"symfony/expression-language": "^2.6 || ^3.0",
1718
"symfony/config": "^2.6 || ^3.0",
1819
"symfony/console": "^2.6 || ^3.0",
1920
"doctrine/orm": "^2.5"

src/DependencyInjection/Configuration.php

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,19 @@
1919
*/
2020
class Configuration implements ConfigurationInterface
2121
{
22+
/**
23+
* @var string[]
24+
*/
25+
private $lockingStorageAliases = [];
26+
27+
/**
28+
* @param \string[] $lockingStorageAliases
29+
*/
30+
public function __construct(array $lockingStorageAliases)
31+
{
32+
$this->lockingStorageAliases = $lockingStorageAliases;
33+
}
34+
2235
/**
2336
* {@inheritdoc}
2437
*/
@@ -43,10 +56,29 @@ public function getConfigTreeBuilder()
4356
->arrayNode('run')
4457
->addDefaultsIfNotSet()
4558
->children()
46-
->enumNode('mode')
47-
->values(['off', 'listener'])
48-
->defaultValue('off')
59+
->enumNode('mode')->values(['off', 'listener'])->defaultValue('off')->end()
60+
->end()
61+
->end()
62+
->arrayNode('locking')
63+
->canBeEnabled()
64+
->addDefaultsIfNotSet()
65+
->children()
66+
->enumNode('storage')
67+
->values(array_keys($this->lockingStorageAliases))
68+
->defaultValue('file')
69+
->end()
70+
->arrayNode('storages')
71+
->addDefaultsIfNotSet()
72+
->children()
73+
->arrayNode('file')
74+
->addDefaultsIfNotSet()
75+
->children()
76+
->scalarNode('directory')->defaultValue(sys_get_temp_dir() . '/task')->end()
77+
->end()
78+
->end()
79+
->end()
4980
->end()
81+
->enumNode('mode')->values(['off', 'listener'])->defaultValue('off')->end()
5082
->end()
5183
->end()
5284
->arrayNode('system_tasks')
@@ -63,4 +95,16 @@ public function getConfigTreeBuilder()
6395

6496
return $treeBuilder;
6597
}
98+
99+
/**
100+
* Returns id for given storage-alias.
101+
*
102+
* @param string $alias
103+
*
104+
* @return string
105+
*/
106+
public function getLockingStorageId($alias)
107+
{
108+
return $this->lockingStorageAliases[$alias];
109+
}
66110
}

src/DependencyInjection/TaskExtension.php

Lines changed: 56 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespace Task\TaskBundle\DependencyInjection;
1313

1414
use Symfony\Component\Config\FileLocator;
15+
use Symfony\Component\Config\Loader\LoaderInterface;
1516
use Symfony\Component\DependencyInjection\ContainerBuilder;
1617
use Symfony\Component\DependencyInjection\ContainerInterface;
1718
use Symfony\Component\DependencyInjection\Definition;
@@ -31,23 +32,29 @@ class TaskExtension extends Extension
3132
*/
3233
public function load(array $configs, ContainerBuilder $container)
3334
{
34-
$configuration = new Configuration();
35+
$configuration = $this->getConfiguration($configs, $container);
3536
$config = $this->processConfiguration($configuration, $configs);
3637

3738
$container->setParameter('task.system_tasks', $config['system_tasks']);
38-
$container->setParameter('task.storage', $config['storage']);
39+
40+
$container->setAlias('task.lock.storage', $configuration->getLockingStorageId($config['locking']['storage']));
41+
foreach (array_keys($config['locking']['storages']) as $key) {
42+
$container->setParameter('task.lock.storages.' . $key, $config['locking']['storages'][$key]);
43+
}
3944

4045
$loader = new Loader\XmlFileLoader($container, new FileLocator(__DIR__ . '/../Resources/config'));
4146
$loader->load(sprintf('storage/%s.xml', $config['storage']));
4247
$loader->load('task_event_listener.xml');
4348
$loader->load('scheduler.xml');
4449
$loader->load('command.xml');
50+
$loader->load('locking/services.xml');
4551

4652
if ($config['run']['mode'] === 'listener') {
4753
$loader->load('listener.xml');
4854
}
4955

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

5360
/**
@@ -70,4 +77,51 @@ private function loadDoctrineAdapter(array $config, ContainerBuilder $container)
7077
$container->setDefinition('task.adapter.doctrine.execution_listener', $definition);
7178
}
7279
}
80+
81+
/**
82+
* Load services for locking component.
83+
*
84+
* @param array $config
85+
* @param LoaderInterface $loader
86+
*/
87+
private function loadLockingComponent(array $config, LoaderInterface $loader)
88+
{
89+
if (!$config['enabled']) {
90+
return $loader->load('locking/null.xml');
91+
}
92+
93+
$loader->load('locking/services.xml');
94+
}
95+
96+
/**
97+
* Find storage aliases and related ids.
98+
*
99+
* @param ContainerBuilder $container
100+
*
101+
* @return array
102+
*/
103+
private function getLockingStorageAliases(ContainerBuilder $container)
104+
{
105+
$taggedServices = $container->findTaggedServiceIds('task.lock.storage');
106+
107+
$result = [];
108+
foreach ($taggedServices as $id => $tags) {
109+
foreach ($tags as $tag) {
110+
$result[$tag['alias']] = $id;
111+
}
112+
}
113+
114+
return $result;
115+
}
116+
117+
/**
118+
* {@inheritdoc}
119+
*/
120+
public function getConfiguration(array $config, ContainerBuilder $container)
121+
{
122+
$loader = new Loader\XmlFileLoader($container, new FileLocator(__DIR__ . '/../Resources/config'));
123+
$loader->load('locking/storages.xml');
124+
125+
return new Configuration($this->getLockingStorageAliases($container));
126+
}
73127
}

src/Entity/TaskExecutionRepository.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,10 @@ public function findNextScheduled(\DateTime $dateTime = null)
140140
->setMaxResults(1)
141141
->getQuery();
142142

143-
return $query->getResult();
143+
try {
144+
return $query->getSingleResult();
145+
} catch (NoResultException $exception) {
146+
return null;
147+
}
144148
}
145149
}

src/Locking/NullLock.php

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
<?php
2+
3+
/*
4+
* This file is part of php-task library.
5+
*
6+
* (c) php-task
7+
*
8+
* This source file is subject to the MIT license that is bundled
9+
* with this source code in the file LICENSE.
10+
*/
11+
12+
namespace Task\TaskBundle\Locking;
13+
14+
use Task\Execution\TaskExecutionInterface;
15+
use Task\Lock\LockInterface;
16+
17+
/**
18+
* Implements LockInterface which does nothing.
19+
*/
20+
class NullLock implements LockInterface
21+
{
22+
/**
23+
* {@inheritdoc}
24+
*/
25+
public function acquire(TaskExecutionInterface $execution)
26+
{
27+
return true;
28+
}
29+
30+
/**
31+
* {@inheritdoc}
32+
*/
33+
public function refresh(TaskExecutionInterface $execution)
34+
{
35+
return true;
36+
}
37+
38+
/**
39+
* {@inheritdoc}
40+
*/
41+
public function release(TaskExecutionInterface $execution)
42+
{
43+
return true;
44+
}
45+
46+
/**
47+
* {@inheritdoc}
48+
*/
49+
public function isAcquired(TaskExecutionInterface $execution)
50+
{
51+
return false;
52+
}
53+
}

src/Resources/config/locking/null.xml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?xml version="1.0" ?>
2+
<container xmlns="http://symfony.com/schema/dic/services"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
5+
<services>
6+
<service id="task.lock" class="Task\TaskBundle\Locking\NullLock"/>
7+
</services>
8+
</container>
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?xml version="1.0" ?>
2+
<container xmlns="http://symfony.com/schema/dic/services"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
5+
<services>
6+
<service id="task.lock.strategy" class="Task\Lock\Strategy\HandlerClassStrategy"/>
7+
8+
<service id="task.lock" class="Task\Lock\Lock">
9+
<argument type="service" id="task.lock.strategy"/>
10+
<argument type="service" id="task.lock.storage"/>
11+
</service>
12+
</services>
13+
</container>
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?xml version="1.0" ?>
2+
<container xmlns="http://symfony.com/schema/dic/services"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
5+
<services>
6+
<service id="task.lock.storage.file" class="Task\Lock\Storage\FileLock">
7+
<argument type="expression">parameter('task.lock.storages.file')['directory']</argument>
8+
9+
<tag name="task.lock.storage" alias="file"/>
10+
</service>
11+
</services>
12+
</container>

src/Resources/config/scheduler.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
<service id="task.runner" class="Task\Runner\TaskRunner">
2020
<argument type="service" id="task.storage.task_execution"/>
2121
<argument type="service" id="task.handler.factory"/>
22+
<argument type="service" id="task.lock"/>
2223
<argument type="service" id="event_dispatcher"/>
2324
</service>
2425
</services>

tests/Functional/Entity/TaskExecutionRepositoryTest.php

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -154,10 +154,8 @@ public function testFindScheduledPast()
154154

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

157-
$result = $this->taskExecutionRepository->findScheduled();
158-
159-
$this->assertCount(1, $result);
160-
$this->assertEquals($execution->getUuid(), $result[0]->getUuid());
157+
$result = $this->taskExecutionRepository->findNextScheduled();
158+
$this->assertEquals($execution->getUuid(), $result->getUuid());
161159
}
162160

163161
public function testFindScheduledFuture()
@@ -167,7 +165,7 @@ public function testFindScheduledFuture()
167165

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

170-
$this->assertEmpty($this->taskExecutionRepository->findScheduled());
168+
$this->assertNull($this->taskExecutionRepository->findNextScheduled());
171169
}
172170

173171
/**

tests/Functional/Handler/TaskHandlerFactoryTest.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
namespace Task\TaskBundle\Tests\Functional\Handler;
1313

1414
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
15-
use Task\Handler\TaskHandlerNotExistsException;
1615
use Task\TaskBundle\Handler\TaskHandlerFactory;
1716
use Task\TaskBundle\Tests\Functional\TestHandler;
1817

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

41+
/**
42+
* @expectedException \Task\Handler\TaskHandlerNotExistsException
43+
*/
4244
public function testCreateNotExists()
4345
{
44-
$this->setExpectedException(TaskHandlerNotExistsException::class);
45-
4646
$this->taskHandlerFactory->create(\stdClass::class);
4747
}
4848
}

tests/app/config/config.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,8 @@
11
parameters:
22
kernel.secret: 12345
3+
4+
task:
5+
locking:
6+
storages:
7+
file:
8+
directory: %kernel.cache_dir%/locks

0 commit comments

Comments
 (0)