The MySQL subdirectory contains ready-to-use driver packages for MySQL and Redis, adapted from the OpenResty drivers. The MySQL package is based on lua-resty-mysql, and the Redis package is based on lua-resty-redis.
These drivers are intended for Cosocket-style use. BAS supports the same general model, but the execution environment differs from OpenResty, so this example includes compatibility code that bridges the OpenResty-style APIs to BAS socket behavior.
Background reading:
MySQL/.configandMySQL/.preload- Packaging and module-loading support for the driver bundle.MySQL/.lua/resty/mysql.lua- OpenResty MySQL driver with the added BAS-specific persistent-connection helpers.MySQL/.lua/resty/redis.lua- OpenResty Redis driver.MySQL/.lua/resty.lua,rsa.lua,sha256.lua,bit.lua- Compatibility support modules.www/.preload- Startup message for the example pages.www/MySQL.lsp- MySQL test page.www/Redis.lsp- Redis test page.
The reusable package layout inside MySQL/ is intentionally close to the original OpenResty structure:
| .config
| .preload
|
\---.lua
| bit.lua
| resty.lua
|
\---resty
mysql.lua
redis.lua
rsa.lua
sha256.lua
Keeping that structure intact makes require "resty.mysql" and require "resty.redis" work the way OpenResty developers expect, while the BAS compatibility layer handles the runtime differences underneath.
If you want to package the reusable drivers into a BAS ZIP app, create the ZIP from the MySQL directory:
cd MySQL
zip -D -q -u -r -9 ../MySQL.zip .The hidden files and directories are intentionally included.
To run the example pages with Mako Server:
mako -l::MySQL.zip -l::wwwBefore testing, start Redis and MySQL. The Linux commands below also work on WSL2:
sudo apt install docker
sudo dockerd
docker run -d --name some-redis -p 6379:6379 redis
docker run --name some-mysql -e MYSQL_DATABASE=world -e MYSQL_ROOT_PASSWORD=qwerty -p 3306:3306 -d mysqlOn WSL2, sudo dockerd must run in a separate WSL2 console. On most Linux systems, the Docker daemon already runs as a service.
Create the sample table for the MySQL test:
mysql -h 127.0.0.1 -u root -pThen execute:
USE world;
CREATE TABLE Persons (
PersonID int,
LastName varchar(255),
FirstName varchar(255),
Address varchar(255),
City varchar(255)
);
insert into Persons (
PersonID,
LastName,
FirstName,
Address,
City
)
VALUES(1,"Bond","James"," Old Bond Street","London");Then open:
http://localhost:portno/MySQL.lsphttp://localhost:portno/Redis.lsp
If you use WSL2, the Mako Server should also run inside WSL2. It is possible to run Mako on Windows and proxy into WSL2, but that adds extra setup. When the server runs inside WSL2, use the WSL2 IP address in the browser rather than localhost.
The example LSP pages show both execution styles:
- direct blocking socket use inside an LSP page
- OpenResty-style cosocket use wrapped in
ba.socket.event(...)
MySQL.lsp opens a connection, queries the Persons table, prints the result, then runs the same test again through ba.socket.event(...). Redis.lsp performs a similar pattern with basic set/get operations plus a pipeline example.
That side-by-side structure is useful because the examples show that the driver API itself does not need to change much when you move from blocking LSP execution to the BAS cosocket model.
The Redis page is especially useful for checking the OpenResty compatibility layer because it exercises:
- normal
connect,set, andgetcalls - the
ngx.nullcompatibility behavior - pipelined commands with
init_pipeline()andcommit_pipeline()
The MySQL driver also includes two BAS-specific helper methods:
db:async(config, callback)- Starts a persistent asynchronous database connection and optionally retries through the callback.db:execute(function)- Queues work to run inside the database cosocket environment.
That persistent-connection logic is implemented near the end of MySQL/.lua/resty/mysql.lua.
The added API makes it possible to keep one database cosocket alive and queue work onto it:
local mysql = require"resty.mysql"
local db,err = mysql:new()
if not db then
trace("mysql:new failed:",err)
return
end
local running = true
local cfg = {
host = "localhost",
port = 3306,
database = "world",
user = "root",
password = "qwerty"
}
local function cb(ok, err, errno, sqlstate)
trace("Connect", ok, err, errno, sqlstate)
return running
end
db:async(cfg, cb)
db:execute(function()
local res, err, errno, sqlstate =
db:query("select * from Persons order by PersonID limit 50")
if not res then
trace("bad result #1: ", err, ": ", errno, ": ", sqlstate, ".")
return
end
for _, row in ipairs(res) do
for k, v in pairs(row) do
trace('>', k, v)
end
end
end)
function onunload()
running = false
db:close()
enddb:async(config, callback)starts the persistent connection flow.callbackreceives the same connection results asdb:connect(config).- If the callback returns
trueafter a failure, the code retries the connection. db:execute(function)queues work to run inside the same database cosocket environment.- Calling
db:execute()without a function returns the queued-operation count.
The recommendation from the original example still applies: study the implementation at the end of MySQL/.lua/resty/mysql.lua if you plan to use the persistent connection pattern in your own app.
That part of the file is where the BAS-specific enhancements live, so it is the best place to compare the original OpenResty driver design with the additional persistent-connection support added for this example.
- BAS sockets are blocking by default. Outside LSP pages, wrap database work in
ba.socket.event()so the code runs in a cosocket environment. - The OpenResty compatibility layer does not implement connection pooling. A socket added to the pool is simply closed.
- If you use WSL2, run the Mako Server there as well unless you also configure Windows-to-WSL proxying.
- The ZIP packaging command intentionally includes hidden files and directories, which is important because BAS apps depend on
.config,.preload, and.luaresources. - The example pages are intentionally conservative and local-first. They are there to validate driver behavior and BAS compatibility, not to provide a production database abstraction layer.
- If your own application only needs Redis or only needs MySQL, you can trim the packaged ZIP down to the parts you actually use, but keep the supporting compatibility files that the selected driver requires.
- Review the packaged module paths carefully.