Content AND Presentation

2020-08-03 Look up a global variable in the database in Node.js

Today I encountered an interesting problem. Assume that you want a global constant in your Node.js backend, but its actual value is to be taken from a database. This means that fetching the constant should be done asynchronously. Unless you use Node.js 14.3.0 or newer (which as the time of me writing this is not yet ubiquitous), you cannot await your database request at the top level like this:

const CONST = await Database.fetch();
// the rest of the code using CONST

(of course, Database.fetch is a fictional function returning a promise).

Still, it is fairly easy to make it work anyway with Immediately Invoked Async Function Expressions. For instance, you can say this:

const CONST = Database.fetch();
(async function() {
	const DOUBLE_CONST = 2 * await CONST;
	const TRIPLE_CONST = 3 * await CONST;
})();

The takeaway here is that the potentially time-consuming Database.fetch() will only be run once, and the value recorded and used in subsequent uses of await CONST without waiting more. Here is a short proof of the above claims:

const long_random_promise = new Promise(resolve => {
	setTimeout(() => {
		resolve(Math.random());
	}, 2000);
});

(async function() {
	console.log(await long_random_promise);
	console.log(await long_random_promise);
})();

Two seconds after launching this script in Node.js (or browser, for that matter), the same value will be logged twice in quick succession.

Granted, this technique is not the most beautiful one, but should suffice until everyone is going to have newer Node.js versions.

CategoryEnglish, CategoryBlog

Comments on this page

2020-07-26 Running Node.js scripts from the command line

A few days ago I accidentally ran Node.js from the command line with a wrong argument. I had a script – call it myscript.js – in a directory called myscript. I typed node mys in the directory one level higher, pressed tab and ended up with node myscript/, then pressed enter and got an error (obviously). So, I then cd​‘d into the right directory and (without much thinking) pressed up twice and enter. To my surprise, the script ran.

What is going on?

I tried to find some information about it in the docs or on the Internet, but to no avail. I even did some grepping in the sources, with the same (lack of) result. So, I can only guess what is going on. My suspicion is that when Node.js gets a script filename as a parameter, it runs (the equivalent of) path.resolve on it. This means that a directory name and .. cancel out (even if the directory is non-existent – path.resolve seems not to actually look at the disk), the single-dot components are left out, the trailing slashes are removed, and if the resulting path is relative, the path to the current directory is added in front of it. Then, if the file with the constructed name exists, it is called, and if not, Node.js checks if adding .js makes it into an existing file.

This means a few things. For instance, if you are in a directory whose sole contents is a Node.js script, called myscript.js, then any of these commands will run it:

node myscript.js
node myscript
node non_existent_dir/../myscript
node non_existent_dir/../myscript.js
node myscript.js/
node myscript.js/.

Also, you can run a script called myscript.js.js by saying node myscript.js, and if you have two files, myscript and myscript.js, then node myscript runs the former.

I’m not sure if any of this is useful to anyone, but here it is – now you know.

CategoryEnglish, CategoryBlog

Comments on this page

2020-07-19 List all files that were ever present in a Git repo

Sometimes I want to dig deep in Git repo history and find some information about the files that are no longer there – either they were deleted or renamed. This is easy if I know the name of the file in question, but what if not? I tried to find some information on the Internet about this, and it turned out to be surprisingly difficult. For instance, this StackOverflow answer gives a nice way to obtain the list of all files that were ever added to the repo – but it is possible that a file is (or was) present in the repo but was never added to it (how? it’s actually pretty easy, just add a file to the repo, then rename it and commit the rename!). Of course, you can use --diff-filter=AR (or even --diff-filter=D if you really only want to see the deleted files), but the whole thing, with the empty --pretty=format: and sort -u seems a kludge.

I found a nice Python script here – it looked great, but didn’t work. Turns out that it is not Python3-compatible. (The Python2/3 issue is IMHO in the top ten of the most moronic things in programming ever, right next to stuff like null-terminated strings and, yes, left-pad.) I have next to zero knowledge of Python, but I did write a couple of lines in it many years ago, and with the help of the interwebs I was apparently able to fix the issues of that script. If you install the pygit2 library and put the script somewhere in your $PATH, you can just say git ls-all-files (because of how Git implements its commands) and see all files that were present in the repo. Hopefully, it won’t break anything (doesn’t look like it could, but this is IT, so you never know…). If it breaks in some scenario, let me know, I’ll see if I can cargo-cult-code a fix.

CategoryEnglish, CategoryBlog, CategoryGit

Comments on this page

More...

CategoryEnglish, CategoryBlog