Kingfisher is a webserver platform for the Roc language.
It lets you build websites by defining your own Model. The model is held in memory and saved on disk.
Kingfisher follows a very minimalistic approach. You do not have to deal with Tasks, SQL and I/O. Just write your views for read and write requests. Use a model structure as you like and don't care about database tables and queries.
Use the platform with the following roc-application-header:
app [main, Model] {
webserver: platform "https://github.com/ostcar/kingfisher/releases/download/v0.0.3/e8Mu5IplmOnXPU9VgpTCT6kyB463gX-SDC2nnMfAq7M.tar.br",
}
The platform requires a Model
. The Model
can be any valid roc type. For
example:
Model : {
modelVersion: U64,
users: List User,
admin: [NoAdmin, Admin Str],
books: List Str,
specialOption: Bool,
}
The platform needs four functions:
Program : {
decodeModel : [Init, Existing (List U8)] -> Model,
encodeModel : Model -> List U8,
handleReadRequest : Request, Model -> Response,
handleWriteRequest : Request, Model -> (Response, Model),
}
main : Program
main = {
decodeModel,
encodeModel,
handleReadRequest,
handleWriteRequest,
}
-
decodeModel:
decodeModel
is called when the server starts. On the first run, it is called withInit
and on every other start withExisting encodedModel
whereencodedModel
is a byte representation of theModel
. The function has to create the initial model or decode the model from the given bytes. -
encodeModel:
encodeModel
is the counterpart ofdecodeModel
. It has to create a byte representation of theModel
.
decodeModel
and encodeModel
are used to create a snapshot of the Model
and
persist it on disk. The functions can also be used to migrate an older version
of a model.
-
handleReadRequest:
handleReadRequest
is called for HTTP requests, that are readonly and can not update theModel
. The function is called with theRequest
and theModel
and has to return aResponse
. -
handleWriteRequest:
handleWriteRequest
is called for HTTP requests, that can update theModel
. The signature is simular thenhandleReadRequest
, but it also returns a newModel
.
The platform makes the distinction between a read and a write request on the
HTTP method. POST
, PUT
, PATCH
and DELETE
requests are write requests.
All other methods are read requests. This means, that a GET
request can not
alter the Model.
The platform can handle many read requests at the same time. But there can only be one concurent write request. When a write request is processed, all other write request and all read requests have to wait.
When the server is shut down, it calls encodeModel
and saves the snapshot to
disk. On restart, the snapshot is loaded to the server has the Model
in memory
again.
Additionally each write request gets persisted on disk. On server failure, the
logged write requests are used to recreate the Model
(the server just calls
the respective roc functions again).
After you have build your app, you can run your binary with the option --help
to see all available runtime options like listening address and path of the
snapshot file.
To build the platform from source, you need to install
roc, go and
zig. Zig is used to
crosscompile the go code. At the moment, it only works with zig 0.11.0
.
Run:
roc run build.roc
to build the platform for linux, windows.
Afterwards, the example can be run with:
roc run examples/hello_world/main.roc
MIT