The discussion evolves
In the span of a short evening coding session (and an early morning one the next day) I quickly refactored to using the new library. Just like that, all my concerns with asynchronicity were gone. Funny. This latest refactor has brought up questions along with answers however.
I feel like I'm about to ask a dumb question but... why wouldn't I use a synchronous database library for a standard server/client application? Let's dig in...
Trunk has an operation that opens an article for you to read in your target language. To do this it performs the following:
- Send a message using IPCRenderer to the backend to say "hey! I want to read article
- IPCMain receives this message, similar to a router, and makes the following database calls: a.
2ais a simple get request, but
2bmakes as many queries as there are words per article, and then attaches the results to the result of
2abefore sending it back to the client.
In all this time, the client can't do anything. It can't show the article until it's back, and the database call for
2b can't be invoked until
2a is completed. I have no other things to process in the background - I have to execute these functions synchronously.
So why wouldn't I want a synchronous db library (that also happens to be faster than the existing async one...)?
Before and After
Let's look a little at how the code evolved.
"Getting" an article, (as described above) started out like this:
Then, here it is with core.async, in which I was able to make the db functions a bit cleaner, and then combine them in the IPC handler:
;; DB functions: ;; Look into preparing statements -- less recursion: ;; https://stackoverflow.com/questions/28803520/does-sqlite3-have-prepared-statements-in-node-js ;; -- IPC Handler: ;; BEFORE, on node-sqlite3 (mapbox) ;; Time to get article with 341 words: 92.222ms ;; Time to get article with 2500~ words: 630.365ms ;; Time to get an article with
And now? Now this is how things look with a synchronous library:
;; -- DB calls: ;; -- IPC handler: ;; AFTER, on better-sqlite3 ;; Time to get article with 341 words: 52.726ms ;; Time to get article with 2500~ words: 251.335ms
As an aside, I thought to see if I could run a benchmark on my macbook before and after I refactored (and along the way I learned about the very useful
MacBook Pro (13-inch, 2019, Two Thunderbolt 3 ports) with
1.4 GHz Quad-Core Intel Core i5 and
16 GB 2133 MHz LPDDR3 the timing was cut in half, pretty much. (Disclaimer, I don't know much about benchmarking...yet.)
All in all, I've encountered another technical decision that is a bit intimidating to make (am I just picking up a different footgun?). However, I'm confident that I'll stay with this change for now. I've also written up a wrapper
sql function that makes most of the calls, so if things change again, I'm hopefuly I'll only need to change one function and the rest will fall into place.
Thanks for reading!