Skip to content
LexerLangv0.1.0

Application state

globals, request.globals and services — data versus live objects.

There are three separate stores, and they are deliberately not mixed:

LexerLang
$app.globals.set("site_name", "Satış Katla")    # data, for the process
$app.request.globals.set("user", $user)         # data, this request only

$redis = $app.services.once("redis", func()     # live object, for the process
    return new redis({host: "localhost", port: 6379}).connect()
end func)
StoreBelongs toLifetimeCarries
$app.globalsthe applicationthe processdata (passes through JSON)
$app.request.globalsthe current requestends with the requestdata
$app.servicesthe applicationthe processlive objects
sessionthe userthe sessiondata (in Redis)

globals#

CallEffect
.set($name, $value)writes
.get($name) · .get($name, $default)reads
.has($name)whether it exists
.delete($name)removes

The backing store can change; the calls do not:

LexerLang
$app.globals.provider = $redis

The default is memory; Redis is not required. Redis keys are written under the lexer:global:<name> namespace.

Values pass through JSON in both stores. Otherwise the same code would break when the provider changed: memory would return a live object and Redis a JSON string. This is why globals cannot carry a database connection.

request.globals#

LexerLang
$app.request.globals.set("user", $user)     # authentication layer
$user = $app.request.globals.get("user")    # page / partial

Without the distinction, a value such as "the current user" would accidentally sit application-wide — even in Redis — and leak into the next request.

globals belongs to the application, session to the user. They answer different questions.

services#

globals carries data; services carries live objects.

LexerLang
$redis = $app.services.once("redis", func()
    return new redis({host: "localhost", port: 6379}).connect()
end func)

once runs the given function only on the first call. Every request after that gets the same instance:

LexerLang
$redis = $app.services.get("redis")

The connection is established once and every file reaches the same instance, removing the cost of reconnecting per request.

The page runs from the top on every request#

This is the one thing to keep in mind when writing state:

LexerLang
$app.globals.set("counter", 0)    # resets to 0 on EVERY request

Because the file is executed from the top on every request, this line runs every time too. Things that should be set up once need services.once or an existence check:

LexerLang
if not $app.globals.has("counter") then
    $app.globals.set("counter", 0)
end if

Heavy values built once at startup and read for the life of the process — a search index, for example — belong in globals, but make sure the code that builds them also runs only once.

Next#

Escaping.