|
4 | 4 |
|
5 | 5 | use Flowpack\DecoupledContentStore\Core\Domain\ValueObject\ContentReleaseIdentifier; |
6 | 6 | use Flowpack\DecoupledContentStore\Core\Infrastructure\RedisClientManager; |
| 7 | +use Flowpack\DecoupledContentStore\PrepareContentRelease\Infrastructure\RedisContentReleaseService; |
7 | 8 | use Neos\Flow\Annotations as Flow; |
8 | 9 |
|
9 | 10 | /** |
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. |
11 | 12 | * |
12 | 13 | * However, when running in a cloud environment with no shared storage, the prunner data folder is not shared between |
13 | 14 | * instances. In this case, during a deployment, two containers run concurrently, with two separate prunner instances |
|
27 | 28 | */ |
28 | 29 | class ConcurrentBuildLockService |
29 | 30 | { |
| 31 | + private const CONTENT_STORE_CONCURRENT_BUILD_LOCK = 'contentStore:concurrentBuildLocks'; |
30 | 32 |
|
31 | 33 | /** |
32 | 34 | * @Flow\Inject |
33 | 35 | * @var RedisClientManager |
34 | 36 | */ |
35 | 37 | protected $redisClientManager; |
36 | 38 |
|
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 |
38 | 46 | { |
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); |
40 | 49 | } |
41 | 50 |
|
42 | | - public function assertNoOtherContentReleaseWasStarted(ContentReleaseIdentifier $contentReleaseIdentifier) |
| 51 | + public function assertNoOtherContentReleaseWasStarted(ContentReleaseIdentifier $contentReleaseIdentifier): void |
43 | 52 | { |
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; |
45 | 56 |
|
46 | | - if (empty($concurrentBuildLockString)) { |
| 57 | + if (!$concurrentBuildLockStringForWorkspace) { |
47 | 58 | echo '!!!!! Hard-aborting the current job ' . $contentReleaseIdentifier->getIdentifier() . ' because the concurrentBuildLock does not exist.' . "\n\n"; |
48 | 59 | echo "This should never happen for correctly configured jobs (that run after prepare_finished).\n\n"; |
49 | 60 | exit(1); |
50 | 61 | } |
51 | | - |
52 | | - $concurrentBuildLock = ContentReleaseIdentifier::fromString($concurrentBuildLockString); |
53 | 62 |
|
| 63 | + $concurrentBuildLock = ContentReleaseIdentifier::fromString($concurrentBuildLockStringForWorkspace); |
54 | 64 | if (!$contentReleaseIdentifier->equals($concurrentBuildLock)) { |
55 | 65 | // the concurrent build lock is different (i.e. newer) than our currently-running content release. |
56 | 66 | // 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"; |
59 | 68 | 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"; |
60 | 69 | exit(1); |
61 | 70 | } |
|
0 commit comments