Skip to content

Instantly share code, notes, and snippets.

@cowboyd
Last active November 7, 2023 17:12
Show Gist options
  • Save cowboyd/0611f51cbe8b834b408c40c54d98064d to your computer and use it in GitHub Desktop.
Save cowboyd/0611f51cbe8b834b408c40c54d98064d to your computer and use it in GitHub Desktop.
Run an operation on a heartbeat, only one operation at a time
import {
call,
createSignal,
each,
type Operation,
spawn,
type Stream,
suspend,
} from "effection";
/**
* Create an infinite stream of pulses that happen on the given period.
*/
export function pulse(period: number): Stream<void, never> {
return {
*subscribe() {
let signal = createSignal<void, never>();
yield* spawn(function* () {
let intervalId = setInterval(signal.send, period);
try {
yield* suspend();
} finally {
clearInterval(intervalId);
}
});
return yield* signal.subscribe();
},
};
}
/**
* Run an operation on a heartbeat loop.
* For each tick of the loop, spawn the operation and await the next tick.
* If the next pulse happens while the spawned operation is still running, it will be shut
* down because it passes out of scope when the `call()` returns.
*/
export function* heartbeat(period: number, operation: () => Operation<unknown>): Operation<void> {
for (let _ of yield* each(pulse(period))) {
yield* call(function* () {
yield* spawn(operation);
yield* each.next();
});
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment