Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor MapboxTimer and Faster Route #2575

Merged
merged 1 commit into from
Mar 13, 2020
Merged

Conversation

kmadsen
Copy link
Contributor

@kmadsen kmadsen commented Mar 11, 2020

Description

Route Refresh is similar to Faster Route. After working on both of them some, I'm adding an incremental improvement. https://github.com/mapbox/navigation-sdks/issues/215

Would like to use this with Route Refresh #2570

  • I have added any issue links
  • I have added all related labels (bug, feature, new API(s), SEMVER, etc.)
  • I have added the appropriate milestone and project boards

Implementation

  • Make MapboxTimer tests simulate time rather than delay actual time
  • Remove faster route interval from NavigationOptions
    -- Configurations here break customers downstream
    -- Configurations here are immutable, this is making it mutable
  • Make MapboxTimer intervals mutable, we want to be able to safely change it whenever we want

Testing

Please describe the manual tests that you ran to verify your changes

  • I have tested locally (including SNAPSHOT upstream dependencies if needed) through testapp/demo app and run all activities to avoid regressions
  • I have tested via a test drive, or a simulation/mock location app
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes

Checklist

  • My code follows the style guidelines of this project
  • I have performed a self-review of my own code
  • I have updated the CHANGELOG including this PR

cc: @abhishek1508 @olegzil @Guardiola31337

@@ -195,48 +190,18 @@ class MapboxNavigationTest {
verify(exactly = 1) { tripSession.unregisterAllVoiceInstructionsObservers() }
}

@Test
fun fasterRoute_timerStarted() {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Faster route and route refresh are not required for navigation. Move this to be tested independently

@codecov-io
Copy link

codecov-io commented Mar 11, 2020

Codecov Report

Merging #2575 into master will not change coverage.
The diff coverage is n/a.

@@            Coverage Diff            @@
##             master    #2575   +/-   ##
=========================================
  Coverage     29.16%   29.16%           
  Complexity     1061     1061           
=========================================
  Files           281      281           
  Lines         10731    10731           
  Branches        870      870           
=========================================
  Hits           3130     3130           
  Misses         7258     7258           
  Partials        343      343


@Test
fun multipleStartCalls_doNotExecuteMultipleJobs() = runBlocking {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This test is not applicable to everything that has a MapboxTimer.

Moving this logic so it can be handled by FasterRoute
#2577

@abhishek1508
Copy link
Contributor

@kmadsen I looked at the PR, but I was curious as to why did we remove the configuration where the client can decide how often he wants the SDK to request faster route. Also I am not sure if making the MapboxTimer polling rate mutable. This can be easily misused intentionally/unintentionally.

@kmadsen
Copy link
Contributor Author

kmadsen commented Mar 12, 2020

I was curious as to why did we remove the configuration where the client can decide how often he wants the SDK to request faster route. Also I am not sure if making the MapboxTimer polling rate mutable. This can be easily misused intentionally/unintentionally.

@abhishek1508 I noticed the faster route configuration in the constructor when it made the driver app require a migration to support a new sdk version. Also, when it is in the constructor customers have to decide their interval rate once and for all when compiling/initializing.

Many companies have server side configurations, where they can control their knobs at runtime. This is why I'm moving things to be mutable at runtime.

@kmadsen
Copy link
Contributor Author

kmadsen commented Mar 12, 2020

Also I am not sure if making the MapboxTimer polling rate mutable. This can be easily misused intentionally/unintentionally.

@abhishek1508 I'm unable to share this concern at this point. MapboxTimer calls a delay. Before this change, a customer could accidentally set the FasterRoute to seconds instead of milliseconds. Creating a polling loop that is 1000x faster than expected. My bigger concern is giving customers direct access to the polling loop.

Copy link
Contributor

@Guardiola31337 Guardiola31337 left a comment

Choose a reason for hiding this comment

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

Left a couple of minor comments / questions. Other than that this looks good to me @kmadsen 👍


private val timerJob: Job by lazy {
mainControllerJobScope.scope.launch {
var routeRefreshInterval = TimeUnit.MINUTES.toMillis(1)
Copy link
Contributor

Choose a reason for hiding this comment

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

If this is a "generic" timer, shouldn't we use a more abstract naming? 🤔 Also in this particular case it's route refresh is confusing because we already have the concept (feature) of route refresh 😅 The same thing happens to startRouteRefresh 👇 What do you think?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's still a MapboxTimer, not a EveryoneTimer. This class is only used to update traffic routes, tend to make things more specific at the beginning. When it's used in more places it could become more abstract.

But actually, this topic is out of scope of the refactor I'm doing so will go back to the original name

MapboxTimer(100L, testLambda).start()
delay(220)
@Test
fun `should not call before interval`() = coroutineRule.runBlockingTest {
Copy link
Contributor

Choose a reason for hiding this comment

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

NIT Normally is good to structure the tests following the triple A 👀 https://speakerdeck.com/guardiola31337/elegant-unit-testing-mobilization-2016?slide=40 http://wiki.c2.com/?ArrangeActAssert
If the Arrange part gets too long we should create factory or builder methods.

The same thing applies to the rest of the tests 👇

Copy link
Contributor Author

Choose a reason for hiding this comment

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

updated the whitespace, is more AAA now. Arrange is setting the timer interval, so only a single line

@kmadsen kmadsen force-pushed the km-update-mapbox-timer branch 4 times, most recently from ba6799c to fab3dcd Compare March 13, 2020 16:02
Copy link
Contributor

@Guardiola31337 Guardiola31337 left a comment

Choose a reason for hiding this comment

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

Minor comment not blocking the PR 🚀

mapboxTimer.restartAfter = TimeUnit.MINUTES.toMillis(5)

// Should emit 1
val job1 = mapboxTimer.startTimer(mockLambda)
Copy link
Contributor

Choose a reason for hiding this comment

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

NIT not a big fan of naming like this job1, job2, etc. 😬 but not a big deal, could we come with a better name?

Copy link
Contributor Author

@kmadsen kmadsen Mar 13, 2020

Choose a reason for hiding this comment

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

hmm yeah i'm typically not either but this 1 means first. not sure if i rename it to first, if that seems passive to your comment. would you have a suggestion?

  • firstJob, secondJob
  • jobFirst, jobSecond
  • firstTimerJob, secondTimerJob

Copy link
Contributor

Choose a reason for hiding this comment

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

firstJob, secondJob

Sounds good to me 🚀


private val timerJob: Job by lazy {
mainControllerJobScope.scope.launch {
var restartAfter = TimeUnit.MINUTES.toMillis(1)
Copy link
Contributor

Choose a reason for hiding this comment

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

Should we rename it to restartAfterMillis or smth like it to show info about used time unit in variable name? wdyt?

Copy link
Contributor Author

@kmadsen kmadsen Mar 13, 2020

Choose a reason for hiding this comment

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

i'm also a fan of putting units on all the variables with units

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah that's a good point. Great catch!

@kmadsen kmadsen merged commit d06ed3b into master Mar 13, 2020
@kmadsen kmadsen deleted the km-update-mapbox-timer branch March 13, 2020 18:45
@kmadsen kmadsen mentioned this pull request Mar 25, 2020
10 tasks
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.

5 participants