88use Flowpack \DecoupledContentStore \Core \Infrastructure \ContentReleaseLogger ;
99use Flowpack \DecoupledContentStore \Core \Infrastructure \RedisClientManager ;
1010use Flowpack \DecoupledContentStore \Core \RedisKeyService ;
11+ use Flowpack \DecoupledContentStore \NodeRendering \Dto \NodeRenderingCompletionStatus ;
12+ use Flowpack \DecoupledContentStore \NodeRendering \Infrastructure \RedisRenderingErrorManager ;
1113use Flowpack \DecoupledContentStore \PrepareContentRelease \Infrastructure \RedisContentReleaseService ;
1214use Flowpack \DecoupledContentStore \ReleaseSwitch \Infrastructure \RedisReleaseSwitchService ;
1315use Flowpack \DecoupledContentStore \Transfer \Dto \RedisKeyPostfixesForEachRelease ;
@@ -42,6 +44,11 @@ class ContentReleaseCleaner
4244 */
4345 protected $ redisReleaseSwitchService ;
4446
47+ /**
48+ * @Flow\Inject
49+ * @var RedisRenderingErrorManager
50+ */
51+ protected $ redisRenderingErrorManager ;
4552
4653 /**
4754 * @Flow\Inject
@@ -66,26 +73,38 @@ public function removeOldReleases(RedisInstanceIdentifier $redisInstanceIdentifi
6673 throw new \RuntimeException ('contentReleaseRetentionCount must be at least 2, found: ' . $ contentReleasesToKeep );
6774 }
6875
69- $ i = 0 ;
76+ $ healthyReleaseCounter = 0 ;
7077 $ releasesToRemove = [];
7178 foreach ($ contentReleaseIds as $ id ) {
7279 if ($ id ->equals ($ currentRelease )) {
7380 $ contentReleaseLogger ->info ('- ' . $ id ->getIdentifier () . ' (LIVE) ' );
7481 } elseif ($ id ->equals ($ contentReleaseIdentifierOfUpcomingRelease )) {
7582 $ contentReleaseLogger ->info ('- ' . $ id ->getIdentifier () . ' (UPCOMING) ' );
7683 } else {
77- $ i ++;
84+ if (!$ redisInstanceIdentifier ->isPrimary ()) {
85+ // We are on a PRODUCTION content store (in case of a replicated setup) - there are no errors transferred there
86+ // by design and we want to NEVER run into a memory problem (that's why the cleanup should always run).
87+ $ healthyReleaseCounter ++;
88+ } else {
89+ // We are on the primary content store (the one which the pipeline uses as scratch space).
90+ // In case of errors, we want to keep more "good" content releases ("success" state and no errors), so that we can
91+ // more easily switch back to an older release.
92+ // -> We accept potential Redis out of memory errors in this case.
93+ if (($ this ->redisContentReleaseService ->fetchMetadataForContentRelease ($ id )->getStatus ()->getStatus () === NodeRenderingCompletionStatus::success ()->getStatus () && count ($ this ->redisRenderingErrorManager ->getRenderingErrors ($ id )) === 0 )) {
94+ $ healthyReleaseCounter ++;
95+ }
96+ }
7897
7998 // we always want to keep $currentRelease and $contentReleaseIdentifierOfUpcomingRelease; thus
8099 // we need to remove 2 from $contentReleasesToKeep
81- $ shouldRemoveRelease = ($ i > $ contentReleasesToKeep - 2 );
82-
83- if ($ shouldRemoveRelease ) {
84- $ releasesToRemove [] = $ id ;
85- $ contentReleaseLogger ->info ('- ' . $ id ->getIdentifier () . ' <-- to remove ' );
86- } else {
87- $ contentReleaseLogger ->info ('- ' . $ id ->getIdentifier ());
88- }
100+ $ shouldRemoveRelease = ($ healthyReleaseCounter > $ contentReleasesToKeep - 2 );
101+
102+ if ($ shouldRemoveRelease ) {
103+ $ releasesToRemove [] = $ id ;
104+ $ contentReleaseLogger ->info ('- ' . $ id ->getIdentifier () . ' <-- to remove ' );
105+ } else {
106+ $ contentReleaseLogger ->info ('- ' . $ id ->getIdentifier ());
107+ }
89108 }
90109 }
91110
0 commit comments