AsapScheduler can interrupt random intervals
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 31.7k
- Forks
- 3k
- PR merge metrics
- No merged PRs in 30d
Description
Describe the bug
An interval scheduled somewhere else (including rxjs timer) can be unduly canceled by AsapScheduler implementation:
- Create a timer with
timer(0, intervalDuration, asapScheduler), withintervalDuration > 0 - The timer method calls
scheduler.schedule(callback, 0)(https://github.com/ReactiveX/rxjs/blob/7.8.2/src/internal/observable/timer.ts#L170C12-L170C30) - The
asapSchedulergenerates an ID fromImmediate, we can call itimmediateId(https://github.com/ReactiveX/rxjs/blob/7.8.2/src/internal/util/Immediate.ts#L24) - The callback reschedules itself calling
schedule(undefined, intervalDuration) - In https://github.com/ReactiveX/rxjs/blob/7.8.2/src/internal/scheduler/AsyncAction.ts#L52,
this.id != null, sothis.recycleAsyncId(scheduler, id, delay)is called with theid = immediateIdand non-zerodelay. asapActionfalls back toayncActionimplementation ofrecycleAsyncIdbecausedelayis non-zero (https://github.com/ReactiveX/rxjs/blob/7.8.2/src/internal/scheduler/AsapAction.ts#L30)asynAction.recycleAsyncIdunduly clears an interval withid = immediateIdhttps://github.com/ReactiveX/rxjs/blob/7.8.2/src/internal/scheduler/AsyncAction.ts#L79
Expected behavior
The AsapScheduler should be protected in order not to affect unrelated code.
The AsyncScheduler could be protected as well by using the type-system to ensure that only ids generated by setInterval are passed to clearInterval
Reproduction code
import { asapScheduler, timer } from 'rxjs';
let n = 0;
const a = setInterval(() => console.log(n++), 200);
console.log(`interval id: ${a}`);
setTimeout(() => {
timer(0, 10000, asapScheduler).subscribe(() => console.log("I did not eat the other interval"));
}, 1);
setTimeout(() => {
timer(0, 10000, asapScheduler).subscribe(() => console.log("I did not eat the other interval"));
}, 2);
setTimeout(() => {
timer(0, 10000, asapScheduler).subscribe(() => console.log("I ate the other interval"));
}, 3);
Reproduction URL
No response
Version
<= 7.8.2
Environment
Any environment. Happens at least in
- Firefox 147
- Chromium 145
- Node version v22.20.0
The reproduction code was tested in Node 22.20.0
Additional context
No response
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
Trace the scheduling flow through src/internal/scheduler/AsapAction.ts and AsyncAction.ts, using Immediate.ts and timer.ts as the documented entry points. Run the reproduction with the listed browser or Node environments, then verify that an asapScheduler timer no longer cancels an unrelated setInterval and add regression coverage for that behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript, typescript
- Domain
- tooling
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Clearly specified
- Newbie friendliness
- 56/100