Skip to content

Commit d708bb6

Browse files
authored
feat: allow changing repeating task interval and timeout (#2934)
To allow for changing the frequency and timeout of repeating tasks add `setInterval` and `setTimeout` methods to the task. This lets us repeat a task often to start with, then slow down the repetition once a successful result has occured.
1 parent 80ddad5 commit d708bb6

File tree

2 files changed

+91
-0
lines changed

2 files changed

+91
-0
lines changed

packages/utils/src/repeating-task.ts

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,34 @@ import { anySignal } from 'any-signal'
33
import type { AbortOptions } from '@libp2p/interface'
44

55
export interface RepeatingTask {
6+
/**
7+
* Update the interval after which the next iteration of the task will run.
8+
*
9+
* This is useful if, for example, you want to retry a task with a short rest
10+
* duration until it succeeds, then periodically after that.
11+
*
12+
* This only affects the next iteration of the task, if it is currently
13+
* running, that run will not be interrupted.
14+
*/
15+
setInterval(ms: number): void
16+
17+
/**
18+
* Update the amount of time a task will run before the passed abort signal
19+
* will fire.
20+
*
21+
* * This only affects the next iteration of the task, if it is currently
22+
* running, that run will not be interrupted.
23+
*/
24+
setTimeout(ms: number): void
25+
26+
/**
27+
* Start the task running
28+
*/
629
start(): void
30+
31+
/**
32+
* Stop the task running
33+
*/
734
stop(): void
835
}
936

@@ -16,6 +43,8 @@ export interface RepeatingTaskOptions {
1643

1744
/**
1845
* Whether to schedule the task to run immediately
46+
*
47+
* @default false
1948
*/
2049
runImmediately?: boolean
2150
}
@@ -54,6 +83,22 @@ export function repeatingTask (fn: (options?: AbortOptions) => void | Promise<vo
5483
let started = false
5584

5685
return {
86+
setInterval: (ms) => {
87+
interval = ms
88+
89+
// maybe reschedule
90+
if (timeout != null) {
91+
clearTimeout(timeout)
92+
timeout = setTimeout(runTask, interval)
93+
}
94+
},
95+
setTimeout: (ms) => {
96+
if (options == null) {
97+
options = {}
98+
}
99+
100+
options.timeout = ms
101+
},
57102
start: () => {
58103
if (started) {
59104
return

packages/utils/test/repeating-task.spec.ts

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,4 +67,50 @@ describe('repeating-task', () => {
6767

6868
expect(count).to.be.greaterThan(1)
6969
})
70+
71+
it('should update the interval of a task', async () => {
72+
let count = 0
73+
74+
const task = repeatingTask(() => {
75+
count++
76+
77+
if (count === 1) {
78+
task.setInterval(2000)
79+
}
80+
}, 100)
81+
task.start()
82+
83+
await delay(1000)
84+
85+
task.stop()
86+
87+
expect(count).to.equal(1)
88+
})
89+
90+
it('should update the timeout of a task', async () => {
91+
let count = 0
92+
93+
const task = repeatingTask(async (options) => {
94+
// simulate a delay
95+
await delay(100)
96+
97+
if (options?.signal?.aborted !== true) {
98+
count++
99+
}
100+
101+
if (count === 1) {
102+
// set the task timeout to less than our simulated delay
103+
task.setTimeout(10)
104+
}
105+
}, 100, {
106+
timeout: 500
107+
})
108+
task.start()
109+
110+
await delay(1000)
111+
112+
task.stop()
113+
114+
expect(count).to.equal(1)
115+
})
70116
})

0 commit comments

Comments
 (0)