Add support for `AbortSignal` to allow cancellation of in-flight image processing operations.
Nobody has claimed this yet.
- Dominant language
- JavaScript
- Stars
- 32.7k
- Forks
- 1.4k
- Avg merge
- 1d 14h
- Merged PRs (30d)
- 5
Description
### What are you trying to achieve?
Add support for `AbortSignal` to allow cancellation of in-flight image processing operations.
Currently, once an image processing pipeline starts (e.g., `sharp(input).resize(...).toBuffer()`), there's no way to cancel it. This is problematic for:
- Long-running operations on large images or complex transformations
- HTTP servers that need to cancel processing when clients disconnect
- Interactive applications where users can cancel operations
- Resource-constrained environments where abandoned work should be stopped
The existing `timeout()` option provides time-based cancellation, but doesn't support event-driven or user-initiated cancellation patterns that are standard in modern Node.js APIs.
### When you searched for similar feature requests, what did you find that might be related?
Searched for: "abort", "cancel", "AbortSignal", "AbortController"
Found that the `timeout()` feature exists but is limited to time-based cancellation. There's no support for the standard `AbortSignal` API that's now ubiquitous in Node.js (fetch, streams, fs.promises, etc.).
The timeout mechanism uses libvips progress callbacks to stop processing, which provides a foundation that could be extended to support abort signals.
### What would you expect the API to look like?
```javascript
const controller = new AbortController();
// Option 1: Pass signal to constructor
const promise = sharp('input.jpg', { signal: controller.signal })
.resize(4000, 4000)
.toBuffer();
// Option 2: Pass signal to output methods
const promise = sharp('input.jpg')
.resize(4000, 4000)
.toBuffer({ signal: controller.signal });
// Option 3: Pass signal to toFile
const promise = sharp('input.jpg')
.resize(4000, 4000)
.toFile('output.jpg', { signal: controller.signal });
// Cancel the operation
controller.abort();
// Promise rejects with AbortError
// { name: 'AbortError', code: 'ABORT_ERR', message: 'The operation was aborted' }
```
The signal should be accepted in:
- `sharp()` constructor options
- `toBuffer()` options
- `toFile()` options
When aborted, processing should actually stop (not just discard the result) and reject with a standard `AbortError`.
### What alternatives have you considered?
1. **External timeout wrappers**: Using `Promise.race()` with timeouts. This doesn't actually stop the processing, just ignores the result, wasting CPU and memory.
2. **Worker thread management**: Running sharp in worker threads and terminating them. This adds complexity, doesn't integrate with Node.js cancellation patterns, and may leave resources in inconsistent states.
3. **Custom event system**: Building a sharp-specific cancellation API. This would be non-standard and require developers to learn a new pattern.
The `AbortSignal` API is the standard across Node.js and web APIs, so supporting it aligns sharp with modern JavaScript patterns and provides a familiar interface for developers.
### Please provide sample image(s) that help explain this feature
Example use case - HTTP server with request cancellation:
```javascript
app.get('/image/:id', (req, res) => {
const controller = new AbortController();
// Cancel processing if client disconnects
req.on('close', () => controller.abort());
sharp(imagePath)
.resize(800)
.toBuffer({ signal: controller.signal })
.then(buffer => res.send(buffer))
.catch(err => {
if (err.name === 'AbortError') {
console.log('Processing cancelled');
return;
}
res.status(500).send(err.message);
});
});
```
This pattern is essential for building efficient HTTP services that don't waste resources on abandoned requests.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the existing timeout feature and its libvips progress-callback mechanism, then inspect the sharp() constructor, toBuffer(), and toFile() option entry points named in the issue. Verify the chosen API accepts AbortSignal, stops in-flight processing, and rejects with the specified AbortError behavior, including cancellation through the HTTP-server example.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript, node.js
- Domain
- api, backend, performance
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100