1111import java .util .Map ;
1212import java .util .Optional ;
1313import java .util .concurrent .ThreadFactory ;
14+ import java .util .concurrent .TimeUnit ;
1415import java .util .concurrent .atomic .AtomicBoolean ;
1516import java .util .function .Consumer ;
1617import javax .annotation .Nonnull ;
2829import io .kubernetes .client .util .Watchable ;
2930import oracle .kubernetes .operator .TuningParameters .WatchTuning ;
3031import oracle .kubernetes .operator .builders .WatchBuilder ;
32+ import oracle .kubernetes .operator .calls .CallResponse ;
3133import oracle .kubernetes .operator .helpers .CallBuilder ;
34+ import oracle .kubernetes .operator .helpers .DomainPresenceInfo ;
3235import oracle .kubernetes .operator .helpers .KubernetesUtils ;
3336import oracle .kubernetes .operator .helpers .LegalNames ;
3437import oracle .kubernetes .operator .helpers .PodHelper ;
3538import oracle .kubernetes .operator .helpers .ResponseStep ;
3639import oracle .kubernetes .operator .logging .LoggingFacade ;
3740import oracle .kubernetes .operator .logging .LoggingFactory ;
3841import oracle .kubernetes .operator .logging .MessageKeys ;
42+ import oracle .kubernetes .operator .steps .DefaultResponseStep ;
3943import oracle .kubernetes .operator .watcher .WatchListener ;
44+ import oracle .kubernetes .operator .work .NextAction ;
45+ import oracle .kubernetes .operator .work .Packet ;
4046import oracle .kubernetes .operator .work .Step ;
4147
48+ import static oracle .kubernetes .operator .ProcessingConstants .SERVER_NAME ;
49+ import static oracle .kubernetes .operator .logging .MessageKeys .EXECUTE_MAKE_RIGHT_DOMAIN ;
50+ import static oracle .kubernetes .operator .logging .MessageKeys .LOG_WAITING_COUNT ;
51+
4252/**
4353 * Watches for changes to pods.
4454 */
@@ -305,6 +315,8 @@ public Step waitForDelete(V1Pod pod, Step next) {
305315
306316 private abstract static class WaitForPodStatusStep extends WaitForReadyStep <V1Pod > {
307317
318+ public static final int RECHECK_DEBUG_COUNT = 10 ;
319+
308320 private WaitForPodStatusStep (V1Pod pod , Step next ) {
309321 super (pod , next );
310322 }
@@ -322,6 +334,67 @@ V1ObjectMeta getMetadata(V1Pod pod) {
322334 Step createReadAsyncStep (String name , String namespace , String domainUid , ResponseStep <V1Pod > responseStep ) {
323335 return new CallBuilder ().readPodAsync (name , namespace , domainUid , responseStep );
324336 }
337+
338+ protected DefaultResponseStep <V1Pod > resumeIfReady (Callback callback ) {
339+ return new DefaultResponseStep <>(getNext ()) {
340+ @ Override
341+ public NextAction onSuccess (Packet packet , CallResponse <V1Pod > callResponse ) {
342+
343+ DomainPresenceInfo info = packet .getSpi (DomainPresenceInfo .class );
344+ String serverName = (String )packet .get (SERVER_NAME );
345+ String resource = initialResource == null ? resourceName : getMetadata (initialResource ).getName ();
346+ if ((info != null ) && (callResponse != null )) {
347+ Optional .ofNullable (callResponse .getResult ()).ifPresent (result ->
348+ info .setServerPodFromEvent (getPodLabel (result ), result ));
349+ if (onReadNotFoundForCachedResource (getServerPod (info , serverName ), isNotFoundOnRead (callResponse ))) {
350+ LOGGER .fine (EXECUTE_MAKE_RIGHT_DOMAIN , serverName , callback .getRecheckCount ());
351+ removeCallback (resource , callback );
352+ return doNext (NEXT_STEP_FACTORY .createMakeDomainRightStep (callback , info , getNext ()), packet );
353+ }
354+ }
355+
356+ if (isReady (callResponse .getResult ()) || callback .didResumeFiber ()) {
357+ callback .proceedFromWait (callResponse .getResult ());
358+ return null ;
359+ }
360+
361+ if (shouldWait ()) {
362+ if ((callback .getRecheckCount () % RECHECK_DEBUG_COUNT ) == 0 ) {
363+ LOGGER .fine (LOG_WAITING_COUNT , serverName , callback .getRecheckCount ());
364+ }
365+ // Watch backstop recheck count is less than or equal to the configured recheck count, delay.
366+ return doDelay (createReadAndIfReadyCheckStep (callback ), packet ,
367+ getWatchBackstopRecheckDelaySeconds (), TimeUnit .SECONDS );
368+ } else {
369+ LOGGER .fine (EXECUTE_MAKE_RIGHT_DOMAIN , serverName , callback .getRecheckCount ());
370+ removeCallback (resource , callback );
371+ // Watch backstop recheck count is more than configured recheck count, proceed to make-right step.
372+ return doNext (NEXT_STEP_FACTORY .createMakeDomainRightStep (callback , info , getNext ()), packet );
373+ }
374+ }
375+
376+ private String getPodLabel (V1Pod pod ) {
377+ return Optional .ofNullable (pod )
378+ .map (V1Pod ::getMetadata )
379+ .map (V1ObjectMeta ::getLabels )
380+ .map (m -> m .get (LabelConstants .SERVERNAME_LABEL ))
381+ .orElse (null );
382+ }
383+
384+ private V1Pod getServerPod (DomainPresenceInfo info , String serverName ) {
385+ return Optional .ofNullable (serverName ).map (info ::getServerPod ).orElse (null );
386+ }
387+
388+ private boolean isNotFoundOnRead (CallResponse callResponse ) {
389+ return callResponse .getResult () == null ;
390+ }
391+
392+ private boolean shouldWait () {
393+ return callback .incrementAndGetRecheckCount () <= getWatchBackstopRecheckCount ();
394+ }
395+ };
396+ }
397+
325398 }
326399
327400 private class WaitForPodReadyStep extends WaitForPodStatusStep {
@@ -360,13 +433,25 @@ protected void removeCallback(String podName, Consumer<V1Pod> callback) {
360433 protected void logWaiting (String name ) {
361434 LOGGER .fine (MessageKeys .WAITING_FOR_POD_READY , name );
362435 }
436+
437+ @ Override
438+ protected boolean onReadNotFoundForCachedResource (V1Pod cachedPod , boolean isNotFoundOnRead ) {
439+ // Return true if cached pod is not null but pod not found in explicit read, false otherwise.
440+ return (cachedPod != null ) && isNotFoundOnRead ;
441+ }
442+
363443 }
364444
365445 private class WaitForPodDeleteStep extends WaitForPodStatusStep {
366446 private WaitForPodDeleteStep (V1Pod pod , Step next ) {
367447 super (pod , next );
368448 }
369449
450+ @ Override
451+ protected boolean onReadNotFoundForCachedResource (V1Pod cachedPod , boolean isNotFoundOnRead ) {
452+ return false ;
453+ }
454+
370455 // A pod is considered deleted when reading its value from Kubernetes returns null.
371456 @ Override
372457 protected boolean isReady (V1Pod result ) {
0 commit comments