The Re-Mirror Storm — JavaScript Bug Hunt
Modelled on the Amazon EBS outage of 21 April 2011: a network change routed traffic onto a low-capacity network.
- Language: JavaScript
- Layer: Backend
- Difficulty: Hard
- Concepts: Retries, Backpressure
- Modelled on: Amazon EBS · 2011
- Visible tests: volumes are placed when capacity exists; a full cluster does not produce a storm
- Reward: 50 XP for a complete fix
Briefing
Modelled on the Amazon EBS outage of 21 April 2011: a network change routed traffic onto a low-capacity network. Volumes that lost their mirror immediately searched the cluster for space, and because they retried without backoff they consumed the remaining capacity and blocked each other — a "re-mirroring storm" that took down Reddit, Quora and Heroku for days.
mirror.js retries the search on every tick with no backoff and no cap.
Fix reMirror so a volume that cannot find space backs off instead of retrying immediately, and the cluster's free capacity is never oversubscribed.
Bug report
BUG-EBS0421 · Priority: Critical · Reported by: storage
reMirror(cluster, volumes, ticks) must return { placed, attempts }:
- each tick, every unplaced volume whose backoff has expired tries once to take one unit of cluster.free
- a failed attempt doubles that volume's backoff (starting at 1), so it waits that many ticks before trying again
- cluster.free must never go negative
Observed: with no free capacity, every volume retries on every tick. The attempt count explodes and nothing ever gets placed.
Logs
[ebs] free=0 attempts=1284000 placed=0
[ebs] control plane saturated by re-mirror requestsThe code as shipped
src/storage/mirror.js (editable)
// Re-mirrors volumes that lost their replica.
exports.reMirror = function (cluster, volumes, ticks) {
var placed = 0;
var attempts = 0;
var state = [];
for (var i = 0; i < volumes.length; i++) state.push({ done: false });
for (var t = 0; t < ticks; t++) {
for (var v = 0; v < volumes.length; v++) {
if (state[v].done) continue;
attempts++;
if (cluster.free > 0) {
cluster.free--;
state[v].done = true;
placed++;
}
}
}
return { placed: placed, attempts: attempts };
};
Read-only context: src/storage/BACKOFF.js.
Open the hunt to edit the files, run the visible tests and submit against the hidden ones. More JavaScript bug hunts.