Skip to content

Comments

Bugfix/strava limit#4

Open
b3b00 wants to merge 5 commits intoorium:masterfrom
b3b00:bugfix/strava-limit
Open

Bugfix/strava limit#4
b3b00 wants to merge 5 commits intoorium:masterfrom
b3b00:bugfix/strava-limit

Conversation

@b3b00
Copy link

@b3b00 b3b00 commented Sep 13, 2018

No description provided.

@b3b00
Copy link
Author

b3b00 commented Sep 20, 2018

@orium did you see my pull-request ?

@orium
Copy link
Owner

orium commented Sep 20, 2018

Sorry @b3b00, I didn't yet :/ I will take a look later today.

Copy link
Owner

@orium orium left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR. I have some suggestions on how to improve things. If you need some extra mentoring let me know, I'm happy to help :)

import scala.util.control.NonFatal
import java.util._

class StravaRateLimiter(isRateLimitExceeded : Throwable => Boolean) extends RateLimiter(isRateLimitExceeded) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't need to replicate so much of this logic.

I think we can have some sort of parameterizeble backup strategy. For instance, we can have something an ADT like:

sealed trait BackoffStrategy
object BackoffStrategy {
  case class ExponentialBackoff(startBackoff: Duration, exponent: Double = 2.0) extends BackoffStrategy
  case class ConstantBackoff(backoff: Duration) extends BackoffStrategy
}

This way we wouldn't need a StravaRateLimiter and RateLimiter would receive a BackoffStrategy. E.g.

object RateLimiter {
  ...

  def byException[T <: Throwable: ClassTag]: RateLimiter =
    new RateLimiter(exceptionCausedBy[T], BackoffStrategy.ExponentialBackoff(startBackoff = 1.minute, exponent = 2.0))

  def byExceptionForStrava[T <: Throwable: ClassTag]: RateLimiter =
    new RateLimiter(exceptionCausedBy[T], BackoffStrategy.ConstantBackoff(startBackoff = 15.minutes))
}

We could still have the nice message saying that we are waiting x time, and will resume at y. Also, to print that message you do some math and manual formatting. There are methods that can help you with that (e.g. take a look at Instant (where you can do math with durations) and Duration).

Copy link
Author

@b3b00 b3b00 Sep 21, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the constantbackoff is not optimal as you will always wait for 15 minutes even thiugh you may only need 1 minute if the exception occurs let say at 03:14 and rate limit will be reset at 3:15 as strava API states. So we must have some specific logic here. Strava rate limits are very specific I have never seen such conditions in other API.

so the constantbackoff must be renamed as the baxkoff is not constant at all.

I will try to provide a refactoring using a strategy pattern approach.

I agree for the flrmatting part.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, it can be a BackoffStrategy.StravaBackoff or something like that :)

val datetime = LocalDateTime.parse(activity.start_date, DateTimeFormatter.ISO_DATE_TIME)

Some(Run(activity.id, datetime, times, distances))
val run = Run(activity.id, datetime, times, distances)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not the best place to do this. The function that populates the cache is Strava.populateRunCache. I think easiest approach might be to just catch exceptions when fetching runs, logging them, and move on.

The fetch is done here:

val r = fetchRunActivity(id).flatMap(activityToRun)

We can put a try { ... } catch { .. } and log that we failed to fetch a run. To report the error add another parameter to the function like the reportFetch (a reportFetchError I guess). This will it abstracted away from the output.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you are right. my proposal was a first draft.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants