Documenting Library Limits

The Course
•
4 min read

Good API documentation tells callers how to use the library correctly and what it cannot guarantee. Our limit caps active mapper calls from 1 to 64. It does not promise CPU parallelism, constant total memory, a timeout, retries, or interruption of a noncooperating callback.

The rejection boundary is especially important: the pool waits for already active callbacks. If a callback ignores abort and never settles, neither does the pool. A caller needing a deadline must design the work itself to stop or settle, not only race an unrelated timer and pretend the underlying resource disappeared.

Input order determines output positions; first observed failure determines the primary failure. A single phrase such as “fast and safe” does not communicate either rule. Pair each guarantee with a small example and a test location.

For extensions, change the contract before the implementation. Streaming results would need a new ordering and buffering policy. Supporting async iterables would require serializing next requests and waiting for async cleanup. Those are separate APIs, not a one-line promise to support everything.

Predict, run, and explain

Write the output and trace the important state changes before checking it. Then run the program. Each editor is independent. Async examples end with main() so this editor waits for their work.

Predict, then run JavaScript
const guarantees = [
  "bounded active calls",
  "input-order results",
  "cooperative abort"
];

console.log(guarantees.join("; "));
Check your prediction
bounded active calls; input-order results; cooperative abort

Replace vague promises with observable rules

A useful guarantee names a trigger, outcome and limit. After first observed mapper failure, the pool stops pulling but waits for active callbacks: that sentence specifies both behavior and settlement. Finite input and eventually settling callbacks are assumptions the caller supplies. Bounded concurrency alone promises neither constant result memory nor interruption of uncooperative work.

Boundary or caseWhat to inspect
OrderOutput follows input positions rather than completion
CancellationSignal requests cooperation and cannot undo side effects
OwnershipItems remain shared references and collected results consume growing storage

Write a counterexample to instant cancellation or constant memory, then state the narrower guarantee this API actually supports. Link it to a distinguishing test. Specify an extension’s new ordering and cleanup policy before promising streaming or asynchronous sources.

Your turn

Exercise

Documenting Library Limits: practise

Implement validateLimit(value) returning the input if it is an integer 1–64, otherwise throwing RangeError. Print 1 and 64, then rejected for 0. Keep the assertion about rejection outside its try block.

Your workspace JavaScript
// This is a boundary contract, not an automatic performance recommendation.
Hint 1: the idea

Both endpoints are inclusive.

Hint 2: a first step

Check integer status and the lower and upper bounds.

Show one solution
function validateLimit(value) {
  if (!Number.isInteger(value) || value < 1 || value > 64) {
    throw new RangeError("Invalid limit");
  }

  return value;
}

console.log(validateLimit(1));
console.log(validateLimit(64));

let rejected = false;

try {
  validateLimit(0);
} catch (error) {
  rejected = error instanceof RangeError;
}

if (!rejected) {
  throw new Error("Expected rejection");
}

console.log("rejected");
1
64
rejected

Explain why the implementation meets the stated contract. Which part is enforced by the language or checker, and which part needs behavioral evidence?

Change it and test it

Draft a README paragraph for a caller with slow, occasionally failing callbacks. Include settlement timing, cleanup ownership and retained output. Then propose one extension and list the extra tests required before advertising it.

Was this article helpful?

Your response is saved on this device.