package com.airlock.iam.common.infrastructure.state.shared;

import com.airlock.iam.common.domain.model.state.RetryableOperation;
import com.airlock.iam.elog.api.ELogger;
import com.airlock.iam.elog.api.ELoggerFactory;
import java.time.Duration;
import java.util.Objects;
import java.util.function.Supplier;

public final class StateRepositoryRetryUtil {
   private static final int LOCK_ACQUISITION_ATTEMPTS = 3;
   private static final Duration LOCK_ACQUISITION_RETRY_WAIT_DURATION = Duration.ofMillis(50L);
   private static final ELogger LOG = ELoggerFactory.getLogger(StateRepositoryRetryUtil.class);

   public static <T extends RetryableOperation> T executeWithRetries(Supplier<T> retryable) {
      T result = null;

      for (int i = 0; i < 3; i++) {
         result = (T)retryable.get();
         if (!result.shouldRetry()) {
            logRetriesLeadingToFinalResult(i);
            return result;
         }

         try {
            Thread.sleep(LOCK_ACQUISITION_RETRY_WAIT_DURATION.toMillis());
         } catch (InterruptedException var4) {
         }
      }

      Objects.requireNonNull(result);
      logUnsuccessfulRetries();
      return result;
   }

   private static void logRetriesLeadingToFinalResult(int retryCount) {
      if (retryCount > 0) {
         LOG.debug("Returning final result from state repository after %s retries.".formatted(retryCount));
      }
   }

   private static void logUnsuccessfulRetries() {
      LOG.debug("Returning result from state repository after %s unsuccessful retries.".formatted(3));
   }
}
