Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 5 additions & 38 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,43 +1,10 @@
name: CI

on: [push, pull_request]
on:
push:
branches: [ master ]
pull_request:

jobs:
test:

runs-on: ubuntu-latest

strategy:
matrix:
scala:
- 2.13.14
- 2.12.19
- 3.3.3

steps:
- uses: actions/checkout@v2

- uses: coursier/cache-action@v6

- name: scala
uses: olafurpg/setup-scala@v11
with:
java-version: openjdk@1.11

- name: build ${{ matrix.scala }}
run: sbt ++${{ matrix.scala }} clean coverage test

- name: test coverage
if: success()
env:
COVERALLS_REPO_TOKEN: ${{ secrets.GITHUB_TOKEN }}
COVERALLS_FLAG_NAME: Scala ${{ matrix.scala }}
run: sbt ++${{ matrix.scala }} coverageReport coverageAggregate coveralls

- name: slack
uses: homoluctus/slatify@master
if: failure() && github.ref == 'refs/heads/master'
with:
type: ${{ job.status }}
job_name: Build
url: ${{ secrets.SLACK_WEBHOOK }}
uses: evolution-gaming/scala-github-actions/.github/workflows/ci.yml@dde27b9bd793d41d5aacf8fb74403c9de5da1146 # v6.3.0
10 changes: 5 additions & 5 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
name: Publish new Release
name: Publish Release

on:
release:
types: [published]
branches: [master]
push:
tags:
- 'v*'

jobs:
release:
uses: evolution-gaming/scala-github-actions/.github/workflows/release.yml@v1
uses: evolution-gaming/scala-github-actions/.github/workflows/release.yml@v5
secrets: inherit
96 changes: 96 additions & 0 deletions .scalafmt.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
# Main goals:
# - nicer commit diffs (trailing commas, no alignment for pattern matching, force new lines)
# - better interop with default IntelliJ IDEA setup (matching import and modifiers sorting logic)
# - better developer experience on laptop screens (like 16' MBPs) with IntelliJ IDEA (line wraps)

version = 3.11.5

runner.dialect = scala213source3

# only format files tracked by git
project.git = true

maxColumn = 120
trailingCommas = always

preset = default
# do not align to make nicer commit diffs
align.preset = none

indent {
# altering defnSite and extendSite to have this:
# final class MyErr extends RuntimeException(
# "super error message",
# )
# instead of this:
# final class MyErr extends RuntimeException(
# "super error message",
# )
defnSite = 2
extendSite = 0
}

spaces {
# makes string interpolation with curlies more visually distinct
inInterpolatedStringCurlyBraces = true
}

newlines {
# keep author new lines where possible
source = keep
# force new line after "(implicit" for multi-line arg lists
implicitParamListModifierForce = [after]
avoidForSimpleOverflow = [
tooLong, # if the line would be too long even after newline inserted, do nothing
slc, # do nothing if overflow caused by single line comment
]
}

verticalMultiline {
atDefnSite = true
arityThreshold = 4 # more than 3 args in a list will be turned vertical
newlineAfterOpenParen = true # for nicer commit diffs
}

# for nicer commit diffs - forces new line before last parenthesis:
# class MyCls(
# arg1: String,
# arg2: String,
# ) extends MyTrait {
#
# without it:
# class MyCls(
# arg1: String,
# arg2: String) extends MyTrait {
danglingParentheses.exclude = []

docstrings {
# easier to view diffs in IDEA on 16' MBP screen if docs max line are shorter than code
wrapMaxColumn = 100
# next settings make it similar to the default IDEA javadoc formatting
style = Asterisk
oneline = unfold
blankFirstLine = unfold
}

rewrite.rules = [
Imports,
RedundantParens,
SortModifiers,
prefercurlyfors,
]

# put visibility modifier first
rewrite.sortModifiers.preset = styleGuide

# Import sorting as similar as possible to scalafix's "OrganizeImports.preset = INTELLIJ_2020_3".
# Scalafix is not used as its commands mess up "all .." build aliases and it takes long time to run,
# while its code semantic based features are not needed here.
# I.e. detection of unused imports is done with Scala compiler options.
rewrite.imports {
sort = ascii
groups = [
[".*"],
["java\\..*", "javax\\..*", "scala\\..*"],
]
}
24 changes: 13 additions & 11 deletions build.sbt
Original file line number Diff line number Diff line change
@@ -1,37 +1,39 @@
import Dependencies._
import Dependencies.*
import sbtversionpolicy.Compatibility.BinaryCompatible

name := "retry"

organization := "com.evolutiongaming"

homepage := Some(url("https://github.com/evolution-gaming/retry"))
homepage := Some(uri("https://github.com/evolution-gaming/retry"))

startYear := Some(2019)

organizationName := "Evolution"

organizationHomepage := Some(url("https://evolution.com"))
organizationHomepage := Some(uri("https://evolution.com"))

publishTo := Some(Resolver.evolutionReleases)

scalaVersion := crossScalaVersions.value.head

crossScalaVersions := Seq("2.13.14", "2.12.19", "3.3.3")
crossScalaVersions := Seq("2.13.18", "3.3.8")

libraryDependencies ++= Seq(
`cats-effect`,
`cats-helper`,
random,
scalatest % Test)
scalatest % Test,
)

licenses := Seq(("MIT", url("https://opensource.org/licenses/MIT")))

releaseCrossBuild := true
licenses := Seq(("MIT", uri("https://opensource.org/licenses/MIT")))

Compile / doc / scalacOptions ++= Seq("-groups", "-implicits", "-no-link-warnings")

ThisBuild / versionScheme := Some("early-semver")

//addCommandAlias("check", "all versionPolicyCheck Compile/doc")
addCommandAlias("check", "show version")
addCommandAlias("build", "+all compile test")
ThisBuild / versionPolicyIntention := BinaryCompatible

addCommandAlias("check", "show versionPolicyCheck scalafmtCheckRepo Compile/doc")
addCommandAlias("fmt", "scalafmtRepo")
addCommandAlias("build", "+all compile testFull")
8 changes: 4 additions & 4 deletions project/Dependencies.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import sbt._

object Dependencies {

val scalatest = "org.scalatest" %% "scalatest" % "3.2.19"
val `cats-helper` = "com.evolutiongaming" %% "cats-helper" % "3.10.3"
val random = "com.evolution" %% "random" % "1.0.4"
val `cats-effect` = "org.typelevel" %% "cats-effect" % "3.4.11"
val scalatest = "org.scalatest" %% "scalatest" % "3.2.20"
val `cats-helper` = "com.evolutiongaming" %% "cats-helper" % "3.12.2"
val random = "com.evolution" %% "random" % "1.0.4"
val `cats-effect` = "org.typelevel" %% "cats-effect" % "3.7.0"
}
2 changes: 1 addition & 1 deletion project/build.properties
Original file line number Diff line number Diff line change
@@ -1 +1 @@
sbt.version=1.11.4
sbt.version = 2.0.6
12 changes: 6 additions & 6 deletions project/plugins.sbt
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
addSbtPlugin("org.scoverage" % "sbt-scoverage" % "2.0.12")
addSbtPlugin("org.scoverage" % "sbt-scoverage" % "2.4.4")

addSbtPlugin("org.scoverage" % "sbt-coveralls" % "1.3.15")

addSbtPlugin("com.github.sbt" % "sbt-release" % "1.4.0")
addSbtPlugin("com.github.sbt" % "sbt-dynver" % "5.1.1")

addSbtPlugin("com.evolution" % "sbt-scalac-opts-plugin" % "0.2.0")

addSbtPlugin("com.evolution" % "sbt-artifactory-plugin" % "0.0.2")
addSbtPlugin("com.evolution" % "sbt-artifactory-plugin" % "0.1.2")

addSbtPlugin("ch.epfl.scala" % "sbt-version-policy" % "3.3.0")

addSbtPlugin("com.typesafe" % "sbt-mima-plugin" % "1.1.4")
addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.6.2")
6 changes: 2 additions & 4 deletions src/main/scala/com/evolutiongaming/retry/Decision.scala
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,15 @@ object Decision {

def giveUp: Decision = GiveUp


final case class Retry(delay: FiniteDuration, status: Status, strategy: Strategy) extends Decision

case object GiveUp extends Decision


implicit class StrategyDecisionOps(val self: Decision) extends AnyVal {

def flatMap(f: Retry => Decision): Decision = {
self match {
case Decision.GiveUp => Decision.giveUp
case Decision.GiveUp => Decision.giveUp
case a: Decision.Retry => f(a)
}
}
Expand All @@ -33,4 +31,4 @@ object Decision {
self.flatMap { a => a.copy(strategy = f(a.strategy)) }
}
}
}
}
38 changes: 17 additions & 21 deletions src/main/scala/com/evolutiongaming/retry/OnError.scala
Original file line number Diff line number Diff line change
Expand Up @@ -14,34 +14,32 @@ trait OnError[F[_], A] {

object OnError {

def empty[F[_] : Applicative, A]: OnError[F, A] = (_, _, _) => ().pure[F]
def empty[F[_]: Applicative, A]: OnError[F, A] = (_, _, _) => ().pure[F]


def apply[F[_] : Applicative](f: Throwable => F[Unit]): OnError[F, Throwable] = {
def apply[F[_]: Applicative](f: Throwable => F[Unit]): OnError[F, Throwable] = {
(error: Throwable, _: Retry.Status, decision: Decision) =>
decision match {
case OnError.Decision.Retry(_) => f(error)
case OnError.Decision.GiveUp => ().pure[F]
case OnError.Decision.GiveUp => ().pure[F]
}
}


def fromLog[F[_]](log: Log[F]): OnError[F, Throwable] = {
(error: Throwable, status: Retry.Status, decision: Decision) => {

decision match {
case OnError.Decision.Retry(delay) =>
log.warn(s"failed, retrying in $delay, error: $error", error)

case OnError.Decision.GiveUp =>
val retries = status.retries
val duration = status.delay
log.error(s"failed after $retries retries within $duration: $error", error)
(error: Throwable, status: Retry.Status, decision: Decision) =>
{

decision match {
case OnError.Decision.Retry(delay) =>
log.warn(s"failed, retrying in $delay, error: $error", error)

case OnError.Decision.GiveUp =>
val retries = status.retries
val duration = status.delay
log.error(s"failed after $retries retries within $duration: $error", error)
}
}
}
}


sealed abstract class Decision extends Product

object Decision {
Expand All @@ -50,17 +48,15 @@ object OnError {

def giveUp: Decision = GiveUp


def apply(decision: StrategyDecision): Decision = {
decision match {
case StrategyDecision.Retry(delay, _, _) => Decision.retry(delay)
case StrategyDecision.GiveUp => Decision.giveUp
case StrategyDecision.GiveUp => Decision.giveUp
}
}


final case class Retry(delay: FiniteDuration) extends Decision

case object GiveUp extends Decision
}
}
}
Loading