Plant a MultiTriggerBomb
The final time you have been in a state of affairs the place you wanted to stop (not anticipate) the execution of a code till
n circumstances have been true, or see what occurred if the
n circumstances didn’t turn into true and execute the code anyway after a deadline is expired — how did you remedy the issue?
The primary answer that involves thoughts once you take a look at this downside is Java’s
CountDownLatch. Countdown latch has an
await() name that makes the calling thread wait till
n variety of
countDowns() are known as. Right here, we don’t want the thread to attend. It’s extra like we’re utilizing the appliance and when ’
n’ occasions occur, we hearth a chunk of code, or if a deadline is overridden, we execute the code in any case.
The requirement is that the circumstances can turn into true on a number of threads, however we now have to make sure that the code mustn’t execute greater than as soon as. We’ve to deal with the case when timer expiration and situation matching occurs on the identical time and ensure it doesn’t hearth the code a number of instances or get into an unstable state.
We will construct an answer by utilizing if-else checks and booleans to keep up the states of the circumstances. However, we encounter these sorts of conditions a number of instances whereas working at Microsoft Groups. So, that’s not scalable, and it’s susceptible to errors.
One instance might be that we wish to stop some non-critical piece of code (reminiscent of prefetch photographs, refreshing auth tokens, obtain person avatars, and so on.) till some vital code paths are accomplished(some vital paths are, 1. Display screen will get rendered, 2. The message depend has up to date, and 3. Present display has completed syncing) that’s tracked as vital OKRs of the app and impression total app efficiency. So principally we maintain on different items of labor until 1,2 and, 3 are finished. And what if some errors floor out and one or the entire steps fail to occur, then the timeout helps us executing the code.
In case your calls are tied to lifecycle callbacks of android, we now have construct a assemble known as
LazyLifecycleCallbacks, which you can test right here, that has
onLazyResume().We’ve constructed this assemble utilizing an idea known as
Barrier, however quickly realised that
barrier has its limitations so we re-implemented it utilizing
Coming again to the subject, we wanted one thing generic that may work on a number of circumstances, is thread secure, and will be onboarded by builders simply. Furthermore, is correctly examined in order that we will belief the performance.
This use case seemed like a multi-trigger bomb. A bomb has a number of triggers to be pressed earlier than the bomb is exploded and has a timer hooked up to it. It appears to be like one thing like this:
* | |
* | [s1] --- [s2] --- [s3] ---[s4] --- [s5] --- | ----> [CHARGE]
* | | ^
* |------------|----------------------------------| |
* | |
* |________________t seconds__________________|
I felt it might be nice if I could make an API floor that will look much like an actual bomb’s method of interplay. Builders will be capable to simply relate to it and a brand new jargon shall be launched to unravel this sort of downside. So the uncovered APIs have been the next:
var hasExploded = false
personal setvar isPlanted = false
personal setpersonal val cost: () -> Unitenjoyable plant()
enjoyable down(trigger: String = "")
enjoyable tryDiffuse()personal enjoyable explode()
Similar to an actual one, as soon as a bomb is created it has a cost planted in it, you’ll be able to
plant() it, on the identical time the timer additionally kicks off. To press the set off, you want a
down() button. And as soon as all of the triggers are down or the timer is expired, the bomb is exploded. The bomb will also be
subtle() earlier than the explosion takes place.
Now I knew all of the contracts that the bomb wants to stick and all of us can relate to it. Isn’t it? Then I wrote the precise implementation.
To make use of this, we have to write a easy code:
// Create a bomb.
multiTriggerBomb = MultiTriggerBomb(5, timerDuration)
// Code that should get fired on explosion
// plant it!
Each time one of many circumstances turns into true, name
down() with the optionally available motive param.
multiTriggerBomb?.down("some situation happy")
When all of the circumstances turn into true or the timer expires, our bomb will explode and execute the code that’s planted inside it.
That’s how we planted a bomb in our code base!
Professional Tip — You should use bomb to attach a number of callbacks/occasions/checks within the codebase and hearth a chunk of code and get the state administration and thread-safety out of the field.