I am trying to make use of vscode's window.showInformationMessage method during a command that takes a screenshot of the current screen. After the screenshot has been taken, I use
await window.showInformationMessage(`File saved to ${path}`,"Open", "Copy Path");
Which gives the user the option to either open their saved image in a file explorer or copy the path to the clipboard. However, if the user does not do anything when the Information Message dialog pops up, then this call never resolves. On top of that, the user can run the screenshot command as many times as they would like, and each time the code execution would halt, waiting for the promise to resolve.
I have used two different methods to solve this:
Use a Promise.race with one parameter being a setTimeout promise
Use a .then at the end of the call to showInformationMessage, and remove the async.
QUESTION 1: what is happening under the hood here? How can I run this command many times if node runs on a single thread? Is another thread being created for each command call or is there a new instance of the extension being created each time I call this command?
QUESTION 2: What is a good way to see all of this? I have used the debugger but it hasn't helped much.
Related
Here is what I'm doing (using this: https://firebase.google.com/docs/functions/task-functions):
Launch an array of callable functions from the site (up to 500 cloud functions are launched after the click of a button from each user) - The same cloud function is called 500 times
Gets them in a queue to be processed at the desired rate
Each of the functions has the same task:
- Get a specific file from an API call (which takes some time)
- Download it to firebase storage (also not instant)
- Finally, update the Firestore database accordingly
Here is my issue:
Doing this is working fine with one user, however, having 2 or more users at the same time will not scale as wanted.
Indeed, the second user has to wait for the 500 cloud functions from the first user to be completed before it can start running its own 500 functions. (Which can take 30min) (Since they get added to the queue)
Edit: As the first comment said, the first user is not actually waiting on all 500 to run some for the second user to proceed, however, the point is that both users are "conflicting" (increase the time of the first user process), and will conflict even more if another user come to start his process as well
So my questions are:
Is there a way to have a queue specific to each user somehow?
If not, how should I approach this using cloud functions? Is this possible?
If not possible with cloud functions, what would you advise?
Any help will be appreciated
Edit: Possible solutions I'm thinking of so far:
1- Minimize the time each of the functions takes and increase the number of function that can run in parallel without exceeding API call possibilities
2- Handle all the work into one big function per user call (without going to the 9min limit if possible) (that means having a 500 array loop inside the function instead of launching 500 cloud functions)
3- Others?
So I'm trying to have my bot restart ENTIRELY on encountering an error. The reason why I don't just let it sift through connection errors is because, whenever I encounter an internet issue, code starts repeating multiple times since the original node process hasn't been terminated, which technically I could fix but other connections to external apis stop working too. So ignoring fixing singular issues, I just want to restart entirely.
What I'm doing currently is using node child_process, with this function:
spawn(process.argv.shift(), process.argv, {
cwd: process.cwd(),
detached : true,
stdio: "inherit"
});
process.exit();
I do know stdio inherit does nothing, since its exiting the parent process, but it doesn't really change anything to put it to ignore so i've just left it. Basically this works in theory, if I use a command to execute this, i can do it over and over and over and it will work fine, singular discord client, no repeats, it's up, i just can't monitor it since my original terminal is disconnected, and I can use a command to exit the current process so it's not stuck since I don't have a terminal to ctrl-c. But once put in practice, executing the function in bot.on("error") by disconnecting my internet seems to work, it ends the first process, but upon regaining internet there is no client connected.
My guess here: bot.on("error") will not be re-executed in the next process due to no discord client being made.
So I don't know if I'm making this too complicated or if I need to add a lot more. If this is the best way to do it then all I would need to solve is to wait until I have internet back and then make a new process or something like that. I'm not educated in fiddling with node so if any answers could be beginner friendly (mainly for node) i'd really appreciate it.
bot.on("error", (err) => {
process.exit(0)
});
Should work, it'll restart the bot when there's an error.
Unsure what you mean by
My guess here: bot.on("error") will not be re-executed in the next process due to no discord client being made.
As long as you bot it in the same code as your startup, it'll restart the bot.
If you use a batch-file to run your bot simply add :a before the node . and goto a at the end.
The following code should write back everything the user puts in:
process.stdin.on('data', blob => {
process.stdout.write(blob)
})
Indeed it does, but when I change on to once I expect the script to only write back one line and then exit:
process.stdin.once('data', blob => {
process.stdout.write(blob)
})
However, it does not exit. Nothing ever happens again, no lines are written back, but the script keeps on running.
Looking at the documentation of once, I would expect it to exit since the documentation states:
The next time eventName is triggered, this listener is removed and then invoked.
Wouldn't that mean that the event loop queue becomes empty?
node process doesn't exit after firebase once seems relevant but the accepted answer now states:
Note that this is no longer applicable. Node.js will no longer hang when using once(), although it will be held open as long as there are active listeners subscribed to the remote server.
Which doesn't seem the case here.
I want to check the time difference between when a command is executed and when the parameter specified in the command states it should end. I have an idea of how to do this, but if i merely stick a loop in my index.js which is the main file that I have the command group names stored will the loop continue to run without it stopping the bot from receiving input from people typing a command in a discord channel (like !flip)? How would I go about making it so it won't stop the other input if it does?
For this you will need to make use of async as otherwise node will wait for the loop to finish.
Try putting
<client>.on('message', async message => { /*code*/})
I created a Node.js API.
When this API gets called I return to the caller fairly quickly. Which is good.
But now I also want API to call or launch an different API or function or something that will go off and run on it's own. Kind of like calling a child process with child.unref(). In fact, I would use child.spawn() but I don't see how to have spawn() call another API. Maybe that alone would be my answer?
Of this other process, I don't care if it crashes or finishes without error.
So it doesn't need to be attached to anything. But if it does remain attached to the Node.js console then icing on the cake.
I'm still thinking about how to identify & what to do if the spawn somehow gets caught up in running a really long time. But ready to cross that part of this yet.
Your thoughts on what I might be able to do?
I guess I could child.spawn('node', [somescript])
What do you think?
I would have to explore if my cloud host will permit this too.
You need to specify exactly what the other spawned thing is supposed to do. If it is calling an HTTP API, with Node.js you should not launch a new process to do that. Node is built to run HTTP requests asynchronously.
The normal pattern, if you really need some stuff to happen in a different process, is to use something like a message queue, the cluster module, or other messaging/queue between processes that the worker will monitor, and the worker is usually set up to handle some particular task or set of tasks this way. It is pretty unusual to be spawning another process after receiving an HTTP request since launching new processes is pretty heavy-weight and can use up all of your server resources if you aren't careful, and due to Node's async capabilities usually isn't necessary especially for things mainly involving IO.
This is from a test API I built some time ago. Note I'm even passing a value into the script as a parameter.
router.put('/test', function (req, res, next) {
var u = req.body.u;
var cp = require('child_process');
var c = cp.spawn('node', ['yourtest.js', '"' + u + '"'], { detach: true });
c.unref();
res.sendStatus(200);
});
The yourtest.js script can be just about anything you want it to be. But I thought I would have enjoy learning more if I thought to first treat the script as a node.js console desktop app. FIRST get your yourtest.js script to run without error by manually running/testing it from your console's command line node yourstest.js yourparamtervalue THEN integrate it in to the child.spawn()
var u = process.argv[2];
console.log('f2u', u);
function f1() {
console.log('f1-hello');
}
function f2() {
console.log('f2-hello');
}
setTimeout(f2, 3000); // wait 3 second before execution f2(). I do this just for troubleshooting. You can watch node.exe open and then close in TaskManager if node.exe is running long enough.
f1();