softwaremill / retry Goto Github PK
View Code? Open in Web Editor NEWbecause you should never give up, at least not on the first try
Home Page: https://softwaremill.com/open-source
License: MIT License
because you should never give up, at least not on the first try
Home Page: https://softwaremill.com/open-source
License: MIT License
Direct policy retries one more time than specified. There is test which shows that:
it ("should deal with future failures") {
implicit val success = Success.always
val policy = retry.Directly(3)
val counter = new AtomicInteger()
val future = policy { () =>
counter.incrementAndGet()
Future.failed(new RuntimeException("always failing"))
}
Await.ready(future, Duration.Inf)
assert(counter.get() === 4)
}
In documentation there is
// retry 4 times
val future = retry.Directly(4) {
attempt
}
which is inconsistent with test
I found retry 0.2.1 is available on maven central. Though 0.2.1 tag is not found on this repository. Can we use it?
I prefer maven central to a library specific repository. I'd happy if I can use .jars on maven central.
This code doesn't compile on scala 2.11 library version 0.2.1
implicit val ec = ExecutionContext.global
implicit val success: Success[String] = Success[String](_.isEmpty)
implicit val format: Formats = DefaultFormats
implicit val timer = odelay.jdk.JdkTimer.newTimer
retry.Backoff(4, 1.second) {
Future {
""
}
}
though this does
val withBackOff: Policy = retry.Backoff(4, 1.second)
withBackOff {
Future {
""
}
}
is the readme just out of date?
Is it ok to store the Policy as a instance variable and invoke it multiple times with the closure. I think i actually prefer it this way as its more readable but none of the examples seem to work like this
One final bit of feedback is why do you require the user to wrap the operation in a future, couldnt you accept any T and wrap it in a futre internally
Hello and thank you for this library! Is it still maintained? I have the following suggestion:
Am I right that there is no way to know how many retries where made? This information is lost. I suppose it could be useful if retry functions return something like RetryStatus
from Soostone/retry Haskell library.
at the moment, this version is api compatible with dispatches embedded retry library. One feature request that I expect will pop soon is the ability for the function that returns the future to somehow "know" about the context of execution with respect to the retry and or have the ability to inform the retry attempt. I think something like this could be doable with an implicit environment exposing the retry information. Alternatively we can try to do this more explicitly by expose a fold
ing interface
retry.Policy.fold(init)(params)((last) => next)
The semantics of this would be to make the function passed to retry act like a catamophism over the last failed attempt. Needs so more thought but just jotting this down to track ideas for now.
like so
val a = new Success[T](...)
val b = new Success[T](...)
a.or(b) // == new Success[T](v => a.predicate(v) || b.predicate(v))
a.or(const) // == new Success[T](a.predicate(_) || const)
a.and(b) // == new Success[T](v => a.predicate(v) && b.predicate(v))
Without an implicit success it says
Cannot find an implicit retry.Success for the given type of Future, either require one yourself or import retry.Success._
however even after importing retry.Success._
nothing changes, is there a simple way to say a future is successful in every case it doesn't fail (e.g. is handled with recover)?
Defaults.jitter throws NullPointerException when apply()
java.lang.NullPointerException:
at retry.Jitter$$anon$2.next(Jitter.scala:99)
at retry.Jitter.apply(Jitter.scala:14)
at retry.Jitter.apply$(Jitter.scala:10)
at retry.Jitter$$anon$2.apply(Jitter.scala:93)
Hi, I am trying to implement retry with backoff for a function which return postgres connection but i am keep getting error not found: type Success in Intellij IDE. Please see the code below and let me know what i am missing to make this code compile. Thanks
import retry.Success
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration._
import scala.concurrent.Future
def getPostgresConnectionRetry(jdbcUrl: String, connectionProperties: Properties, processName: String, customerId: String): Future[Connection] = {
implicit val nonNullResponse: Connection = Success[Connection](conn => conn != null)
retry.Backoff(NUM_RETRIES, INITIAL_RETRY_AFTER).apply(() =>
Future[Connection] {
try {
DriverManager.getConnection(jdbcUrl, connectionProperties)
}
catch {
case e: Throwable =>
LOG.error(s"Error while connecting to postgres for customerId; $customerId, processName: $processName. Error: ${e.getMessage}")
throw e
}
}
)
}
The Connection is of type java.sql.connection.
Thanks
I have a method that I want to retry that could result in multiple exceptions. Only one of them I want to retry on the other ones I want to consider as a success and throw that exception.
The Success condition for the Policy is only checked within a .map
of the future being evaluated so a failed future will always result in a retry.
Is there a way to only retry on certain failures without having to wrap the content of the futures in a Try or Either?
This library looks great. Unfortunately lack of full examples is makes working with it quite difficult. Uncomplete code faragments are not helpfull.
For example:
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future
retry.Backoff()(Future {
// something that can "fail"
})
produce
Multiple markers at this line
- type mismatch; found : scala.concurrent.Future[Int] required:
odelay.Timer
- type mismatch; found : scala.concurrent.Future[Unit] required:
odelay.Timer
or
val future = retry.Directly(4) {
attempt
}
Leads to type mismatch; found : X required: () => scala.concurrent.Future[?]
Could you provide some simple but full examples of usage? With:
Scala 2.13 support ๐๐ผ
I was looking through the codebase and didn't find(maybe just search not thourough enough) an option to set a value which will be used to calculate an addition to delay
using randomness. In retry.JitterBackoff
I noticed that it uses delay itself for such puprose.
What I mean is following...
Here is the definition of Backoff's apply:
def apply(max: Int = 8, delay: FiniteDuration = Defaults.delay, base: Int = 2)
. So retry.Backoff(3, 1.second)
means that 1st retry will be exactly after 1 second, 2nd retry after 2 seconds, and 3rd retry after 4 seconds.
What I want to achieve is next: 1st retry after (1 + random(0, N))
second, 2nd retry after 2*(1 + random(0, N)) + random(0, N)
seconds, and 3rd retry after 2*( 2*(1 + random(0, N)) + random(0, N) ) + random(0, N)
seconds.
There is a JitterBackoff
but seems for aformentioned N
it uses initial delay
value.
Is such functionality supported?
PS. I'm neglacting cap
here
retry 0.2.1 depends on odelay-core 0.1.0 which doesn't exist on maven central.
Please release a new version which depends on odelay-core 0.1.1 on maven central.
Hi,
Currently the Success
object provides default Success
implicits for various standard types:
implicit def either[A,B]: Success[Either[A,B]] =
Success(_.isRight)
implicit def option[A]: Success[Option[A]] =
Success(!_.isEmpty)
implicit def tried[A]: Success[Try[A]] =
Success(_.isSuccess)
These are available even without explicit import. I found that this can lead to unintentional retries when forgetting to add your own implicit Success
value.
For example, when querying a database I have a result type of Future[Option[???]]
, where an empty Option
stands for a missing value in the database. In some use cases, this is a legitimate return value, and retrying the query won't change anything.
The correct behavior here would be to explicitly have:
implicit val always = Success.always
in scope.
But if you forget to add this line, everything still compiles and the option
implicit from the Success
object is picked up, leading to unwanted retries.
I would suggest removing the implicit
modifier from def
s above to avoid the unintentional retries.
Thanks
Would you be open to a PR to support Scala 3 ?
I would happily work on it if you tell me it can be merged and published.
this
should be something more like
@implicitNotFound(
"Cannot find an implicit retry.Success for the given type of Future[${T}], either require one yourself or import retry.Success._")
I'm not sure why but I'm getting an extra call to my promise
Looks like the retry is occurring correctly since logged "Retrying request" matches my retry attempt.
The last attempt is the one that looks extraneous. Would you be able to advise why?
Therefore if I use Directly(1) I'm seeting my request sent 3 times instead of 2.
def sendWithRetry[U](promise: => Future[U], retryPolicy: retry.Policy): Future[U] = {
val retryOnSpecifiedFailurePolicy = retry.When {
case CustomException() =>
logger.warn("Retrying request...")
retryPolicy
}
retryOnSpecifiedFailurePolicy(promise)
}
I'm calling the above like this
sendWithRetry(send(message), retry.Directly(1))
and I have this defined in class scope
implicit val always: retry.Success[Any] = retry.Success.always
Thanks for a great library!
Would you be open to a PR that allowed policies to take Future[T]
s by-name? This would be in addition to the () => Future[T]
option offered now.
This would let clients write:
retry.Directly(3) { attemptSomething() }
instead of
retry.Directly(3) { () => {
attemptSomething()
}}
I believe I can do this with a small addition to the Policy
trait and with no breaking changes.
the timer modules really only private timer implementations and have little to nothing to do with retry behavior but rather delayed execution. After odelay is published this library should depend on that instead.
How can I do graceful shutdown using this library? Say I have some code that is doing retry on some HTTP call. Then the application starts shutting down. Can I somehow register that this should be gracefully shut down?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.