Skip to content

Commit 1f0cf92

Browse files
committed
FEATURE: add previous config epoch and toggle button
1 parent 514f918 commit 1f0cf92

5 files changed

Lines changed: 66 additions & 7 deletions

File tree

Classes/ContentReleaseManager.php

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
namespace Flowpack\DecoupledContentStore;
66

7+
use Flowpack\DecoupledContentStore\Core\Domain\ValueObject\RedisInstanceIdentifier;
78
use Flowpack\DecoupledContentStore\Core\Infrastructure\RedisClientManager;
89
use Neos\Flow\Annotations as Flow;
910
use Flowpack\Prunner\PrunnerApiService;
@@ -33,6 +34,12 @@ class ContentReleaseManager
3334
*/
3435
protected $redisClientManager;
3536

37+
/**
38+
* @Flow\InjectConfiguration("configEpoch")
39+
* @var array
40+
*/
41+
protected $configEpochSettings;
42+
3643
const REDIS_CURRENT_RELEASE_KEY = 'contentStore:current';
3744
const NO_PREVIOUS_RELEASE = 'NO_PREVIOUS_RELEASE';
3845

@@ -63,4 +70,18 @@ public function cancelAllRunningContentReleases()
6370
$this->prunnerApiService->cancelJob($job);
6471
}
6572
}
73+
74+
public function toggleConfigEpoch(RedisInstanceIdentifier $redisInstanceIdentifier)
75+
{
76+
$currentConfigEpochConfig = $this->configEpochSettings['current'] ?? null;
77+
$previousConfigEpochConfig = $this->configEpochSettings['previous'] ?? null;
78+
$redis = $this->redisClientManager->getRedis($redisInstanceIdentifier);
79+
$configEpochRedis = $redis->get('contentStore:configEpoch');
80+
81+
if ($configEpochRedis === $currentConfigEpochConfig) {
82+
$redis->set('contentStore:configEpoch', $previousConfigEpochConfig);
83+
} else {
84+
$redis->set('contentStore:configEpoch', $currentConfigEpochConfig);
85+
}
86+
}
6687
}

Classes/Controller/BackendController.php

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,17 +82,31 @@ class BackendController extends \Neos\Flow\Mvc\Controller\ActionController
8282
*/
8383
protected $redisContentStores;
8484

85+
/**
86+
* @Flow\InjectConfiguration("configEpoch")
87+
* @var array
88+
*/
89+
protected $configEpochSettings;
90+
8591
protected $defaultViewObjectName = FusionView::class;
8692

8793
public function indexAction(?string $contentStore = null)
8894
{
8995
$contentStore = $contentStore ? RedisInstanceIdentifier::fromString($contentStore) : RedisInstanceIdentifier::primary();
90-
$storeSize = $this->redisClientManager->getRedis($contentStore)->info('memory')['used_memory_human'];
96+
$redis = $this->redisClientManager->getRedis($contentStore);
97+
$storeSize = $redis->info('memory')['used_memory_human'];
98+
$currentConfigEpoch = $this->configEpochSettings['current'] ?? null;
99+
$previousConfigEpoch = $this->configEpochSettings['previous'] ?? null;
100+
$configEpochRedis = $redis->get('contentStore:configEpoch');
101+
$showToggleConfigEpochButton = $previousConfigEpoch !== null && !$contentStore->isPrimary();
91102

92103
$this->view->assign('contentStore', $contentStore->getIdentifier());
93104
$this->view->assign('overviewData', $this->backendUiDataService->loadBackendOverviewData($contentStore));
94105
$this->view->assign('redisContentStores', array_keys($this->redisContentStores));
95106
$this->view->assign('storeSize', $storeSize);
107+
$this->view->assign('toggleFromConfigEpoch', $configEpochRedis);
108+
$this->view->assign('toggleToConfigEpoch', $configEpochRedis === $currentConfigEpoch ? $previousConfigEpoch : $currentConfigEpoch);
109+
$this->view->assign('showToggleConfigEpochButton', $showToggleConfigEpochButton);
96110
}
97111

98112
public function detailsAction(string $contentReleaseIdentifier, ?string $contentStore = null, ?string $detailTaskName = '', ?string $prunnerJobId = '')
@@ -183,4 +197,12 @@ public function cancelRunningReleaseAction(string $redisInstanceIdentifier)
183197

184198
$this->redirect('index', null, null, ['contentStore' => $redisInstanceIdentifier->getIdentifier()]);
185199
}
200+
201+
public function toggleConfigEpochAction(string $redisInstanceIdentifier)
202+
{
203+
$redisInstanceIdentifier = RedisInstanceIdentifier::fromString($redisInstanceIdentifier);
204+
$this->contentReleaseManager->toggleConfigEpoch($redisInstanceIdentifier);
205+
206+
$this->redirect('index', null, null, ['contentStore' => $redisInstanceIdentifier->getIdentifier()]);
207+
}
186208
}

Classes/Transfer/ContentReleaseSynchronizer.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,9 @@ class ContentReleaseSynchronizer
3030

3131
/**
3232
* @Flow\InjectConfiguration("configEpoch")
33-
* @var string
33+
* @var array
3434
*/
35-
protected $configEpochSetting;
35+
protected $configEpochSettings;
3636

3737
/**
3838
* @Flow\Inject
@@ -70,7 +70,7 @@ public function syncToTarget(RedisInstanceIdentifier $targetRedisIdentifier, Con
7070
}
7171

7272
$targetRedis->zAdd('contentStore:registeredReleases', 0, $contentReleaseIdentifier->getIdentifier());
73-
$targetRedis->set('contentStore:configEpoch', $this->configEpochSetting);
73+
$targetRedis->set('contentStore:configEpoch', $this->configEpochSettings['current']);
7474
}
7575

7676
/**

Configuration/Settings.yaml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,9 @@ Flowpack:
121121
isRequired: true
122122

123123
# can be used on the consuming site to ensure non-breaking deployments for changes in the config
124-
configEpoch: v1
124+
configEpoch:
125+
current: v1
126+
previous: ~
125127

126128

127129
resourceSync:

Resources/Private/BackendFusion/Integration/Backend.Index.fusion

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ Flowpack.DecoupledContentStore.BackendController.index = Neos.Fusion:Component {
55
// - contentStore: contains string content store identifier
66
// - redisContentStores: array of all configured content store identifiers
77
// - storeSize: string of content store size
8+
// - toggleFromConfigEpoch: string, e.g. "v2"
9+
// - toggleToConfigEpoch: string, e.g. "v1"
10+
// - showToggleConfigEpochButton: boolean
811

912
renderer = Neos.Fusion:Component {
1013
_pruneContentStoreUri = Neos.Fusion:UriBuilder {
@@ -20,6 +23,13 @@ Flowpack.DecoupledContentStore.BackendController.index = Neos.Fusion:Component {
2023
}
2124
}
2225

26+
_toggleConfigEpoch = Neos.Fusion:UriBuilder {
27+
action = 'toggleConfigEpoch'
28+
arguments = Neos.Fusion:DataStructure {
29+
redisInstanceIdentifier = ${contentStore}
30+
}
31+
}
32+
2333
_renderedTableBody = Neos.Fusion:Loop {
2434
items = ${overviewData}
2535
itemRenderer = Neos.Fusion:Component {
@@ -95,13 +105,17 @@ Flowpack.DecoupledContentStore.BackendController.index = Neos.Fusion:Component {
95105
<span>Store size: </span>
96106
<span class="neos-badge neos-badge-info">{storeSize}</span>
97107
<br />
98-
<button form="postHelper" formaction={props._pruneContentStoreUri} type="submit" class="neos-button neos-button-danger" style="margin-top: 300px;">
108+
<button form="postHelper" formaction={props._pruneContentStoreUri} type="submit" class="neos-button neos-button-warning" style="margin-top: 300px;">
99109
Prune content store
100110
</button>
101111
<span> </span>
102-
<button form="postHelper" formaction={props._cancelRunningReleaseUri} type="submit" class="neos-button neos-button-danger" style="margin-top: 300px;">
112+
<button form="postHelper" formaction={props._cancelRunningReleaseUri} type="submit" class="neos-button neos-button-warning" style="margin-top: 300px;">
103113
Cancel running release
104114
</button>
115+
<span> </span>
116+
<button @if.showToggleConfigEpochButton={showToggleConfigEpochButton} form="postHelper" formaction={props._toggleConfigEpoch} type="submit" class="neos-button neos-button-danger" style="margin-top: 300px;">
117+
{'Toggle config epoch: ' + toggleFromConfigEpoch + ' to ' + toggleToConfigEpoch}
118+
</button>
105119

106120
<div class="neos-footer !h-full">
107121
<Flowpack.DecoupledContentStore:ListFooter />

0 commit comments

Comments
 (0)