@@ -224,10 +224,12 @@ private StatefulSet concileSts(
224224 requiredSts .getMetadata ().getNamespace ());
225225 final Map <String , String > appLabel = labelFactory .appLabel ();
226226 final List <Pod > currentPods = findStatefulSetPods (requiredSts , appLabel );
227+ final var patroniCtl = this .patroniCtl .instanceFor (context );
228+ final List <PatroniMember > patroniMembers = patroniCtl .list ();
227229 final boolean isRolloutAllowed = ClusterRolloutUtil .isRolloutAllowed (context );
228230 final boolean isReducedImpact = ClusterRolloutUtil .isRolloutReducedImpact (context );
229231 final boolean requiresRestart = ClusterRolloutUtil
230- .getRestartReasons (context , currentSts , currentPods , List . of () )
232+ .getRestartReasons (context , currentSts , currentPods , patroniMembers )
231233 .requiresRestart ();
232234
233235 final int desiredReplicas ;
@@ -243,7 +245,6 @@ private StatefulSet concileSts(
243245 }
244246 final int lastReplicaIndex = desiredReplicas - 1 ;
245247
246- final var patroniCtl = this .patroniCtl .instanceFor (context );
247248 final Optional <String > latestPrimaryFromPatroni =
248249 PatroniUtil .getLatestPrimaryFromPatroni (patroniCtl );
249250 if (desiredReplicas > 0 ) {
@@ -346,7 +347,8 @@ private void performRollout(
346347 .getRestartReasons (context , Optional .of (updatedSts ), pod , List .of ())
347348 .getReasons ().contains (RestartReason .STATEFULSET ))
348349 .findAny ();
349- if (anyOtherPodAndPendingRestart .isPresent ()) {
350+ if (foundPrimaryPod .isEmpty ()
351+ && anyOtherPodAndPendingRestart .isPresent ()) {
350352 if (LOGGER .isDebugEnabled ()) {
351353 LOGGER .debug ("Restarting non primary Pod {} since pending restart" ,
352354 anyOtherPodAndPendingRestart .get ().getMetadata ().getName ());
@@ -387,7 +389,24 @@ private void performRollout(
387389 foundPrimaryPod .get ().getMetadata ().getName ());
388390 }
389391 var credentials = getPatroniCredentials (context .getMetadata ().getName (), context .getMetadata ().getNamespace ());
390- patroniCtl .restart (credentials .v1 , credentials .v2 , foundPrimaryPod .get ().getMetadata ().getName ());
392+ patroniCtl .restart (credentials .v1 , credentials .v2 ,
393+ foundPrimaryPod .get ().getMetadata ().getName ());
394+ return ;
395+ }
396+ var anyOtherPodAndPendingRestartInstance = otherPods
397+ .stream ()
398+ .filter (pod -> patroniMembers .stream ()
399+ .anyMatch (patroniMember -> patroniMember .getMember ().equals (pod .getMetadata ().getName ())
400+ && patroniMember .getPendingRestart () != null ))
401+ .findFirst ();
402+ if (anyOtherPodAndPendingRestartInstance .isPresent ()) {
403+ if (LOGGER .isDebugEnabled ()) {
404+ LOGGER .debug ("Restarting Postgres instance of non primary Pod {} since pending restart" ,
405+ anyOtherPodAndPendingRestartInstance .get ().getMetadata ().getName ());
406+ }
407+ var credentials = getPatroniCredentials (context .getMetadata ().getName (), context .getMetadata ().getNamespace ());
408+ patroniCtl .restart (credentials .v1 , credentials .v2 ,
409+ anyOtherPodAndPendingRestartInstance .get ().getMetadata ().getName ());
391410 return ;
392411 }
393412 if (foundPrimaryPod .isPresent ()
@@ -408,62 +427,61 @@ private void performRollout(
408427 handler .delete (context , anyOtherPodAndPendingRestartAnyReason .get ());
409428 return ;
410429 }
411- final Optional <PatroniMember > leastLagPatroniMemberAndReady =
412- patroniMembers
413- .stream ()
414- .filter (PatroniMember ::isReplica )
415- .filter (PatroniMember ::isRunning )
416- .filter (member -> Optional .ofNullable (member .getTags ())
417- .filter (tags -> tags .entrySet ().stream ().anyMatch (
418- tag -> tag .getKey ().equals (PatroniUtil .NOFAILOVER_TAG )
419- && tag .getValue () != null && tag .getValue ().getValue () != null
420- && Objects .equals (tag .getValue ().getValue ().toString (), Boolean .TRUE .toString ())))
421- .isEmpty ())
422- .min ((m1 , m2 ) -> {
423- var l1 = Optional .ofNullable (m1 .getLagInMb ())
424- .map (IntOrString ::getIntVal );
425- var l2 = Optional .ofNullable (m2 .getLagInMb ())
426- .map (IntOrString ::getIntVal );
427- if (l1 .isPresent () && l2 .isPresent ()) {
428- return l1 .get ().compareTo (l2 .get ());
429- } else if (l1 .isPresent () && l2 .isEmpty ()) {
430- return -1 ;
431- } else if (l1 .isEmpty () && l2 .isPresent ()) {
432- return 1 ;
433- } else {
434- return 0 ;
435- }
436- });
437- final Optional <Pod > otherLeastLagPodAndReady = leastLagPatroniMemberAndReady
438- .stream ()
439- .flatMap (member -> otherPods
440- .stream ()
441- .filter (ClusterRolloutUtil ::isPodReady )
442- .filter (pod -> member .getMember ().equals (pod .getMetadata ().getName ())))
443- .findFirst ();
444- if (foundPrimaryPodAndPendingRestart .isPresent ()
445- && otherLeastLagPodAndReady .isPresent ()) {
446- if (LOGGER .isDebugEnabled ()) {
447- LOGGER .debug ("Failover primary Pod {} to Pod {} since ready and with least lag" ,
430+ if (foundPrimaryPodAndPendingRestart .isPresent ()) {
431+ final Optional <PatroniMember > leastLagPatroniMemberAndReady =
432+ patroniMembers
433+ .stream ()
434+ .filter (PatroniMember ::isReplica )
435+ .filter (PatroniMember ::isRunning )
436+ .filter (member -> Optional .ofNullable (member .getTags ())
437+ .filter (tags -> tags .entrySet ().stream ().anyMatch (
438+ tag -> tag .getKey ().equals (PatroniUtil .NOFAILOVER_TAG )
439+ && tag .getValue () != null && tag .getValue ().getValue () != null
440+ && Objects .equals (tag .getValue ().getValue ().toString (), Boolean .TRUE .toString ())))
441+ .isEmpty ())
442+ .min ((m1 , m2 ) -> {
443+ var l1 = Optional .ofNullable (m1 .getLagInMb ())
444+ .map (IntOrString ::getIntVal );
445+ var l2 = Optional .ofNullable (m2 .getLagInMb ())
446+ .map (IntOrString ::getIntVal );
447+ if (l1 .isPresent () && l2 .isPresent ()) {
448+ return l1 .get ().compareTo (l2 .get ());
449+ } else if (l1 .isPresent () && l2 .isEmpty ()) {
450+ return -1 ;
451+ } else if (l1 .isEmpty () && l2 .isPresent ()) {
452+ return 1 ;
453+ } else {
454+ return 0 ;
455+ }
456+ });
457+ final Optional <Pod > otherLeastLagPodAndReady = leastLagPatroniMemberAndReady
458+ .stream ()
459+ .flatMap (member -> otherPods
460+ .stream ()
461+ .filter (ClusterRolloutUtil ::isPodReady )
462+ .filter (pod -> member .getMember ().equals (pod .getMetadata ().getName ())))
463+ .findFirst ();
464+ if (otherLeastLagPodAndReady .isPresent ()) {
465+ if (LOGGER .isDebugEnabled ()) {
466+ LOGGER .debug ("Failover primary Pod {} to Pod {} since ready and with least lag" ,
467+ foundPrimaryPod .get ().getMetadata ().getName (),
468+ otherLeastLagPodAndReady .get ().getMetadata ().getName ());
469+ }
470+ var credentials = getPatroniCredentials (context .getMetadata ().getName (), context .getMetadata ().getNamespace ());
471+ patroniCtl .switchover (
472+ credentials .v1 ,
473+ credentials .v2 ,
448474 foundPrimaryPod .get ().getMetadata ().getName (),
449475 otherLeastLagPodAndReady .get ().getMetadata ().getName ());
476+ return ;
477+ } else {
478+ if (LOGGER .isDebugEnabled ()) {
479+ LOGGER .debug ("Restarting primary Pod {} since pending restart" ,
480+ foundPrimaryPodAndPendingRestart .get ().getMetadata ().getName ());
481+ }
482+ handler .delete (context , foundPrimaryPodAndPendingRestart .get ());
483+ return ;
450484 }
451- var credentials = getPatroniCredentials (context .getMetadata ().getName (), context .getMetadata ().getNamespace ());
452- patroniCtl .switchover (
453- credentials .v1 ,
454- credentials .v2 ,
455- foundPrimaryPod .get ().getMetadata ().getName (),
456- otherLeastLagPodAndReady .get ().getMetadata ().getName ());
457- return ;
458- }
459- if (foundPrimaryPodAndPendingRestart .isPresent ()
460- && otherLeastLagPodAndReady .isEmpty ()) {
461- if (LOGGER .isDebugEnabled ()) {
462- LOGGER .debug ("Restarting primary Pod {} since pending restart" ,
463- foundPrimaryPodAndPendingRestart .get ().getMetadata ().getName ());
464- }
465- handler .delete (context , foundPrimaryPodAndPendingRestart .get ());
466- return ;
467485 }
468486 }
469487
0 commit comments