The free plan that Cloudflare gives away is my main distraction lately. I figured I need to level up my node.js skills. When I'm done with my normal 8 hour shift, I typically want to write C++. C++ is MY FAVORITE pass-time. But, prototyping apps in node.js is my second favorite.
One thing I learned about cloudflare's serverless setup is that their Workers FREE plan is actually fairly decent for how much cpu you get. You don't even need to enter a credit card JUST IN CASE. You just get a couple hundred thousand requests per day and a fixed wall time per request.
To famliarize myself with their platformer, I wrote a simple API to store user data in their D1 database binding.
D1 is essentially just Sqlite with a wrapper around it.
If you ever decide to start writing CF Workers, do yourself a favor and install the Wrangler CLI tool. It's written in node, so you'll want to lock it down to a VM underneath several layers of chroots, MAC policies, and app armor. Can't be too safe! How many times have we seen a rogue node package wreak havoc.
D1 can be a bit quirky to get acclimated to. I'm used to using postgresql 80% of the time and when the project calls for it, sometimes mysql (or should I say MariaDB). The grammar for D1 isn't documented at all on Cloudflare's document portal. Just lookup the Sqlite3 docs and you'll be good. ... With one exception ...
BEGIN TRANSACTION/`ROLLBACK/COMMIT`I got a Javascript runtime error when I tried just executing a raw sql string:
await db.exec('BEGIN TRANSACTION');
... Their database binding looks specifically for transaction begin/rollback/commit and tells you to kick rocks. I like that their library parses the string, though it may also just be an internal thing in an untouchable node script that is firewall'd off from userland code.
I rolled my own little rollback mechanism.
I just used INSERT INTO ... blah ... RETURNING id, then when I didn't get the id back, I knew the insert failed.
But if it succeeded, I just pushed the name of the table and the id to an array.
if(stmt.success){
this.created.push({type: 'customer',pkid: stmt.results[0].id});
}else{
this.errors.push('failed to create customer');
}
At the end of the function, I do a simple check to see if anything failed:
if(this.errors.length > 0){
// then i loop through this.created and remove
for(const row of this.created){
if(row.type === 'customer') {
await CustomerORM.removeByID(row.pkid);
}
// ...
// and so on, for each table
}
}
Well, I haven't thought of using Authorization tokens and I'm pretty sure JWT is going to be overkill.
I think if I imported a JWT library, that would spike the wall time and cpu of my worker. JWT does not
seem like a very lite implementation. It is public key cryptography....
hah, nothing. Get it? "What's left? What's right?" Actually, what's right is in my one worker application I managed to write my own little router implementation. It's nothing fancy like Express. It's in it's early stages, but for the most part, I'm likely to refactor it soon.
Sat May 4 12⭐18 PM MDT 2024
Later