Skip to content

Commit 6b25d92

Browse files
committed
FEATURE: Set build lock by workspace to allow parallel releases
1 parent 5e53d53 commit 6b25d92

1 file changed

Lines changed: 19 additions & 10 deletions

File tree

Classes/Core/ConcurrentBuildLockService.php

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,11 @@
44

55
use Flowpack\DecoupledContentStore\Core\Domain\ValueObject\ContentReleaseIdentifier;
66
use Flowpack\DecoupledContentStore\Core\Infrastructure\RedisClientManager;
7+
use Flowpack\DecoupledContentStore\PrepareContentRelease\Infrastructure\RedisContentReleaseService;
78
use Neos\Flow\Annotations as Flow;
89

910
/**
10-
* We usually rely on prunner to ensure that only one build is running at any given time.
11+
* We usually rely on prunner to ensure that only one build per workspace is running at any given time.
1112
*
1213
* However, when running in a cloud environment with no shared storage, the prunner data folder is not shared between
1314
* instances. In this case, during a deployment, two containers run concurrently, with two separate prunner instances
@@ -27,35 +28,43 @@
2728
*/
2829
class ConcurrentBuildLockService
2930
{
31+
private const CONTENT_STORE_CONCURRENT_BUILD_LOCK = 'contentStore:concurrentBuildLocks';
3032

3133
/**
3234
* @Flow\Inject
3335
* @var RedisClientManager
3436
*/
3537
protected $redisClientManager;
3638

37-
public function ensureAllOtherInProgressContentReleasesWillBeTerminated(ContentReleaseIdentifier $contentReleaseIdentifier)
39+
/**
40+
* @Flow\Inject
41+
* @var RedisContentReleaseService
42+
*/
43+
protected $redisContentReleaseService;
44+
45+
public function ensureAllOtherInProgressContentReleasesWillBeTerminated(ContentReleaseIdentifier $contentReleaseIdentifier): void
3846
{
39-
$this->redisClientManager->getPrimaryRedis()->set('contentStore:concurrentBuildLock', $contentReleaseIdentifier->getIdentifier());
47+
$metadata = $this->redisContentReleaseService->fetchMetadataForContentRelease($contentReleaseIdentifier);
48+
$this->redisClientManager->getPrimaryRedis()->hSet(self::CONTENT_STORE_CONCURRENT_BUILD_LOCK, $metadata->getWorkspaceName(), (string)$contentReleaseIdentifier);
4049
}
4150

42-
public function assertNoOtherContentReleaseWasStarted(ContentReleaseIdentifier $contentReleaseIdentifier)
51+
public function assertNoOtherContentReleaseWasStarted(ContentReleaseIdentifier $contentReleaseIdentifier): void
4352
{
44-
$concurrentBuildLockString = $this->redisClientManager->getPrimaryRedis()->get('contentStore:concurrentBuildLock');
53+
$metadata = $this->redisContentReleaseService->fetchMetadataForContentRelease($contentReleaseIdentifier);
54+
$concurrentBuildLockStrings = $this->redisClientManager->getPrimaryRedis()->hGetAll(self::CONTENT_STORE_CONCURRENT_BUILD_LOCK);
55+
$concurrentBuildLockStringForWorkspace = $concurrentBuildLockStrings[$metadata->getWorkspaceName()] ?? null;
4556

46-
if (empty($concurrentBuildLockString)) {
57+
if (!$concurrentBuildLockStringForWorkspace) {
4758
echo '!!!!! Hard-aborting the current job ' . $contentReleaseIdentifier->getIdentifier() . ' because the concurrentBuildLock does not exist.' . "\n\n";
4859
echo "This should never happen for correctly configured jobs (that run after prepare_finished).\n\n";
4960
exit(1);
5061
}
51-
52-
$concurrentBuildLock = ContentReleaseIdentifier::fromString($concurrentBuildLockString);
5362

63+
$concurrentBuildLock = ContentReleaseIdentifier::fromString($concurrentBuildLockStringForWorkspace);
5464
if (!$contentReleaseIdentifier->equals($concurrentBuildLock)) {
5565
// the concurrent build lock is different (i.e. newer) than our currently-running content release.
5666
// Thus, we abort the in-progress content release as quickly as we can - by DYING.
57-
58-
echo '!!!!! Hard-aborting the current job ' . $contentReleaseIdentifier->getIdentifier() . ' because the concurrentBuildLock contains ' . $concurrentBuildLock->getIdentifier() . "\n\n";
67+
echo '!!!!! Hard-aborting the current job ' . $contentReleaseIdentifier->getIdentifier() . ' because the concurrentBuildLock for workspace "' . $metadata->getWorkspaceName() . '" contains ' . $concurrentBuildLock->getIdentifier() . "\n\n";
5968
echo "This is no error during deployment, but should never happen outside a deployment.\n\n It can only happen if two prunner instances run concurrently.\n\n";
6069
exit(1);
6170
}

0 commit comments

Comments
 (0)