I'm not going to dive into the specifics of my thoughts on this question. I think a lot of comments here address this.
But does anyone else get embarrassed of their career choice when you read things like this?
I've loved software since I was a kid, but as I get older, and my friends' careers develop in private equity, medicine, law, {basically anything else}, I can tell a distinct difference between their field and mine. Like, there's no way a grown adult in another field evaluates another grown adult in the equivalent mechanism of what we see here. I know this as a fact.
I just saw a comment last week of a guy who proudly serves millions of webpages off a CSV-powered database, citing only reasons that were also covered by literally any other database.
I think a lot of fields of engineering have analogous questions actually. EEs ask to explain a circuit or draw a new one. Mech Es ask to design some piece of simple hardware with a clever catch. Interviewing is just hard, it’s impossible to cover breadth of knowledge in 45 mins so we end up with little brain teasers.
This particular question is a bit ill formed and confusing I will say. But that might serve as a nice signal to the candidate that they should work elsewhere, so not all is lost.
Lawyers have law school after a degree, a bar exam, legal liability for malpractice, and ongoing licensing requirements.
Medicine has medical school after a degree, a 5+ year residency under close supervision with significant failure rates, legal liability for malpractice, and ongoing licensing requirements.
So explain to us what it is that you "know this for a fact" regarding how they have it easier. Most of the people reading this, myself included, would never have been allowed into this industry, let alone been allowed to stay in it, if the bar were as high as law or medicine.
The difference is that if you fail medicine, it’s ok (it’s hard). But if you fail to get a job because of the stupid “async queue” author’s problem, well, that’s depressing.
I'm not so sure. Failing your residency means your medical career is basically done, and you have to basically start a new career from scratch in your late 20s. Chances are you'll have debt from not just undergrad but also med school.
By comparison, failing a leetcode interview means you've got to find a new company to interview with.
Nope. In my opinion Wild West in software is much preferred model. If one wants to create software and sell it there should be no barriers. It is one of the the very few fields that give chance to simple people with no money to break out and live decent life.
When I started writing code for a living 30 years ago, we were mostly left alone to solve problems.
Now it feels like I'm back in high school, including strict irrelevant rules to be followed, people constantly checking in on you, and especially all of the petty drama and popularity contests.
> does anyone else get embarrassed of their career choice when you read things like this?
On the contrary, it makes me proud. In private equity, medicine, or law, if you have the right accent and went to a good school and have some good names on your resume, you can get a job even if you're thoroughly incompetent - and if you're a genius but don't have the right credentials you'll probably be overlooked. In programming it still mostly comes down to whether you can actually program. Long may it continue.
The author says this is one of their favourite interview questions. I stop to wonder what the others are.
When I'm interviewing a candidate, I'm trying to assess really a few things: 1) the capability of the person I'm interviewing to have a technical conversation with another human being; 2) how this person thinks when they are presented with a problem they have to solve; and 3) can this person be trusted with important work?
For 1) and 2), coding interviews and the types of artificially constructed and unrealistic scenarios really aren't helpful, in my experience. I care a lot less about the person being able to solve one specific problem I hand them and I care a lot more about the person being able to handle a much more realistic scenario of being hand handed an ill-defined thing and picking it apart. Those conversations are typically much more open-ended; the goal is to hear how the person approaches the problem, what assumptions they make about the problem, and what follow-ups are needed once they realise at least one of their assumptions is wrong.
This is a really hard thing to do. For example, I imagine (but do not know) that when a medical practice hires a doctor for a certain role, there is an expectation that they already know how the human body works. For an ER doctor, you might care more about how well that person can prioritise and triage patients based on their initial symptoms. And you might also care about how that person handles an escalation when a patient presents not too awfully but is in fact seriously ill. For a GP, it's probably more important for a practice to care more about healthcare philosophy and patient care approaches rather than the prioritisation thing I mentioned above. I'm spit-balling here, but the point is these two situations are both hiring doctors. You care less about what the person knows because there is a tacit assumption that they know what they need to know; you're not giving the candidate a trial surgery or differential diagnosis (maybe... again I'm not a doctor so I don't actually know what I'm talking about here).
If I'm hiring a software engineer or performance engineer, I am trying to figure out how you approach a software design problem or a performance problem. I am not trying to figure out if you can design an async queue in a single-threaded client. This problem doesn't even generalise well to a real situation. It would be like asking a doctor to assume that a patient has no allergies.
Item number 3) is "Can this person be trusted with important work?" and this is basically impossible to determine from an interview. It's also impossible to determine from a CV. The only way to find out is to hire them and give them important work. CVs will say that a candidate was responsible for X, Y and Z. They never say what their contribution was, or whether or not that contribution was a group effort or solo. The only way to find out, is to hire. And I've hired candidates that I thought could be trusted and I was wrong. It sucks. You course-correct them and figure out how to get them to a place where they can be trusted.
Hiring is hard. It's a massive risk. Interviews only give you a partial picture. When you get a good hire it's such a blessing and reduces my anxiety. When you hire a candidate you thought would be good and turns out to be an absolute pain to manage it causes me many sleepless nights.
The higher layer of people in our industry aren’t subjected to those questions. They are evaluated and get jobs more like in law and medicine, ie based on connections and track of record.
Me and you are just not of that high layer. We’re kind of laborers given those simple aptitude tests.
When I was on track to get into the higher layer 15 years ago I got that my last job just by invitation and half an hour talk with VP. Next offer and other invitations came soon the same way, yet I got lazy and stuck at the current job simplemindedly digging the trench deeper and deeper like a laborer.
I dunno, seems like a really confusing question. Communication is important but I can imagine that explaining this verbally on the spot to an interviewee would not be straightforward especially because the assumptions made around single threading get confusing. If it's just a Javascript question say that - because it seems it basically is. Writing this in go would be super easy so I think the question is just asking people how well they understand Javascript.
Agreed. ‘sendOnce’ implies something very specific in most async settings and, in this interview question, is being used to mean something rather different.
Exactly. If I were asked this question during an interview, the first thing I'd say is "why should the client bother with anything more complex than jittered exponential backoff?"
FWIW I’ve basically been given basically this exact requirement by a partner with a crappy API.
We’d get on calls with them and they’d be like “you can’t do multithreading!” we eventually parsed out that what they literally meant was that we could only make a single request to their API at a time. We’d had to integrate with them, and they weren’t going to fix it on their side.
(Our solve ended being a lot more complicated than this, as we had multiple processes across multiple machines that were potentially making concurrent requests.)
> Not actually that hard with a redis lock or any database (Postgres has a specific lock for this but you could also just use a record in a table)
Redis is just another SPOF, and so is Postgres without fiddly third party extensions (that are pretty unreliable in practice, IME). I'm talking about something truly distributed.
Because it was written in ALGOL 60, none of the mainframe devs are willing to touch that code, and the dozen other clients probably depend on the broken functionality.
That makes it even better, the candidate should ask clarifying questions. I've worked with people who, when encountering some amount of ambiguity, either throw their hands up, or make some random assumptions. Ability to communicate effectively to bridge the gaps in understanding is what I'd expect from any candidate, especially more senior ones.
But that doesn’t work. One could ask why server can handle only one request? Why can’t we upgrade (vertically or horizontally) the server? Why the logic needs to live in the client? And a large etc.
It’s not the ability to communicate effectively that’s at play here, it’s your ability to read your interviewer’s thoughts. Sure thing, if you work with stakeholders, you need some of that as well, but you typically can iterate with them as needed, whereas you have a single shot in the interview.
Plenty of times, at the end of the interview, I do have a better mental picture of the problem and can come up with a way better solution, but “hey, 1h has already passed so get the fuck out of here. Next!”
Sure, but this isn't a back&forth interview - it's a blog post. The author could have included a section with clarifying questions they expect the candidate to ask, and responses to those questions.
As it stands, we still don't know why the server was broken in this way and why they created a work around in the client instead of fixing the server.
Yeah, I really don’t see how this is a sensible interview question. It does not even mention async await syntax. Expecting knowledge on callbacks seems dated.
As a self promoting post I think the author did a good job. As an interview format, I would rather work somewhere less ego driven development and more real problem oriented workplace. But that is just me. Someone could prefer these kind of interviews. I also did a set of questions for java engineers in the past and I always felt there is something really icky. I also noticed the engineers with huge ego revel in these kind of candidate assessments as it makes the feel good, but the candidate performance is poorly tested. Thats what the probation period is for. Just ask the candidate whats his experience. Asking these "cleverly" designed problems is nice for the interviever importance of keeping his job, but is not really usefull. You could even miss a good engineer. Perhaps i see this too narrow and you just really want to observe what the candidate is thinking, but you could make a couple of not really complicated questions and you could see where he is at. I dont bite this head-game at all.
I agree to a point. For me, what chaffs is the convulted prompt that goes against all my instincts for how to design something simply and clearly.
"Ok, but if you had to code something convulted and illogical..." I tend to have trouble with these sorts of black box problems not because of the challenge but because of going down the path feels wrong I would expect my day to day at the company would be surrounded by too clever solutions.
Also, recognize a minimum requirement to solve this under interview pressure is a lot of low-level futzing with Javascript async and timeout details. Not everyone comes in with that knowledge or experience, and it's fine if that is a hard requirement but it seems ancillary to the goal of "interviewing engineers". I can't imagine anyone solving this or even knowing how to prompt AI in the right ways without a fair bit of prior knowledge.
for the record (and disregarding how appropriate this is as an interview question): in JS you can (ab)use the event loop and promise chains to do this for you without managing any queues or lists manually. You have a single `let job = Promise.success();` as a global var, and scheduling a new job becomes `job = job.then(f, errHandler).then(callback, errHandler)`. It's a nightmare to debug (because you can't "see" the in-process queue) but it means you don't have to muck around with manual lists, queues, loops, shift/unshift, "isProcessing" flags etc, all of which is basically you reimplementing that native functionality in user space. It completely sidesteps the bug of TFAs naive implementation.
Not advocating for this in prod but in the context of a programming puzzle it can be neat.
late edit: ironically this is also a comment on the LLM talk in TFA: messing with the event loop like this can give you a strong mental model of JS semantics. Using LLMs I would just have accepted a loop and never learned about promise chains. This is the risk in using LLMs: you plateau. If you will allow a tortured metaphor: my naive understanding of SR is that you always move at light speed, but in 4 dimensions, so the faster you move in the 3D world, the slower you move through time, and vice versa. Skill is similar: your skill vector is always a fixed size (= "talent"?). If you use LLMs, it's basically flat: complete tasks fast but learn nothing. Without them, you move diagonally upwards: always improving, but slower in the "task completion" plane. Are you ready to plateau?
If you don't care about the order of requests then you can just set up a flag to denote if a task is running, and keep rescheduling the other tasks. Something like
let isProcessing = false;
async function checkFlagAndRun(task) {
if (isProcessing) {
return setTimeout(() => checkFlagAndRun(task), 0);
}
isProcessing = true;
await task();
isProcessing = false;
}
should do the trick. You can test it with
function delayedLog(message, delay) {
return new Promise(resolve => {
setTimeout(() => {
console.log(message);
resolve();
}, delay);
});
}
function test(name,num) {
for (let i = 1; i <= num; i++) {
const delay = Math.floor(Math.random() * 1000 + 1);
checkFlagAndRun(() => delayedLog(`${name}-${i} waited ${delay} ms`, delay));
}
}
test('t1',20); test('t2',20); test('t3',20);
BTW, for 4 scheduled tasks, it basically always keeps the order, and I am not sure why. Even if the first task always runs first, the rest 3 should race each other. 5 simultaneously scheduled tasks ruins the order.
I expected this to be the answer. I guess the interview is not necessarily for JavaScript programmers, but this seems like the correct solution. It brings in some facilities for dealing with errors, too.
echoing the other comments about this being a rather terrible interview question...
> this interview can be given in JavaScript or any other language
it's a language-agnostic question...but it revolves around the assumption of making a callback on request completion. which is common in JS, but if you were solving this in some other language, that's usually not idiomatic at all.
followed by:
> For candidates without JavaScript experience or doing this interview in pseudo-code, you have to tell them that there's another function available to them now with the following signature:
> declare function setTimeout(callback: () => void, delayMs: number): number;
so you add in this curveball of delaying requests (it's unclear why?), and it's trivial to solve...using a function from the JS stdlib. and if the candidate is not using JS, you need to tell them "oh there's a function from JS that you can assume is available"
> After sendOnce is implemented, it's time to make the interview a lot more interesting. This is where you can start to distinguish less skilled software engineers from more skilled software engineers. You can do this by adding a bunch of new requirements to the problem
as you originally specified it, this code is a workaround for a buggy server. and for Contrived Interview Reasons we can't modify the server at all, only the client.
in that scenario, "extend it into a generic queue with a bunch of bells and whistles" is maybe the worst design decision you could pursue? this thing, if it existed in the real world, should be named something like SingleRequestQueueForWorkingAroundHopelesslyBuggyServer with comments explaining the backstory for why it needs to exist. working around the hopelessly buggy server should be roped off into one small corner of the codebase, and not allowed to infect other code that makes normal requests to non-buggy servers.
I think we all have but that doesn't change that this is almost exclusively a js specific interview question with a very js'y solution to the point of hammering in a imagined "js land" api.
I am not against testing deeper language understanding for a job that requires it but the layers of contrivances to make it "not only js" rightfully rubs non-js devs the wrong way. This comes from someone who loves them some js.
The AI ick at the end makes what would have been mildly interesting, incoherent and uninteresting.
Maybe I came into this article knowing too much about the solution, but I dont agree with commenters saying this is a poorly designed interview question. Its a blog post as well, not the format that would be presented to a candidate.
I think it has clear requirements and opportunities for nudges from the interviewer without invalidating the assessment (when someone inevitably gets tunnel vision on one particular requirement). It has plenty of ways for an interviewee to demonstrate their knowledge and solve the problem in different ways.
Ive run debounce interview questions that attempt to exercise similar competency from candidates, with layering on of requirements time allowing (leading/trailing edge, cancel, etc) and this queue form honestly feels closer to what Id expect devs to actually have built in their day to day.
Same here. I thought that this specific problem is not that uncommon. On top of my mind: say if the endpoint you're hitting is rate-limited. It doesn't even have to be an API call. I think I've probably written something with the same pattern once or twice before.
I do agree that this is quite javascript specific though.
We actually have this pattern in our codebase and, while we don’t have all the features on top, it’s a succinct enough thing to understand that also gives lots of opportunity for discussion.
Interviewer and candidate meet at time X for 1h session of “live coding”. A saas throws at them both one problem at random. Let the game begin. The company can decide if they want interviewer and candidate to collaborate together to solve the problem (the saas is the judge) or perhaps they both need to play against each other and see who gets the optimal solution.
You can add a twist (faangs most likely): if the candidate submits a “better” answer than the interviewer’s , candidate takes over their job.
An LLM could be very well behind the saas.
Oh boy, I wouldn’t feel that nervous anymore in any interview. Fairness is the trick. One feels so underpowered when you know that the interviewer knows every detail about the proposed problem. But when both have no idea about the problem? That’s levelling the field!
Why would anyone agree to participate in interviews then? Do we then force developers to conduct interviews? If so, which ones? The superstars or the ones on PIP? You can see where this is going..
Might be a whoosh, but really don’t understand the idea of seeing the interviewer as an adversary. Stress in interviews comes from many places but honestly one of the roles of the interviewer is to bring it down.
I think maybe the problem being alluded to is that a lot of interviewers aren't that good at this and instead give off vibes that play up the "I'm judging you from a default presumption that I'm more competent than you" angle.
(Really, it shouldn't be surprising that most technical interviewers aren't that competent, since they usually aren't selected for it.)
Oh god. I’ve met some seriously incompetent people when interviewing - to the point where I’m glad they are the one conducting the interview cause I never want to work with them. I’ve actually finished an interview where I was the candidate with “thank you, but I don’t think this is going to work out”.
I've seen somewhat similar things in embedded development, e.g. ADCs with a triggered conversion mode that start a new conversion on receipt of a new trigger, abandoning a previous conversion if one was in progress. They fire an interrupt when the conversion completes. Not in any way buggy or unexpected, ICs generally either can block or can immediately respond but can't queue multiple requests.
Of course on the embedded side you're likely using C, quite likely an RTOS and thus threads, but if you're just using a superloop then you've got a single-threaded system (though with the complication of interrupt handlers) a bit like the interview asks about. I'd probably use a state machine for this with a superloop design, just about everything "async" in embedded boils down to writing a state machine & polling it. Actually writing a fully general-purpose async queue for embedded systems is rather more work, because you'll have to consider how it can be used from within the interrupt context. You really shouldn't block in an interrupt context, so all the queue operations need to be non-blocking. That turns it into something far too complex for an interview question.
Interestingly I think I would over-think this. The interviewer is assuming a single server, running in a VPS type environment. There's also no notion of state persistence/timeout/recovery etc. I think I'd immediately have started factoring those things in.
ALSO while JavaScript is a single threaded environment, the while solution would still basically work due to the scheduler (at least if you yield, await sleep, etc.)
I've implemented multiple production versions of this problem (but not in JavaScript)[1], so maybe my view of this problem is miscalibrated...
This feels both too easy and too hard for an interview? I would expect almost any new grad to be able to implement this in the language of their choice. Adding delays makes it less trivial, except that the answer is... Just use the function provided by the language. That's the right answer for real code, but what are you really assessing by asking it?
It's too hard because the variations you could add to it (multi threading) that add enough depth to make it hard make it too hard, in my opinion. If you look at the implementation I linked in my previous comment, it's fully lock-free, which is pretty unreasonable to expect from anyone who isn't already familiar with lock free concurrency. On the other hand the version with a lock is basically identical to the single thread version. Asking for the two-lock queue is also a bad interview question because it's not something you'd reasonably expect someone to derive in an interview.
The other examples given for fleshing it out are all pretty similar; if a candidate can do one, chances are they can do the others too. If you want to get a decent signal if candidate skill, you have to ask a question easy enough that any candidate you'd accept can answer it, then incrementally add difficulty until you've given the candidate a chance to show off the limit of their abilities (at least as applied to your question).
Otherwise you ask a too-easy question which everyone nails, then make it way too hard and everyone fails. Or you ask a too-easy question and follow it up with additional enhancements that don't actually add much difficulty, and again all the candidates look similar. That's just my experience; the author seems pleased with the question so maybe they're getting good signal out of it.
> (a lot of people resort to some type of blocking sleep style function call to solve the delay part of this problem)
In many async languages you can do an async sleep (e.g. Python's asyncio.sleep()) which is a sleep that uses the event loop. Really, that's all Javascript's setTimeout() is doing anyway; it's just named differently.
Do I have to use JavaScript? I'd write it in Java in a way that it would be trivial to ramp up the number of connections in the pool once they fix their stupid server.
For this first implementation, I don't see anything ever added to the queue. Am I missing something? New task is added to the queue if the queue is not empty only, but when the queue is empty the task is executed and the queue remains empty so in the end the queue is always empty?
Another thing is that the article emphasized that it's single threaded. That by itself guarantees that there will only ever be 1 inflight request, since calling the send() function will block until the request completes, and the callback is called.
If there is some kind of cooperative multitasking going on, then it should be noted in the pseudo code with eg. async/await or equivalent keywords. As the code is, send() never gives back control to the calling code, until it completely finishes.
Interviews are a two way street. If you strongly imply that working around servers that only do one thing is part of your day to day work, a lot of people will want to work somewhere they can learn about more modern software.
If I were asked this question, the first thing I said would be this is a poorly designed architecture. Client is the poor place to do throttling by itself. It has no information on the aggregated load of the system. It makes assumption that leads to complicate code in the sample code. There're more robust and better ways to do flow control and throttling.
the intro isnt throttling, its request serialization. there isnt some limit to keep your requests to, just that its one at a time. it could go as fast or as slow as the individual requests finish.
its still not a great architecture, but its different from throttling
> But that server is faulty!! If it has to handle multiple requests at once, it starts to break down. So, we decide to make our server's life easier by trying to ensure, from the client, that it doesn't ever have to handle more than one request at once
Easier to write. But there is a case to be made that code which can be understood without understanding somewhat esoteric language internals is superior.
I did this in the firmware of a VoIP base station.
I was informed by the radio firmware guys that a certain kind of request from the host could not be handled concurrently by the radio module due to an unchecked conflict over some global piece of memory or whatever.
I create a wait-free circular buffer for serializing the requests of that type, where the replies from the previous request would kick down the next one.
> So, we decide to make our server's life easier by trying to ensure, from the client, that it doesn't ever have to handle more than one request at once (at least from the same client, so we can assume this is a single-server per-client type of architecture).
It’s funny because I have had ti implement “serialized fetch()” a few times recently, with delays and random jitter too.
I think this question is a bit confusing in its wording even though the concept is actually quite useful in practice. First, async queues have nothing to do with network coms. You can have a async queues for local tasks.
Also while it is obvious to most that you shouldn’t do this, you can also satisfy the requirements to this task by polling the queue and flag using setTimeout() or setInterval(): on invocation, check if there is anything in the queue and if so, if we aren’t waiting on a response fire off the next send().
Retry logic with this system is always a problem. Do you block the queue forever by retrying a request that will never complete (which lets the queue grow infinite in size), or do you give up after some number of retired? If you give up, does that invalidate all queued requests? Some? None? This becomes application-specific. For this kind of thing I have implemented it using multiple parallel queues. That is, you request a send() but using a specifically named queue so that if one queue’s serialized requests break, other queues aren’t affected.
If you do something like `sendOnce(payloadA, callbackA, 5000); sendOnce(payloadB, callbackB, 1);` should payloadB be sent in 1ms or 5000 + RTT + 1ms?
You could solve this in the JavaScript environment by using something like WebSockets or WebTransport much more trivially than by using send() which is I assume a thinly veiled fetch(). This probably fails OP’s interview but in reality leverages the lower level queueing/buffering.
A more fun and likely more illuminating question would be to do something like provide a version of send() that uses a callback for the response and ask to convert it to a promise. This is a really fun one that I had to deal with when using WebCodecs: a video decoder uses callbacks to give you frames but for example Safari has a bug where it will return frames that are encoded as delta frames out of presentation order. So the much better API is to feed a bunch of demuxed encoded chunks to a wrapper around VideoDecoder, and then wait for the resolution (or rejection) of a promise where the result is all the decoded frames at once. This problem really gets at the concept of callbacks vs promises which I think is the right level of abstraction for evaluating how someone thinks of single threaded concurrency. You also can get a really good feel for a person’s attitude here if they refuse to use callbacks or promises (or the async/await sugar around promises).
In another thread I asked if leetcode style questions are still common, and the answer I got was yes, so where would I encounter this kind of question? I only ever got leetcode style questions or something like "what is the difference between var and let"
The minDelay extension feels contrived and also the solution sucks. None of the pending requests are actually added to the queue until the timeout is finished, meaning you have no knowledge of all these delayed requests until the timeout passes and they all enqueue themselves
I don’t know anything about the author, so just speculating here: assuming that the interview lasts 1h, it’s not realistic (nor fair) to judge the candidate’s answer if the interviewer has spent more than 1h to think about the problem and potential solution(s).
Interviewers have thought about the problem they propose countless of times (at least once per interview they have hold) each time refines their understanding of the problem, and so they become god of their tiny realm. Candidates have less than one hour, add to that stress and a single shot to get it more or less right. You’re not assessing candidate’s ability to code nor their ability to handle new requirements as they come.
thanks for sharing and by reading the blogpost and the comments I think I get the whole point: it's all about how engineers understand the requests and the reasoning about how does it approach that more than the code itself.
If this raw code really works or not it's almost secondary here - IMHO nobody I'll start coding a real queue out of blue like this.
I’m really confused why this is an “async queue.” Seems pretty synchronous to me since requests are completed in order, one at a time. I literally wrote something to do this in the past few months. This was to work around JavaScript’s asynchronous IO making a shit show of updates from library being used in the client. I had to queue requests in JavaScript, have them execute in order (FIFO), and explicitly described it “synchronous.”
Is it only “async” because it’s doing it in JavaScript and the underlying network request API is asynchronous? Seems like, IMHO, a really bad way to describe the desired result since all IO in JavaScript is going to be async by default.
the async part isnt very exciting, but its the callback after the entry has been through the queue and worked on.
its certainly serialized, but nothing fancy otherwise.
it would be synchronous if you blocked the requester until the request go through the queue and then completed. you wouldnt need to introduce an async/await.
you can see examples in JS on the node FS functions. the defualt ones are async, but they have some magic wrappers that make it actually sychronous and block the event loop from running until the file is loaded
The explanation is way too long, in an area that is pretty big and can be done in many ways. Couple this with candidates who will variously be fearful of asking to many or too few questions, and you just have confusion about who is good and who is not.
This is one of the most confusing and badly worded interview problems I've ever seen. If I had been given this problem, I'd view it as a signal that I'd be wasting my time working with the folks that thought it was good.
Hmm… this code doesn’t work in the real world unless you only run it on a single machine. Perhaps a more interesting question is how to make a multi-node queue with max N concurrent requests.
“… it doesn't ever have to handle more than one request at once (at least from the same client, so we can assume this is a single-server per-client type of architecture).“
For sure a multithreaded async queue would be a very interesting interview, but if you started with the send system the interview is constructed around youd run out of time quickly.
These are multiple assumptions
"This queue is only on one machine and on one thread", what's the real world use-case here? Not saying there's none but make it clear. I wouldn't want to work for a company that has to think of some random precise question instead of e.g. "when would you not use mysql?"
I'm not going to dive into the specifics of my thoughts on this question. I think a lot of comments here address this.
But does anyone else get embarrassed of their career choice when you read things like this?
I've loved software since I was a kid, but as I get older, and my friends' careers develop in private equity, medicine, law, {basically anything else}, I can tell a distinct difference between their field and mine. Like, there's no way a grown adult in another field evaluates another grown adult in the equivalent mechanism of what we see here. I know this as a fact.
I just saw a comment last week of a guy who proudly serves millions of webpages off a CSV-powered database, citing only reasons that were also covered by literally any other database.
It just doesn't feel like this is right.
I think a lot of fields of engineering have analogous questions actually. EEs ask to explain a circuit or draw a new one. Mech Es ask to design some piece of simple hardware with a clever catch. Interviewing is just hard, it’s impossible to cover breadth of knowledge in 45 mins so we end up with little brain teasers.
This particular question is a bit ill formed and confusing I will say. But that might serve as a nice signal to the candidate that they should work elsewhere, so not all is lost.
Lawyers have law school after a degree, a bar exam, legal liability for malpractice, and ongoing licensing requirements.
Medicine has medical school after a degree, a 5+ year residency under close supervision with significant failure rates, legal liability for malpractice, and ongoing licensing requirements.
So explain to us what it is that you "know this for a fact" regarding how they have it easier. Most of the people reading this, myself included, would never have been allowed into this industry, let alone been allowed to stay in it, if the bar were as high as law or medicine.
The difference is that if you fail medicine, it’s ok (it’s hard). But if you fail to get a job because of the stupid “async queue” author’s problem, well, that’s depressing.
I'm not so sure. Failing your residency means your medical career is basically done, and you have to basically start a new career from scratch in your late 20s. Chances are you'll have debt from not just undergrad but also med school.
By comparison, failing a leetcode interview means you've got to find a new company to interview with.
Perhaps the bar should be as high as law and medicine if we want people to take our industry just as seriously.
Nope. In my opinion Wild West in software is much preferred model. If one wants to create software and sell it there should be no barriers. It is one of the the very few fields that give chance to simple people with no money to break out and live decent life.
Just make sure to save up before ageism kicks in.
Agreed, this is just terrible for the field as a whole it’s like we’re regressing or something
When I started writing code for a living 30 years ago, we were mostly left alone to solve problems.
Now it feels like I'm back in high school, including strict irrelevant rules to be followed, people constantly checking in on you, and especially all of the petty drama and popularity contests.
Which part, the fact that you have to answer such questions to get a job? Those other fields are more established and have formal barriers to entry.
> does anyone else get embarrassed of their career choice when you read things like this?
On the contrary, it makes me proud. In private equity, medicine, or law, if you have the right accent and went to a good school and have some good names on your resume, you can get a job even if you're thoroughly incompetent - and if you're a genius but don't have the right credentials you'll probably be overlooked. In programming it still mostly comes down to whether you can actually program. Long may it continue.
> It just doesn't feel like this is right.
I know the feeling.
The author says this is one of their favourite interview questions. I stop to wonder what the others are.
When I'm interviewing a candidate, I'm trying to assess really a few things: 1) the capability of the person I'm interviewing to have a technical conversation with another human being; 2) how this person thinks when they are presented with a problem they have to solve; and 3) can this person be trusted with important work?
For 1) and 2), coding interviews and the types of artificially constructed and unrealistic scenarios really aren't helpful, in my experience. I care a lot less about the person being able to solve one specific problem I hand them and I care a lot more about the person being able to handle a much more realistic scenario of being hand handed an ill-defined thing and picking it apart. Those conversations are typically much more open-ended; the goal is to hear how the person approaches the problem, what assumptions they make about the problem, and what follow-ups are needed once they realise at least one of their assumptions is wrong.
This is a really hard thing to do. For example, I imagine (but do not know) that when a medical practice hires a doctor for a certain role, there is an expectation that they already know how the human body works. For an ER doctor, you might care more about how well that person can prioritise and triage patients based on their initial symptoms. And you might also care about how that person handles an escalation when a patient presents not too awfully but is in fact seriously ill. For a GP, it's probably more important for a practice to care more about healthcare philosophy and patient care approaches rather than the prioritisation thing I mentioned above. I'm spit-balling here, but the point is these two situations are both hiring doctors. You care less about what the person knows because there is a tacit assumption that they know what they need to know; you're not giving the candidate a trial surgery or differential diagnosis (maybe... again I'm not a doctor so I don't actually know what I'm talking about here).
If I'm hiring a software engineer or performance engineer, I am trying to figure out how you approach a software design problem or a performance problem. I am not trying to figure out if you can design an async queue in a single-threaded client. This problem doesn't even generalise well to a real situation. It would be like asking a doctor to assume that a patient has no allergies.
Item number 3) is "Can this person be trusted with important work?" and this is basically impossible to determine from an interview. It's also impossible to determine from a CV. The only way to find out is to hire them and give them important work. CVs will say that a candidate was responsible for X, Y and Z. They never say what their contribution was, or whether or not that contribution was a group effort or solo. The only way to find out, is to hire. And I've hired candidates that I thought could be trusted and I was wrong. It sucks. You course-correct them and figure out how to get them to a place where they can be trusted.
Hiring is hard. It's a massive risk. Interviews only give you a partial picture. When you get a good hire it's such a blessing and reduces my anxiety. When you hire a candidate you thought would be good and turns out to be an absolute pain to manage it causes me many sleepless nights.
The higher layer of people in our industry aren’t subjected to those questions. They are evaluated and get jobs more like in law and medicine, ie based on connections and track of record.
Me and you are just not of that high layer. We’re kind of laborers given those simple aptitude tests.
When I was on track to get into the higher layer 15 years ago I got that my last job just by invitation and half an hour talk with VP. Next offer and other invitations came soon the same way, yet I got lazy and stuck at the current job simplemindedly digging the trench deeper and deeper like a laborer.
I dunno, seems like a really confusing question. Communication is important but I can imagine that explaining this verbally on the spot to an interviewee would not be straightforward especially because the assumptions made around single threading get confusing. If it's just a Javascript question say that - because it seems it basically is. Writing this in go would be super easy so I think the question is just asking people how well they understand Javascript.
> seems like a really confusing question
Agreed. ‘sendOnce’ implies something very specific in most async settings and, in this interview question, is being used to mean something rather different.
The confusing part for me is why I’m dicking around with the client when the server’s broken.
Exactly. If I were asked this question during an interview, the first thing I'd say is "why should the client bother with anything more complex than jittered exponential backoff?"
FWIW I’ve basically been given basically this exact requirement by a partner with a crappy API.
We’d get on calls with them and they’d be like “you can’t do multithreading!” we eventually parsed out that what they literally meant was that we could only make a single request to their API at a time. We’d had to integrate with them, and they weren’t going to fix it on their side.
(Our solve ended being a lot more complicated than this, as we had multiple processes across multiple machines that were potentially making concurrent requests.)
So in the end it had to be funneled to a single server keeping a list of requests to make serially to their API?
That's the easy way to do it, the fun one is implementing a distributed lock/queue.
Not actually that hard with a redis lock or any database (Postgres has a specific lock for this but you could also just use a record in a table)
Far easier than the original single threaded solution - and has fault tolerance baked in cause you can run it on multiple clients
> Not actually that hard with a redis lock or any database (Postgres has a specific lock for this but you could also just use a record in a table)
Redis is just another SPOF, and so is Postgres without fiddly third party extensions (that are pretty unreliable in practice, IME). I'm talking about something truly distributed.
Because it was written in ALGOL 60, none of the mainframe devs are willing to touch that code, and the dozen other clients probably depend on the broken functionality.
That makes it even better, the candidate should ask clarifying questions. I've worked with people who, when encountering some amount of ambiguity, either throw their hands up, or make some random assumptions. Ability to communicate effectively to bridge the gaps in understanding is what I'd expect from any candidate, especially more senior ones.
But that doesn’t work. One could ask why server can handle only one request? Why can’t we upgrade (vertically or horizontally) the server? Why the logic needs to live in the client? And a large etc.
It’s not the ability to communicate effectively that’s at play here, it’s your ability to read your interviewer’s thoughts. Sure thing, if you work with stakeholders, you need some of that as well, but you typically can iterate with them as needed, whereas you have a single shot in the interview.
Plenty of times, at the end of the interview, I do have a better mental picture of the problem and can come up with a way better solution, but “hey, 1h has already passed so get the fuck out of here. Next!”
Sure, but this isn't a back&forth interview - it's a blog post. The author could have included a section with clarifying questions they expect the candidate to ask, and responses to those questions.
As it stands, we still don't know why the server was broken in this way and why they created a work around in the client instead of fixing the server.
adding the delay is where it throws me off.
what is the delay actually doing? does it actually introduce bugs into that backend? how do we check that?
Absolutely. And it isn’t just about JS, it is about the JS style thinking.
Yeah, I really don’t see how this is a sensible interview question. It does not even mention async await syntax. Expecting knowledge on callbacks seems dated.
As a self promoting post I think the author did a good job. As an interview format, I would rather work somewhere less ego driven development and more real problem oriented workplace. But that is just me. Someone could prefer these kind of interviews. I also did a set of questions for java engineers in the past and I always felt there is something really icky. I also noticed the engineers with huge ego revel in these kind of candidate assessments as it makes the feel good, but the candidate performance is poorly tested. Thats what the probation period is for. Just ask the candidate whats his experience. Asking these "cleverly" designed problems is nice for the interviever importance of keeping his job, but is not really usefull. You could even miss a good engineer. Perhaps i see this too narrow and you just really want to observe what the candidate is thinking, but you could make a couple of not really complicated questions and you could see where he is at. I dont bite this head-game at all.
I agree to a point. For me, what chaffs is the convulted prompt that goes against all my instincts for how to design something simply and clearly.
"Ok, but if you had to code something convulted and illogical..." I tend to have trouble with these sorts of black box problems not because of the challenge but because of going down the path feels wrong I would expect my day to day at the company would be surrounded by too clever solutions.
Also, recognize a minimum requirement to solve this under interview pressure is a lot of low-level futzing with Javascript async and timeout details. Not everyone comes in with that knowledge or experience, and it's fine if that is a hard requirement but it seems ancillary to the goal of "interviewing engineers". I can't imagine anyone solving this or even knowing how to prompt AI in the right ways without a fair bit of prior knowledge.
for the record (and disregarding how appropriate this is as an interview question): in JS you can (ab)use the event loop and promise chains to do this for you without managing any queues or lists manually. You have a single `let job = Promise.success();` as a global var, and scheduling a new job becomes `job = job.then(f, errHandler).then(callback, errHandler)`. It's a nightmare to debug (because you can't "see" the in-process queue) but it means you don't have to muck around with manual lists, queues, loops, shift/unshift, "isProcessing" flags etc, all of which is basically you reimplementing that native functionality in user space. It completely sidesteps the bug of TFAs naive implementation.
Not advocating for this in prod but in the context of a programming puzzle it can be neat.
late edit: ironically this is also a comment on the LLM talk in TFA: messing with the event loop like this can give you a strong mental model of JS semantics. Using LLMs I would just have accepted a loop and never learned about promise chains. This is the risk in using LLMs: you plateau. If you will allow a tortured metaphor: my naive understanding of SR is that you always move at light speed, but in 4 dimensions, so the faster you move in the 3D world, the slower you move through time, and vice versa. Skill is similar: your skill vector is always a fixed size (= "talent"?). If you use LLMs, it's basically flat: complete tasks fast but learn nothing. Without them, you move diagonally upwards: always improving, but slower in the "task completion" plane. Are you ready to plateau?
If you don't care about the order of requests then you can just set up a flag to denote if a task is running, and keep rescheduling the other tasks. Something like
should do the trick. You can test it with BTW, for 4 scheduled tasks, it basically always keeps the order, and I am not sure why. Even if the first task always runs first, the rest 3 should race each other. 5 simultaneously scheduled tasks ruins the order.Nesting at 5 deep increases the timeouts to 4ms! TIL
https://developer.mozilla.org/en-US/docs/Web/API/Window/setT...
I expected this to be the answer. I guess the interview is not necessarily for JavaScript programmers, but this seems like the correct solution. It brings in some facilities for dealing with errors, too.
Honestly that’s not even an abuse of the event loop / Promises. Making a queue like this is literally one of the intended uses of Promises.
echoing the other comments about this being a rather terrible interview question...
> this interview can be given in JavaScript or any other language
it's a language-agnostic question...but it revolves around the assumption of making a callback on request completion. which is common in JS, but if you were solving this in some other language, that's usually not idiomatic at all.
followed by:
> For candidates without JavaScript experience or doing this interview in pseudo-code, you have to tell them that there's another function available to them now with the following signature:
> declare function setTimeout(callback: () => void, delayMs: number): number;
so you add in this curveball of delaying requests (it's unclear why?), and it's trivial to solve...using a function from the JS stdlib. and if the candidate is not using JS, you need to tell them "oh there's a function from JS that you can assume is available"
> After sendOnce is implemented, it's time to make the interview a lot more interesting. This is where you can start to distinguish less skilled software engineers from more skilled software engineers. You can do this by adding a bunch of new requirements to the problem
as you originally specified it, this code is a workaround for a buggy server. and for Contrived Interview Reasons we can't modify the server at all, only the client.
in that scenario, "extend it into a generic queue with a bunch of bells and whistles" is maybe the worst design decision you could pursue? this thing, if it existed in the real world, should be named something like SingleRequestQueueForWorkingAroundHopelesslyBuggyServer with comments explaining the backstory for why it needs to exist. working around the hopelessly buggy server should be roped off into one small corner of the codebase, and not allowed to infect other code that makes normal requests to non-buggy servers.
I dunno about you, but I spend a good amount of time writing my way around buggy servers that I can't change. It seems pretty realistic to me.
I think we all have but that doesn't change that this is almost exclusively a js specific interview question with a very js'y solution to the point of hammering in a imagined "js land" api.
I am not against testing deeper language understanding for a job that requires it but the layers of contrivances to make it "not only js" rightfully rubs non-js devs the wrong way. This comes from someone who loves them some js.
The AI ick at the end makes what would have been mildly interesting, incoherent and uninteresting.
Maybe I came into this article knowing too much about the solution, but I dont agree with commenters saying this is a poorly designed interview question. Its a blog post as well, not the format that would be presented to a candidate.
I think it has clear requirements and opportunities for nudges from the interviewer without invalidating the assessment (when someone inevitably gets tunnel vision on one particular requirement). It has plenty of ways for an interviewee to demonstrate their knowledge and solve the problem in different ways.
Ive run debounce interview questions that attempt to exercise similar competency from candidates, with layering on of requirements time allowing (leading/trailing edge, cancel, etc) and this queue form honestly feels closer to what Id expect devs to actually have built in their day to day.
Same here. I thought that this specific problem is not that uncommon. On top of my mind: say if the endpoint you're hitting is rate-limited. It doesn't even have to be an API call. I think I've probably written something with the same pattern once or twice before.
I do agree that this is quite javascript specific though.
If it’s rate limited it’s handling the concurrency for you. Just back off from the rate limit.
I feel similarly and again.
We actually have this pattern in our codebase and, while we don’t have all the features on top, it’s a succinct enough thing to understand that also gives lots of opportunity for discussion.
Here’s an idea for fair interviews:
Interviewer and candidate meet at time X for 1h session of “live coding”. A saas throws at them both one problem at random. Let the game begin. The company can decide if they want interviewer and candidate to collaborate together to solve the problem (the saas is the judge) or perhaps they both need to play against each other and see who gets the optimal solution.
You can add a twist (faangs most likely): if the candidate submits a “better” answer than the interviewer’s , candidate takes over their job.
An LLM could be very well behind the saas.
Oh boy, I wouldn’t feel that nervous anymore in any interview. Fairness is the trick. One feels so underpowered when you know that the interviewer knows every detail about the proposed problem. But when both have no idea about the problem? That’s levelling the field!
Why would anyone agree to participate in interviews then? Do we then force developers to conduct interviews? If so, which ones? The superstars or the ones on PIP? You can see where this is going..
Might be a whoosh, but really don’t understand the idea of seeing the interviewer as an adversary. Stress in interviews comes from many places but honestly one of the roles of the interviewer is to bring it down.
I think maybe the problem being alluded to is that a lot of interviewers aren't that good at this and instead give off vibes that play up the "I'm judging you from a default presumption that I'm more competent than you" angle.
(Really, it shouldn't be surprising that most technical interviewers aren't that competent, since they usually aren't selected for it.)
Oh god. I’ve met some seriously incompetent people when interviewing - to the point where I’m glad they are the one conducting the interview cause I never want to work with them. I’ve actually finished an interview where I was the candidate with “thank you, but I don’t think this is going to work out”.
> if the candidate submits a “better” answer than the interviewer’s , candidate takes over their job
Corporate life meets the squid games (I quite like it:)
Oh I see what you're doing here...this is just an interview to massage the interviewer's ego.
It must be so boring working you
How does this interview question massage the interviewer's ego?
> "This is a good way to test how "AI-native" the candidate is."
yuck
yuck.
I've seen somewhat similar things in embedded development, e.g. ADCs with a triggered conversion mode that start a new conversion on receipt of a new trigger, abandoning a previous conversion if one was in progress. They fire an interrupt when the conversion completes. Not in any way buggy or unexpected, ICs generally either can block or can immediately respond but can't queue multiple requests.
Of course on the embedded side you're likely using C, quite likely an RTOS and thus threads, but if you're just using a superloop then you've got a single-threaded system (though with the complication of interrupt handlers) a bit like the interview asks about. I'd probably use a state machine for this with a superloop design, just about everything "async" in embedded boils down to writing a state machine & polling it. Actually writing a fully general-purpose async queue for embedded systems is rather more work, because you'll have to consider how it can be used from within the interrupt context. You really shouldn't block in an interrupt context, so all the queue operations need to be non-blocking. That turns it into something far too complex for an interview question.
Interestingly I think I would over-think this. The interviewer is assuming a single server, running in a VPS type environment. There's also no notion of state persistence/timeout/recovery etc. I think I'd immediately have started factoring those things in.
ALSO while JavaScript is a single threaded environment, the while solution would still basically work due to the scheduler (at least if you yield, await sleep, etc.)
I've implemented multiple production versions of this problem (but not in JavaScript)[1], so maybe my view of this problem is miscalibrated...
This feels both too easy and too hard for an interview? I would expect almost any new grad to be able to implement this in the language of their choice. Adding delays makes it less trivial, except that the answer is... Just use the function provided by the language. That's the right answer for real code, but what are you really assessing by asking it?
[1] https://github.com/google/guava/blob/master/guava/src/com/go...
You explained how it is too easy, so how is it also too hard?
It's too hard because the variations you could add to it (multi threading) that add enough depth to make it hard make it too hard, in my opinion. If you look at the implementation I linked in my previous comment, it's fully lock-free, which is pretty unreasonable to expect from anyone who isn't already familiar with lock free concurrency. On the other hand the version with a lock is basically identical to the single thread version. Asking for the two-lock queue is also a bad interview question because it's not something you'd reasonably expect someone to derive in an interview.
The other examples given for fleshing it out are all pretty similar; if a candidate can do one, chances are they can do the others too. If you want to get a decent signal if candidate skill, you have to ask a question easy enough that any candidate you'd accept can answer it, then incrementally add difficulty until you've given the candidate a chance to show off the limit of their abilities (at least as applied to your question).
Otherwise you ask a too-easy question which everyone nails, then make it way too hard and everyone fails. Or you ask a too-easy question and follow it up with additional enhancements that don't actually add much difficulty, and again all the candidates look similar. That's just my experience; the author seems pleased with the question so maybe they're getting good signal out of it.
> (a lot of people resort to some type of blocking sleep style function call to solve the delay part of this problem)
In many async languages you can do an async sleep (e.g. Python's asyncio.sleep()) which is a sleep that uses the event loop. Really, that's all Javascript's setTimeout() is doing anyway; it's just named differently.
Do I have to use JavaScript? I'd write it in Java in a way that it would be trivial to ramp up the number of connections in the pool once they fix their stupid server.
You can also schedule code to run each "tick" of the event loop, which is a non-blocking version of a while loop.
Or you could promisify the send function and use normal async/await.
Or you could actually spin up a new worker thread and get multithreading :P> Here's a naive, faulty implementation
For this first implementation, I don't see anything ever added to the queue. Am I missing something? New task is added to the queue if the queue is not empty only, but when the queue is empty the task is executed and the queue remains empty so in the end the queue is always empty?
Another thing is that the article emphasized that it's single threaded. That by itself guarantees that there will only ever be 1 inflight request, since calling the send() function will block until the request completes, and the callback is called.
If there is some kind of cooperative multitasking going on, then it should be noted in the pseudo code with eg. async/await or equivalent keywords. As the code is, send() never gives back control to the calling code, until it completely finishes.
JS has an event loop, it's single threaded but still lets you write asynchronous code.
let send = (payload, callback) => fetch(...).then(callback)
fetch() returns a promise synchronously, but it's not awaited.
That's how I read it too. Nothing is ever added.
That's correct.
Definitely one of those where the interviewer wants to show how smart they are.
Interviews are a two way street. If you strongly imply that working around servers that only do one thing is part of your day to day work, a lot of people will want to work somewhere they can learn about more modern software.
If I were asked this question, the first thing I said would be this is a poorly designed architecture. Client is the poor place to do throttling by itself. It has no information on the aggregated load of the system. It makes assumption that leads to complicate code in the sample code. There're more robust and better ways to do flow control and throttling.
the intro isnt throttling, its request serialization. there isnt some limit to keep your requests to, just that its one at a time. it could go as fast or as slow as the individual requests finish.
its still not a great architecture, but its different from throttling
> But that server is faulty!! If it has to handle multiple requests at once, it starts to break down. So, we decide to make our server's life easier by trying to ensure, from the client, that it doesn't ever have to handle more than one request at once
I made use of this in my LisaGUI project; I referenced an absolutely fantastic example on this on SO: https://stackoverflow.com/a/63208885
Promises in JS make this stuff much easier (at least to my mind):
const lockify = f => {
Easier to write. But there is a case to be made that code which can be understood without understanding somewhat esoteric language internals is superior.
Is code wrote for a broken server.
It makes no sense even with common js idiom.
I'd just have them play Factorio and watch how they reason.
I did this in the firmware of a VoIP base station.
I was informed by the radio firmware guys that a certain kind of request from the host could not be handled concurrently by the radio module due to an unchecked conflict over some global piece of memory or whatever.
I create a wait-free circular buffer for serializing the requests of that type, where the replies from the previous request would kick down the next one.
No mutexes, only atomic compare-swap.
How did you make it wait free with only compare and swap?
The use-case described is ill suited to be addressed by the client.
Which make the whole coding exercise moot.
What if there are 1 million users opening the browser at the same time?
The queue question is fun but doing it in the client is not right.
This is addressed in the article.
> So, we decide to make our server's life easier by trying to ensure, from the client, that it doesn't ever have to handle more than one request at once (at least from the same client, so we can assume this is a single-server per-client type of architecture).
This might be a server interacting with another server.
It’s funny because I have had ti implement “serialized fetch()” a few times recently, with delays and random jitter too.
I think this question is a bit confusing in its wording even though the concept is actually quite useful in practice. First, async queues have nothing to do with network coms. You can have a async queues for local tasks.
Also while it is obvious to most that you shouldn’t do this, you can also satisfy the requirements to this task by polling the queue and flag using setTimeout() or setInterval(): on invocation, check if there is anything in the queue and if so, if we aren’t waiting on a response fire off the next send().
Retry logic with this system is always a problem. Do you block the queue forever by retrying a request that will never complete (which lets the queue grow infinite in size), or do you give up after some number of retired? If you give up, does that invalidate all queued requests? Some? None? This becomes application-specific. For this kind of thing I have implemented it using multiple parallel queues. That is, you request a send() but using a specifically named queue so that if one queue’s serialized requests break, other queues aren’t affected.
If you do something like `sendOnce(payloadA, callbackA, 5000); sendOnce(payloadB, callbackB, 1);` should payloadB be sent in 1ms or 5000 + RTT + 1ms?
You could solve this in the JavaScript environment by using something like WebSockets or WebTransport much more trivially than by using send() which is I assume a thinly veiled fetch(). This probably fails OP’s interview but in reality leverages the lower level queueing/buffering.
A more fun and likely more illuminating question would be to do something like provide a version of send() that uses a callback for the response and ask to convert it to a promise. This is a really fun one that I had to deal with when using WebCodecs: a video decoder uses callbacks to give you frames but for example Safari has a bug where it will return frames that are encoded as delta frames out of presentation order. So the much better API is to feed a bunch of demuxed encoded chunks to a wrapper around VideoDecoder, and then wait for the resolution (or rejection) of a promise where the result is all the decoded frames at once. This problem really gets at the concept of callbacks vs promises which I think is the right level of abstraction for evaluating how someone thinks of single threaded concurrency. You also can get a really good feel for a person’s attitude here if they refuse to use callbacks or promises (or the async/await sugar around promises).
“Can you work out the tricks that require this previous experience? If you can then you’re smart if not then you’re worthless.”
Just say no thanks and walk out if this is their core way to assess your capabilities.
In another thread I asked if leetcode style questions are still common, and the answer I got was yes, so where would I encounter this kind of question? I only ever got leetcode style questions or something like "what is the difference between var and let"
Why is the method called sendOnce? It’s send with a capacity limiter / semaphore right, so what about it is Once?
The minDelay extension feels contrived and also the solution sucks. None of the pending requests are actually added to the queue until the timeout is finished, meaning you have no knowledge of all these delayed requests until the timeout passes and they all enqueue themselves
I don’t know anything about the author, so just speculating here: assuming that the interview lasts 1h, it’s not realistic (nor fair) to judge the candidate’s answer if the interviewer has spent more than 1h to think about the problem and potential solution(s).
Interviewers have thought about the problem they propose countless of times (at least once per interview they have hold) each time refines their understanding of the problem, and so they become god of their tiny realm. Candidates have less than one hour, add to that stress and a single shot to get it more or less right. You’re not assessing candidate’s ability to code nor their ability to handle new requirements as they come.
So do you want to give candidates infinite time (which they won't have on-the-job) or not attempt to assess their coding ability or what?
thanks for sharing and by reading the blogpost and the comments I think I get the whole point: it's all about how engineers understand the requests and the reasoning about how does it approach that more than the code itself. If this raw code really works or not it's almost secondary here - IMHO nobody I'll start coding a real queue out of blue like this.
I’m really confused why this is an “async queue.” Seems pretty synchronous to me since requests are completed in order, one at a time. I literally wrote something to do this in the past few months. This was to work around JavaScript’s asynchronous IO making a shit show of updates from library being used in the client. I had to queue requests in JavaScript, have them execute in order (FIFO), and explicitly described it “synchronous.”
Is it only “async” because it’s doing it in JavaScript and the underlying network request API is asynchronous? Seems like, IMHO, a really bad way to describe the desired result since all IO in JavaScript is going to be async by default.
the async part isnt very exciting, but its the callback after the entry has been through the queue and worked on.
its certainly serialized, but nothing fancy otherwise.
it would be synchronous if you blocked the requester until the request go through the queue and then completed. you wouldnt need to introduce an async/await.
you can see examples in JS on the node FS functions. the defualt ones are async, but they have some magic wrappers that make it actually sychronous and block the event loop from running until the file is loaded
Is the send function considered non-blocking?
Why would it have a completion callback if it wasn't?
The explanation is way too long, in an area that is pretty big and can be done in many ways. Couple this with candidates who will variously be fearful of asking to many or too few questions, and you just have confusion about who is good and who is not.
This is one of the most confusing and badly worded interview problems I've ever seen. If I had been given this problem, I'd view it as a signal that I'd be wasting my time working with the folks that thought it was good.
Hmm… this code doesn’t work in the real world unless you only run it on a single machine. Perhaps a more interesting question is how to make a multi-node queue with max N concurrent requests.
This is handled in the framing of the question:
“… it doesn't ever have to handle more than one request at once (at least from the same client, so we can assume this is a single-server per-client type of architecture).“
For sure a multithreaded async queue would be a very interesting interview, but if you started with the send system the interview is constructed around youd run out of time quickly.
The whole point of this interview is that the candidate is operating on a single-threaded environment.
These are multiple assumptions "This queue is only on one machine and on one thread", what's the real world use-case here? Not saying there's none but make it clear. I wouldn't want to work for a company that has to think of some random precise question instead of e.g. "when would you not use mysql?"
I guess I don’t want to hire candidates who assume the world is single-threaded