Reported October 2026
Anroksimulation

Batched Key Fetch Callbacks

Reported by candidates from Anrok's online assessment. Pattern, common pitfall, and the honest play if you blank under the timer.

Get StealthCoderRuns invisibly during the live Anrok OA. Under 2s to a working solution.
Founder's read

The mistake that sinks a first attempt on this Anrok OA, reported in October 2026, is treating the 100ms window as closed on the right. It isn't. A call stamped exactly at the deadline starts a new batch. The problem is a single-pass simulation with a hash map: group calls into half-open windows, dedupe keys by first appearance, then emit callbacks in input order. It reads like a JavaScript debounce question wearing a string-formatting costume. If you blank on the boundary rule mid-assessment, StealthCoder runs invisibly on your desktop and gives you the solution as a safety net.

The problem

Simulate calls to startFetch(key, callback). The parallel arrays callTimes, keys, and callbackIds describe those calls in nondecreasing timestamp order. Each row [key, value] in keyValues supplies the successful response value for that key.
When a call arrives while no timer is pending, schedule one batch flush exactly 100 milliseconds later. Every call whose timestamp is strictly earlier than that deadline joins the pending batch. The timeout runs before a call stamped exactly at the deadline, so that call starts a new half-open window.
At each flush, issue exactly one request in the form GET:/get?keys=key1,key2,.... Include each requested key once, ordered by its first call in that batch. Model the response as available synchronously at the flush.
After the request event, invoke every registered callback in original input order. A callback receives the value mapped to its key, including when several callbacks requested the same key. Record an invocation as CALL:callbackId:value.
Return one string row per HTTP batch. The request event is the first string in its row, followed by that batch's callback events. If there are no calls, return an empty matrix.

Function
batchFetchCallbacks(callTimes: int[], keys: String[], callbackIds: String[], keyValues: String[][]) → String[][]

Examples
Example 1
callTimes = [0,30,70,120]
keys = ["foo","bar","foo","foo"]
callbackIds = ["cb1","cb2","cb3","cb4"]
keyValues = [["foo","123"],["bar","abs"]]
return = [["GET:/get?keys=foo,bar","CALL:cb1:123","CALL:cb2:abs","CALL:cb3:123"],["GET:/get?keys=foo","CALL:cb4:123"]]
The call at time 0 schedules a flush at time 100. The calls at times 30 and 70 join that batch, with foo appearing once in the request while both of its callbacks receive 123. The call at time 120 starts the second request.
Example 2
callTimes = [5,104,105,105]
keys = ["a","a","b","a"]
callbackIds = ["first","second","third","fourth"]
keyValues = [["a","A"],["b","B"]]
return = [["GET:/get?keys=a","CALL:first:A","CALL:second:A"],["GET:/get?keys=b,a","CALL:third:B","CALL:fourth:A"]]
The first half-open window is [5,105). The timeout runs before calls stamped 105, so those two calls start a new window and preserve their input order.
Example 3
callTimes = [10,10,50,250,349]
keys = ["z","x","z","x","y"]
callbackIds = ["c0","c1","c2","c3","c4"]
keyValues = [["x","vx"],["y","vy"],["z","vz"]]
return = [["GET:/get?keys=z,x","CALL:c0:vz","CALL:c1:vx","CALL:c2:vz"],["GET:/get?keys=x,y","CALL:c3:vx","CALL:c4:vy"]]
Equal-time calls keep their input order. After the first flush, time 250 starts a fresh window ending at 350, so the call at 349 joins it.

Constraints
0 <= callTimes.length = keys.length = callbackIds.length <= 200000.
0 <= callTimes[i] <= 10^9, and callTimes is nondecreasing.
keyValues contains exactly one row for every distinct key in keys.
Keys contain 1 to 20 lowercase ASCII letters, digits, or underscores and do not contain commas.
Callback IDs contain 1 to 20 ASCII letters, digits, or underscores and do not contain colons.
Response values contain 1 to 20 ASCII letters, digits, underscores, or hyphens and do not contain colons.

Reported by candidates. Source: FastPrep

Pattern and pitfall

Walk the arrays once with an index. When you start a batch at time t, the deadline is t+100. Keep consuming calls while callTimes[i] < deadline. That strict less-than is the whole trick, and Example 2 proves it: 105 starts a new window when the first began at 5. Inside a batch, keep a set of seen keys and an ordered list for the request string, so each key appears once, ordered by first call. Then build the row: the GET string first, then one CALL:id:value per callback in original order, looking values up from a map built from keyValues. Pitfalls: using <= on the deadline, deduping callbacks instead of keys, and string concatenation in a loop with 200000 calls. Use a list and join. Complexity is O(n). If the boundary logic slips under pressure, StealthCoder is the hedge during the live OA.

Memorize the pattern. If you can't, run StealthCoder. The proctor sees the IDE. They don't see what's behind it.

If this hits your live OA

You can drill Batched Key Fetch Callbacks cold, or you can hedge it. StealthCoder runs invisibly during screen share and surfaces a working solution in under 2 seconds. The proctor sees the IDE. They don't see what's behind it. Made by an engineer who treats the OA as theater. If yours is tonight, you don't have time to grind. You have time to hedge.

Get StealthCoder
⏵ The honest play

You've seen the question. Make sure you actually pass Anrok's OA.

Anrok reuses patterns across OAs. Made by an engineer who treats the OA as theater. If yours is tonight, you don't have time to grind. You have time to hedge. Works on HackerRank, CodeSignal, CoderPad, and Karat.

Batched Key Fetch Callbacks FAQ

What's the trick in the Anrok batched fetch problem?+

The window is half-open. A batch started at time t takes every call with timestamp strictly less than t+100. A call at exactly t+100 begins a new batch. Get that one comparison right and the rest is straightforward bookkeeping with a map and a list.

How hard is this one really?+

Easy to medium on algorithm, medium on care. There's no fancy data structure. It's one linear pass. The difficulty is the edge rules: boundary timing, key dedupe by first appearance, and callbacks staying in input order even when keys repeat.

Do I dedupe callbacks or keys?+

Only keys. The request string lists each key once, ordered by its first call in that batch. Every callback still fires, in original input order, and each gets the value for its own key. Example 1 shows two foo callbacks both receiving 123.

What should I return when there are no calls?+

An empty matrix. With zero-length inputs your loop never runs, so returning your result list as-is handles it naturally. Just make sure you don't push an empty row or a lone request string before checking that calls exist.

How do I prepare for this in 48 hours?+

Write the solution from scratch once and test it against all three examples, especially Example 2 for the boundary. Practice the pattern: simulate with an index, a hash map for lookups, and a set for ordered dedupe. Watch for performance with 200000 calls.

Problem reported by candidates from a real Online Assessment. Sourced from a publicly-available candidate-aggregated repository. Not affiliated with Anrok.

OA at Anrok?
Invisible during screen share
Get it