octokit.js
octokit.js copied to clipboard
Deno: `deno run` does not exit
Follow up to https://github.com/octokit/octokit.js/issues/2075
What happened?
@laughedelic was able to narrow down the problem to the throttle plugin.
import { Octokit } from "https://cdn.skypack.dev/@octokit/core"; import { throttling } from "https://cdn.skypack.dev/@octokit/plugin-throttling"; const MyOctokit = Octokit.plugin(throttling); const octokit = new MyOctokit({ auth: Deno.env.get("GITHUB_TOKEN"), throttle: { onRateLimit: (retryAfter: any, options: any, octokit: any) => { return true; }, onAbuseLimit: (retryAfter: any, options: any, octokit: any) => { octokit.log.warn(`Abuse detected for request ${options.method} ${options.url}`); }, }, }); octokit.log.warn("foo");
It prints
foo
and hangs. If I remove everything relatedthrottling
, it prints the message and exits.A workaround for this hanging is to add
Deno.exit(0)
at the end.
What did you expect to happen?
The deno process should exit, just like Node does
What the problem might be
The throttle plugin is using bottleneck by @SGrondin. Maybe it's a known issue?
I'd appreciate if someone with more deno experience could try to reproduce the hanging problem with just Bottleneck. The sourcecode where we use bottleneck
is here: https://github.com/octokit/plugin-throttling.js/
Hey, Deno maintainer here :wave: I was actually just trying to use octokit to extract our release download stats and hit this issue. So far my script is as simple as it gets :
const octokit = new Octokit({ auth: Deno.env.get("GITHUB_TOKEN") });
const repo = await octokit.rest.repos.get({
owner: "denoland",
repo: "deno",
});
I also traced it down to plugin-throttling, I'll try to get a minimal repro with just Bottleneck next week. Don't hesitate to contact me too if you happen to be working on it.
thank you so much @wperron for looking into it! Please let me know if there is anything that I can help with
I believe I found the reason for the hang, probably around the _startAutoCleanup
function in Bottleneck (here).
In Deno, just like in the browser setInterval
returns an IntervalID as opposed to the Timeout
object returned by Node.js's setInterval
. I have made the following little script to highlight the differences in Node.js and Deno
// Nodejs: `node this.js`
// Deno: `deno run this.js`
const base = setInterval(() => {}, 1);
if (typeof base.unref === "function") {
base.unref();
} else {
console.log("can't unref");
}
Without using the unref
they both hang forever. unref
allows Node to exit when it reaches the end of the script, regardless of the interval running in the background. I have a suspicion that the hang is also present when using octokit directly in the browser as an ES Module, but that due to the nature of how browsers work, it's simply not being noticed. I'm having issues with Skypack at the moment so Octokit simply won't load. I'll try again soon and confirm whether or not my hypothesis is correct.
hi pls help me i have no idea
{"crashreporter_key":"43cd7e99167b919a3a11347cf6ecf9d47f733c14","bug_type":"211","timestamp":"2022-08-05 07:00:58.00 +0700","os_version":"iPhone OS 15.5 (19F77)","incident_id":"CF2E895A-09E5-4EB6-9A65-D4BF657E9960"}
{"_marker":"
@wperron I'm still running into this today. As a workaround I'm ending my program with a Deno.exit(0)
now but I was wondering if there is anything I could do or contribute to avoid that. Any ideas?