Skip to content

Commit c63d249

Browse files
committed
FEATURE: Allow defining a workspace for a content release
Previously only the live workspace has been used.
1 parent b38c231 commit c63d249

7 files changed

Lines changed: 75 additions & 66 deletions

File tree

Classes/Command/ContentReleasePrepareCommandController.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,23 +28,23 @@ class ContentReleasePrepareCommandController extends CommandController
2828
*/
2929
protected $concurrentBuildLock;
3030

31-
public function createContentReleaseCommand(string $contentReleaseIdentifier, string $prunnerJobId)
31+
public function createContentReleaseCommand(string $contentReleaseIdentifier, string $prunnerJobId, string $workspaceName = 'live'): void
3232
{
3333
$contentReleaseIdentifier = ContentReleaseIdentifier::fromString($contentReleaseIdentifier);
3434
$prunnerJobId = PrunnerJobId::fromString($prunnerJobId);
3535
$logger = ContentReleaseLogger::fromConsoleOutput($this->output, $contentReleaseIdentifier);
3636

37-
$this->redisContentReleaseService->createContentRelease($contentReleaseIdentifier, $prunnerJobId, $logger);
37+
$this->redisContentReleaseService->createContentRelease($contentReleaseIdentifier, $prunnerJobId, $logger, $workspaceName);
3838
}
3939

40-
public function ensureAllOtherInProgressContentReleasesWillBeTerminatedCommand(string $contentReleaseIdentifier)
40+
public function ensureAllOtherInProgressContentReleasesWillBeTerminatedCommand(string $contentReleaseIdentifier): void
4141
{
4242
$contentReleaseIdentifier = ContentReleaseIdentifier::fromString($contentReleaseIdentifier);
4343

4444
$this->concurrentBuildLock->ensureAllOtherInProgressContentReleasesWillBeTerminated($contentReleaseIdentifier);
4545
}
4646

47-
public function registerManualTransferJobCommand(string $contentReleaseIdentifier, string $prunnerJobId)
47+
public function registerManualTransferJobCommand(string $contentReleaseIdentifier, string $prunnerJobId): void
4848
{
4949
$contentReleaseIdentifier = ContentReleaseIdentifier::fromString($contentReleaseIdentifier);
5050
$prunnerJobId = PrunnerJobId::fromString($prunnerJobId);

Classes/ContentReleaseManager.php

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use Flowpack\DecoupledContentStore\Core\Domain\ValueObject\ContentReleaseIdentifier;
88
use Flowpack\DecoupledContentStore\Core\Domain\ValueObject\RedisInstanceIdentifier;
99
use Flowpack\DecoupledContentStore\Core\Infrastructure\RedisClientManager;
10+
use Neos\ContentRepository\Domain\Model\Workspace;
1011
use Flowpack\Prunner\ValueObject\JobId;
1112
use Neos\Flow\Annotations as Flow;
1213
use Flowpack\Prunner\PrunnerApiService;
@@ -60,7 +61,7 @@ public function startIncrementalContentRelease(string $currentContentReleaseId =
6061
}
6162

6263
// the validate parameter can be used to intentionally skip the validation step for this release
63-
public function startFullContentRelease(bool $validate = true, string $currentContentReleaseId = null): ContentReleaseIdentifier
64+
public function startFullContentRelease(bool $validate = true, string $currentContentReleaseId = null, Workspace $workspace = null): ContentReleaseIdentifier
6465
{
6566
$redis = $this->redisClientManager->getPrimaryRedis();
6667
if ($currentContentReleaseId) {
@@ -69,7 +70,12 @@ public function startFullContentRelease(bool $validate = true, string $currentCo
6970

7071
$contentReleaseId = ContentReleaseIdentifier::create();
7172
$this->contentCache->flush();
72-
$this->prunnerApiService->schedulePipeline(PipelineName::create('do_content_release'), ['contentReleaseId' => $contentReleaseId, 'currentContentReleaseId' => $currentContentReleaseId ?: self::NO_PREVIOUS_RELEASE, 'validate' => $validate]);
73+
$this->prunnerApiService->schedulePipeline(PipelineName::create('do_content_release'), [
74+
'contentReleaseId' => $contentReleaseId,
75+
'currentContentReleaseId' => $currentContentReleaseId ?: self::NO_PREVIOUS_RELEASE,
76+
'validate' => $validate,
77+
'workspaceName' => $workspace ? $workspace->getName() : 'live'
78+
]);
7379
return $contentReleaseId;
7480
}
7581

Lines changed: 26 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,50 @@
11
<?php
2-
namespace Flowpack\DecoupledContentStore\NodeEnumeration\Domain\Service;
2+
declare(strict_types=1);
33

4+
namespace Flowpack\DecoupledContentStore\NodeEnumeration\Domain\Service;
45

6+
use Flowpack\DecoupledContentStore\Exception\NodeNotFoundException;
7+
use Neos\ContentRepository\Domain\Model\Workspace;
8+
use Neos\ContentRepository\Domain\Service\ContextFactoryInterface;
59
use Neos\Flow\Annotations as Flow;
610
use Neos\Neos\Domain\Model\Site;
711
use Neos\ContentRepository\Domain\Model\NodeInterface;
12+
use Neos\Neos\Domain\Repository\SiteRepository;
13+
use Neos\Neos\Domain\Service\ContentDimensionPresetSourceInterface;
814

915
class NodeContextCombinator
1016
{
1117

1218
/**
1319
* @Flow\Inject
14-
* @var \Neos\Neos\Domain\Service\ContentDimensionPresetSourceInterface
20+
* @var ContentDimensionPresetSourceInterface
1521
*/
1622
protected $dimensionPresetSource;
1723

1824
/**
1925
* @Flow\Inject
20-
* @var \Neos\Neos\Domain\Repository\SiteRepository
26+
* @var SiteRepository
2127
*/
2228
protected $siteRepository;
2329

2430
/**
2531
* @Flow\Inject
26-
* @var \Neos\ContentRepository\Domain\Service\ContextFactoryInterface
32+
* @var ContextFactoryInterface
2733
*/
2834
protected $contextFactory;
2935

3036
/**
3137
* Iterate over the node with the given identifier and site in contexts for all available presets (if it exists as a variant)
3238
*
33-
* @param string $nodeIdentifier
34-
* @param Site $site
35-
* @return \Generator
36-
* @throws Exception\NodeNotFoundException
39+
* @return \Generator<NodeInterface>
40+
* @throws NodeNotFoundException
3741
*/
38-
public function nodeInContexts($nodeIdentifier, Site $site)
42+
public function nodeInContexts(string $nodeIdentifier, Site $site, string $workspaceName = 'live'): \Generator
3943
{
4044
$nodeFound = false;
4145

4246
/** @var NodeInterface $siteNode */
43-
foreach ($this->siteNodeInContexts($site) as $siteNode) {
47+
foreach ($this->siteNodeInContexts($site, $workspaceName) as $siteNode) {
4448
$node = $siteNode->getContext()->getNodeByIdentifier($nodeIdentifier);
4549

4650
if ($node instanceof NodeInterface) {
@@ -50,17 +54,17 @@ public function nodeInContexts($nodeIdentifier, Site $site)
5054
}
5155

5256
if (!$nodeFound) {
53-
throw new Exception\NodeNotFoundException('Could not find node by identifier ' . $nodeIdentifier . ' in any context',
57+
throw new NodeNotFoundException('Could not find node by identifier ' . $nodeIdentifier . ' in any context',
5458
1467285561);
5559
}
5660
}
5761

5862
/**
5963
* Iterate over all sites
6064
*
61-
* @return Site[]
65+
* @return \Generator<Site>
6266
*/
63-
public function sites()
67+
public function sites(): \Generator
6468
{
6569
$sites = $this->siteRepository->findAll();
6670

@@ -72,16 +76,15 @@ public function sites()
7276
/**
7377
* Iterate over the site node in all available presets (if it exists)
7478
*
75-
* @param Site $site
76-
* @return NodeInterface[]
79+
* @return \Generator<NodeInterface>
7780
*/
78-
public function siteNodeInContexts(Site $site)
81+
public function siteNodeInContexts(Site $site, string $workspaceName = 'live'): \Generator
7982
{
8083
$presets = $this->dimensionPresetSource->getAllPresets();
8184
if ($presets === []) {
8285
$contentContext = $this->contextFactory->create(array(
8386
'currentSite' => $site,
84-
'workspaceName' => 'live',
87+
'workspaceName' => $workspaceName,
8588
'dimensions' => [],
8689
'targetDimensions' => []
8790
));
@@ -96,7 +99,7 @@ public function siteNodeInContexts(Site $site)
9699

97100
$contentContext = $this->contextFactory->create(array(
98101
'currentSite' => $site,
99-
'workspaceName' => 'live',
102+
'workspaceName' => $workspaceName,
100103
'dimensions' => $dimensions,
101104
'targetDimensions' => []
102105
));
@@ -114,16 +117,15 @@ public function siteNodeInContexts(Site $site)
114117
/**
115118
* Iterate over the given node and all document child nodes recursively
116119
*
117-
* @param NodeInterface $node
118-
* @return NodeInterface[]
120+
* @return \Generator<NodeInterface>
119121
*/
120-
public function recurseDocumentChildNodes(NodeInterface $node)
122+
public function recurseDocumentChildNodes(NodeInterface $node): \Generator
121123
{
122124
yield $node;
123125

124-
foreach ($node->getChildNodes('Neos.Neos:Document') as $node) {
125-
yield from $this->recurseDocumentChildNodes($node);
126+
foreach ($node->getChildNodes('Neos.Neos:Document') as $childNode) {
127+
yield from $this->recurseDocumentChildNodes($childNode);
126128
}
127129
}
128130

129-
}
131+
}

Classes/NodeEnumeration/NodeEnumerator.php

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,7 @@ class NodeEnumerator
5050
*/
5151
protected $nodeTypeWhitelist;
5252

53-
54-
public function enumerateAndStoreInRedis(?Site $site, ContentReleaseLogger $contentReleaseLogger, ContentReleaseIdentifier $releaseIdentifier)
53+
public function enumerateAndStoreInRedis(?Site $site, ContentReleaseLogger $contentReleaseLogger, ContentReleaseIdentifier $releaseIdentifier): void
5554
{
5655
$contentReleaseLogger->info('Starting content release', ['contentReleaseIdentifier' => $releaseIdentifier->jsonSerialize()]);
5756

@@ -61,7 +60,7 @@ public function enumerateAndStoreInRedis(?Site $site, ContentReleaseLogger $cont
6160
$this->redisContentReleaseService->setContentReleaseMetadata($releaseIdentifier, $newMetadata, RedisInstanceIdentifier::primary());
6261

6362
$this->redisEnumerationRepository->clearDocumentNodesEnumeration($releaseIdentifier);
64-
foreach (GeneratorUtility::createArrayBatch($this->enumerateAll($site, $contentReleaseLogger), 100) as $enumeration) {
63+
foreach (GeneratorUtility::createArrayBatch($this->enumerateAll($site, $contentReleaseLogger, $newMetadata->getWorkspaceName()), 100) as $enumeration) {
6564
$this->concurrentBuildLockService->assertNoOtherContentReleaseWasStarted($releaseIdentifier);
6665
// $enumeration is an array of EnumeratedNode, with at most 100 elements in it.
6766
// TODO: EXTENSION POINT HERE, TO ADD ADDITIONAL ENUMERATIONS (.metadata.json f.e.)
@@ -71,22 +70,20 @@ public function enumerateAndStoreInRedis(?Site $site, ContentReleaseLogger $cont
7170
}
7271

7372
/**
74-
* @param Site $site
75-
* @param ContentReleaseLogger $contentReleaseLogger
7673
* @return iterable<EnumeratedNode>
7774
*/
78-
private function enumerateAll(?Site $site, ContentReleaseLogger $contentReleaseLogger): iterable
75+
private function enumerateAll(?Site $site, ContentReleaseLogger $contentReleaseLogger, string $workspaceName): iterable
7976
{
8077
$combinator = new NodeContextCombinator();
8178

8279
$nodeTypeWhitelist = $this->nodeTypeConstraintFactory->parseFilterString($this->nodeTypeWhitelist);
8380

84-
$queueSite = function (Site $site) use ($combinator, &$documentNodeVariantsToRender, $nodeTypeWhitelist, $contentReleaseLogger) {
81+
$queueSite = function (Site $site) use ($combinator, &$documentNodeVariantsToRender, $nodeTypeWhitelist, $contentReleaseLogger, $workspaceName) {
8582
$contentReleaseLogger->debug('Publishing site', [
8683
'name' => $site->getName(),
8784
'domain' => $site->getFirstActiveDomain()
8885
]);
89-
foreach ($combinator->siteNodeInContexts($site) as $siteNode) {
86+
foreach ($combinator->siteNodeInContexts($site, $workspaceName) as $siteNode) {
9087
$dimensionValues = $siteNode->getContext()->getDimensions();
9188

9289
$contentReleaseLogger->debug('Publishing dimension combination', [
@@ -113,7 +110,6 @@ private function enumerateAll(?Site $site, ContentReleaseLogger $contentReleaseL
113110
}
114111
};
115112

116-
117113
if ($site === null) {
118114
foreach ($combinator->sites() as $site) {
119115
yield from $queueSite($site);

Classes/PrepareContentRelease/Dto/ContentReleaseMetadata.php

Lines changed: 25 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
use Flowpack\DecoupledContentStore\Core\Domain\ValueObject\ContentReleaseIdentifier;
77
use Flowpack\DecoupledContentStore\Core\Domain\ValueObject\PrunnerJobId;
88
use Flowpack\DecoupledContentStore\NodeRendering\Dto\NodeRenderingCompletionStatus;
9+
use Neos\ContentRepository\Domain\Model\Workspace;
910
use Neos\Flow\Annotations as Flow;
1011

1112
/**
@@ -38,20 +39,31 @@ final class ContentReleaseMetadata implements \JsonSerializable
3839

3940
private NodeRenderingCompletionStatus $status;
4041

41-
private function __construct(PrunnerJobId $prunnerJobId, ?\DateTimeInterface $startTime, ?\DateTimeInterface $endTime, ?\DateTimeInterface $switchTime, ?NodeRenderingCompletionStatus $status, ?array $manualTransferJobIds = [])
42+
private ?string $workspaceName;
43+
44+
private function __construct(
45+
PrunnerJobId $prunnerJobId,
46+
?\DateTimeInterface $startTime,
47+
?\DateTimeInterface $endTime,
48+
?\DateTimeInterface $switchTime,
49+
?NodeRenderingCompletionStatus $status,
50+
?array $manualTransferJobIds = [],
51+
string $workspaceName = 'live'
52+
)
4253
{
4354
$this->prunnerJobId = $prunnerJobId;
4455
$this->startTime = $startTime;
4556
$this->endTime = $endTime;
4657
$this->switchTime = $switchTime;
4758
$this->status = $status ?: NodeRenderingCompletionStatus::scheduled();
4859
$this->manualTransferJobIds = $manualTransferJobIds;
60+
$this->workspaceName = $workspaceName;
4961
}
5062

5163

52-
public static function create(PrunnerJobId $prunnerJobId, \DateTimeInterface $startTime): self
64+
public static function create(PrunnerJobId $prunnerJobId, \DateTimeInterface $startTime, string $workspace = 'live'): self
5365
{
54-
return new self($prunnerJobId, $startTime, null, null, NodeRenderingCompletionStatus::scheduled());
66+
return new self($prunnerJobId, $startTime, null, null, NodeRenderingCompletionStatus::scheduled(), [], $workspace);
5567
}
5668

5769
public static function fromJsonString($metadataEncoded, ContentReleaseIdentifier $contentReleaseIdentifier): self
@@ -72,20 +84,22 @@ public static function fromJsonString($metadataEncoded, ContentReleaseIdentifier
7284
NodeRenderingCompletionStatus::fromString($tmp['status']),
7385
isset($tmp['manualTransferJobIds']) ? array_map(function (string $item) {
7486
return PrunnerJobId::fromString($item);
75-
}, json_decode($tmp['manualTransferJobIds'])) : []
87+
}, json_decode($tmp['manualTransferJobIds'])) : [],
88+
$tmp['workspace'] ?? 'live'
7689
);
7790
}
7891

7992

80-
public function jsonSerialize()
93+
public function jsonSerialize(): array
8194
{
8295
return [
8396
'prunnerJobId' => $this->prunnerJobId->getIdentifier(),
8497
'startTime' => $this->startTime ? $this->startTime->format(\DateTime::RFC3339_EXTENDED) : null,
8598
'endTime' => $this->endTime ? $this->endTime->format(\DateTime::RFC3339_EXTENDED) : null,
8699
'switchTime' => $this->switchTime ? $this->switchTime->format(\DateTime::RFC3339_EXTENDED) : null,
87100
'status' => $this->status,
88-
'manualTransferJobIds' => json_encode($this->manualTransferJobIds)
101+
'manualTransferJobIds' => json_encode($this->manualTransferJobIds),
102+
'workspaceName' => $this->workspaceName
89103
];
90104
}
91105

@@ -111,41 +125,26 @@ public function withAdditionalManualTransferJobId(PrunnerJobId $prunnerJobId): s
111125
return new self($this->prunnerJobId, $this->startTime, $this->endTime, $this->switchTime, $this->status, $manualTransferIdArray);
112126
}
113127

114-
/**
115-
* @return PrunnerJobId
116-
*/
117128
public function getPrunnerJobId(): PrunnerJobId
118129
{
119130
return $this->prunnerJobId;
120131
}
121132

122-
/**
123-
* @return \DateTimeInterface|null
124-
*/
125133
public function getStartTime(): ?\DateTimeInterface
126134
{
127135
return $this->startTime;
128136
}
129137

130-
/**
131-
* @return \DateTimeInterface|null
132-
*/
133138
public function getEndTime(): ?\DateTimeInterface
134139
{
135140
return $this->endTime;
136141
}
137142

138-
/**
139-
* @return \DateTimeInterface|null
140-
*/
141143
public function getSwitchTime(): ?\DateTimeInterface
142144
{
143145
return $this->switchTime;
144146
}
145147

146-
/**
147-
* @return NodeRenderingCompletionStatus
148-
*/
149148
public function getStatus(): NodeRenderingCompletionStatus
150149
{
151150
return $this->status;
@@ -159,4 +158,9 @@ public function getManualTransferJobIds(): ?array
159158
return $this->manualTransferJobIds;
160159
}
161160

161+
public function getWorkspaceName(): ?string
162+
{
163+
return $this->workspaceName;
164+
}
165+
162166
}

0 commit comments

Comments
 (0)