Getting started with iocaine is now online.

From nothing to running iocaine + Caddy with ai.robots.txt's robots.json and a few metrics as a starting point.

Contains #Roto, #Lua, and #Fennel - and a few tests too, for each.

I'm on a bit of a roll lately, and have released #iocaine version 2.4.0 just a few moments ago.

This does not bring that many significant changes as 2.3.0 did, but it does introduce #Lua and #Fennel as languages you can script its decision making with, on top of #Roto, which was introduced in 2.2.0.

While these languages run slower than Roto, they're still very fast, and are not going to be a bottleneck - they do provide a more familiar language to write the decision making in!

Oh, and metrics can now be persisted across restarts.

"What is acceptable?", you may ask.

Well, anything faster than ~40k req/sec in release mode will do. Why ~40k req/sec? Because that's my reverse proxy's bottleneck.

I also expect a very naive implementation of return false to run at at least at 1k req/sec in release mode.

What's a naive implementation? Creating the runtime environment on every request, and compiling the trivial program on every request.

In other #iocaine news, I'm doing some final polishing on #Lua scripting support, to make it as convenient as #Roto.

Right now, there's a differenc between how Lua and Roto scripts are loaded: with Roto, one needs to give a path to a directory, and pkg.roto will be loaded from there, and any imports will be relative to that directory.

With Lua, one gives iocaine a file path, and - currently - needs to set up the package.path search path manually.

So here's what I'll do: I'll make iocaine require a directory for Lua too, and it will add it to package.path, and will require("main"). The required module will also have to return a table with at least a decide key, and an optional run_tests key. This will simplify finding the functions to run, and will greatly reduce the number of special cases.

Today, I'm writing tests. Originally, I planned to write a bunch of tests in Rust to exercise the request handlers, but that felt like a huge pain in the backside, and would've involved a lot of repetition and boilerplate.

Then, I figured: I'll write the tests in #Roto and #Lua! Test the things from that side. Much less boilerplate, but still a lot of repetition.

Instead, I'll be writing a test suite to verify the decisions of a request handler. I'll run it for both engines, #Roto and #Lua. I will still have to write the scripts twice, but I will only write the verification once.