From bcd8ccf723def1da9397f40c9118b21175fc51c0 Mon Sep 17 00:00:00 2001 From: Ender Tunc Date: Thu, 16 Mar 2023 13:54:07 +0100 Subject: [PATCH 1/3] check merge request status with backoff --- .../core/forge/ForgeSelection.scala | 5 ++-- .../core/forge/gitlab/GitLabApiAlg.scala | 24 +++++++++++++++---- 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/modules/core/src/main/scala/org/scalasteward/core/forge/ForgeSelection.scala b/modules/core/src/main/scala/org/scalasteward/core/forge/ForgeSelection.scala index 914d2e741e..f52ffe18c7 100644 --- a/modules/core/src/main/scala/org/scalasteward/core/forge/ForgeSelection.scala +++ b/modules/core/src/main/scala/org/scalasteward/core/forge/ForgeSelection.scala @@ -16,8 +16,9 @@ package org.scalasteward.core.forge +import cats.effect.Temporal import cats.syntax.all._ -import cats.{Applicative, MonadThrow, Parallel} +import cats.{Applicative, Parallel} import org.http4s.headers.Authorization import org.http4s.{BasicCredentials, Header, Request} import org.scalasteward.core.application.Config @@ -42,7 +43,7 @@ object ForgeSelection { )(implicit httpJsonClient: HttpJsonClient[F], logger: Logger[F], - F: MonadThrow[F] + temporal: Temporal[F] ): ForgeApiAlg[F] = { val auth = (_: Any) => authenticate(forgeCfg.tpe, user) forgeSpecificCfg match { diff --git a/modules/core/src/main/scala/org/scalasteward/core/forge/gitlab/GitLabApiAlg.scala b/modules/core/src/main/scala/org/scalasteward/core/forge/gitlab/GitLabApiAlg.scala index e062f14005..391c39024a 100644 --- a/modules/core/src/main/scala/org/scalasteward/core/forge/gitlab/GitLabApiAlg.scala +++ b/modules/core/src/main/scala/org/scalasteward/core/forge/gitlab/GitLabApiAlg.scala @@ -16,6 +16,7 @@ package org.scalasteward.core.forge.gitlab +import cats.effect.Temporal import cats.{MonadThrow, Parallel} import cats.syntax.all._ import io.circe._ @@ -31,6 +32,8 @@ import org.scalasteward.core.util.uri.uriDecoder import org.scalasteward.core.util.{intellijThisImportIsUsed, HttpJsonClient, UnexpectedResponse} import org.typelevel.log4cats.Logger +import scala.concurrent.duration.{Duration, DurationInt} + final private[gitlab] case class ForkPayload(id: String, namespace: String) final private[gitlab] case class MergeRequestPayload( id: String, @@ -162,7 +165,8 @@ final class GitLabApiAlg[F[_]: Parallel]( )(implicit client: HttpJsonClient[F], logger: Logger[F], - F: MonadThrow[F] + F: MonadThrow[F], + temporal: Temporal[F] ) extends ForgeApiAlg[F] { import GitLabJsonCodec._ @@ -205,14 +209,26 @@ final class GitLabApiAlg[F[_]: Parallel]( def waitForMergeRequestStatus( number: PullRequestNumber, - retries: Int = 10 + retries: Int = 10, + initialDelay: Duration = 100.milliseconds, + backoffMultiplier: Double = 2.0 ): F[MergeRequestOut] = client .get[MergeRequestOut](url.existingMergeRequest(repo, number), modify(repo)) .flatMap { case mr if mr.mergeStatus =!= GitLabMergeStatus.Checking => F.pure(mr) - case _ if retries > 0 => waitForMergeRequestStatus(number, retries - 1) - case other => F.pure(other) + case _ if retries > 0 => + temporal.sleep(initialDelay) >> waitForMergeRequestStatus( + number, + retries - 1, + initialDelay * backoffMultiplier + ) + case other => + logger + .warn( + s"Exhausted all retires while waiting for merge request status. Last known status is ${other.mergeStatus}" + ) + .as(other) } val updatedMergeRequest = From 8c143425e5f321bd8fb0f101bcd3b136980450ad Mon Sep 17 00:00:00 2001 From: Ender Tunc Date: Thu, 16 Mar 2023 14:55:15 +0100 Subject: [PATCH 2/3] add logs about retry attempts --- .../org/scalasteward/core/forge/gitlab/GitLabApiAlg.scala | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/modules/core/src/main/scala/org/scalasteward/core/forge/gitlab/GitLabApiAlg.scala b/modules/core/src/main/scala/org/scalasteward/core/forge/gitlab/GitLabApiAlg.scala index 391c39024a..8862b6bb73 100644 --- a/modules/core/src/main/scala/org/scalasteward/core/forge/gitlab/GitLabApiAlg.scala +++ b/modules/core/src/main/scala/org/scalasteward/core/forge/gitlab/GitLabApiAlg.scala @@ -218,7 +218,10 @@ final class GitLabApiAlg[F[_]: Parallel]( .flatMap { case mr if mr.mergeStatus =!= GitLabMergeStatus.Checking => F.pure(mr) case _ if retries > 0 => - temporal.sleep(initialDelay) >> waitForMergeRequestStatus( + logger.info( + s"Merge request is still in '${GitLabMergeStatus.Checking}' state. We will check merge request status in $initialDelay again. " + + s"Remaining retries count is $retries" + ) >> temporal.sleep(initialDelay) >> waitForMergeRequestStatus( number, retries - 1, initialDelay * backoffMultiplier @@ -226,7 +229,7 @@ final class GitLabApiAlg[F[_]: Parallel]( case other => logger .warn( - s"Exhausted all retires while waiting for merge request status. Last known status is ${other.mergeStatus}" + s"Exhausted all retires while waiting for merge request status. Last known status is '${other.mergeStatus}'" ) .as(other) } From 9a99f9d09ce13447ea0640af28520576ec998ba6 Mon Sep 17 00:00:00 2001 From: Ender Tunc Date: Fri, 24 Mar 2023 19:37:32 +0100 Subject: [PATCH 3/3] address pull request feedback --- .../core/forge/ForgeSelection.scala | 2 +- .../core/forge/gitlab/GitLabApiAlg.scala | 17 ++++++++--------- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/modules/core/src/main/scala/org/scalasteward/core/forge/ForgeSelection.scala b/modules/core/src/main/scala/org/scalasteward/core/forge/ForgeSelection.scala index f52ffe18c7..e53fe350b2 100644 --- a/modules/core/src/main/scala/org/scalasteward/core/forge/ForgeSelection.scala +++ b/modules/core/src/main/scala/org/scalasteward/core/forge/ForgeSelection.scala @@ -43,7 +43,7 @@ object ForgeSelection { )(implicit httpJsonClient: HttpJsonClient[F], logger: Logger[F], - temporal: Temporal[F] + F: Temporal[F] ): ForgeApiAlg[F] = { val auth = (_: Any) => authenticate(forgeCfg.tpe, user) forgeSpecificCfg match { diff --git a/modules/core/src/main/scala/org/scalasteward/core/forge/gitlab/GitLabApiAlg.scala b/modules/core/src/main/scala/org/scalasteward/core/forge/gitlab/GitLabApiAlg.scala index 8862b6bb73..8ec4d09efc 100644 --- a/modules/core/src/main/scala/org/scalasteward/core/forge/gitlab/GitLabApiAlg.scala +++ b/modules/core/src/main/scala/org/scalasteward/core/forge/gitlab/GitLabApiAlg.scala @@ -17,7 +17,7 @@ package org.scalasteward.core.forge.gitlab import cats.effect.Temporal -import cats.{MonadThrow, Parallel} +import cats.Parallel import cats.syntax.all._ import io.circe._ import io.circe.generic.semiauto._ @@ -165,8 +165,7 @@ final class GitLabApiAlg[F[_]: Parallel]( )(implicit client: HttpJsonClient[F], logger: Logger[F], - F: MonadThrow[F], - temporal: Temporal[F] + F: Temporal[F] ) extends ForgeApiAlg[F] { import GitLabJsonCodec._ @@ -217,21 +216,21 @@ final class GitLabApiAlg[F[_]: Parallel]( .get[MergeRequestOut](url.existingMergeRequest(repo, number), modify(repo)) .flatMap { case mr if mr.mergeStatus =!= GitLabMergeStatus.Checking => F.pure(mr) - case _ if retries > 0 => + case mr if retries > 0 => logger.info( - s"Merge request is still in '${GitLabMergeStatus.Checking}' state. We will check merge request status in $initialDelay again. " + + s"Merge request is still in '${mr.mergeStatus}' state. We will check merge request status in $initialDelay again. " + s"Remaining retries count is $retries" - ) >> temporal.sleep(initialDelay) >> waitForMergeRequestStatus( + ) >> F.sleep(initialDelay) >> waitForMergeRequestStatus( number, retries - 1, initialDelay * backoffMultiplier ) - case other => + case mr => logger .warn( - s"Exhausted all retires while waiting for merge request status. Last known status is '${other.mergeStatus}'" + s"Exhausted all retries while waiting for merge request status. Last known status is '${mr.mergeStatus}'" ) - .as(other) + .as(mr) } val updatedMergeRequest =