Nyx by Example

Serve Full-stack

A full-stack pattern: HTTP server that uses nyx-kv as its state backend. The counter endpoint demonstrates read-modify-write with RESP commands.

Code

// nyx-serve full-stack — HTTP server + JSON API + nyx-kv backend
// nyx-serve full-stack — servidor HTTP + API JSON + backend nyx-kv

import "std/http"
import "std/web"

fn resp_cmd(parts: Array) -> String {
    var sb: StringBuilder = StringBuilder.new()
    sb.append("*")
    sb.append(int_to_string(parts.length()))
    sb.append("\r\n")
    var i: int = 0
    while i < parts.length() {
        let p: String = parts[i]
        sb.append("$" + int_to_string(p.length()) + "\r\n" + p + "\r\n")
        i = i + 1
    }
    return sb.to_string()
}

// Call nyx-kv and return the result (or empty on error)
fn kv_get(key: String) -> String {
    let fd: int = tcp_connect("127.0.0.1", 6380)
    if fd < 0 { return "" }
    tcp_write(fd, resp_cmd(["GET", key]))
    let hdr: String = tcp_read_line(fd)
    let val: String = tcp_read_line(fd)
    tcp_close(fd)
    return val.trim()
}

fn kv_set(key: String, val: String) -> int {
    let fd: int = tcp_connect("127.0.0.1", 6380)
    if fd < 0 { return -1 }
    tcp_write(fd, resp_cmd(["SET", key, val]))
    tcp_read_line(fd)
    tcp_close(fd)
    return 0
}

// GET /counter — increments and returns a global counter stored in nyx-kv
fn counter(req: Request) -> Response {
    let current: String = kv_get("counter")
    var n: int = 0
    if current.length() > 0 { n = string_to_int(current) }
    n = n + 1
    kv_set("counter", int_to_string(n))
    return response_json(200, "{\"count\": " + int_to_string(n) + "}")
}

fn main() -> int {
    let app: App = app_new()
    app_get(app, "/counter", counter)

    print("full-stack app: HTTP + JSON + KV backend")
    print("GET /counter increments a counter stored in nyx-kv")
    print("this pattern powers nyxlang.com's request analytics")
    return 0
}

Output

full-stack app: HTTP + JSON + KV backend
GET /counter increments a counter stored in nyx-kv
this pattern powers nyxlang.com's request analytics

Explanation

This is the canonical Nyx full-stack pattern: a stateless HTTP tier talking to a stateful nyx-kv tier over RESP. resp_cmd encodes commands in Redis's wire format — a length-prefixed array of bulk strings — which nyx-kv speaks natively. kv_get and kv_set each open a short-lived connection; for production you'd pool them. The /counter endpoint shows read-modify-write: GET the current value, increment, SET it back. This pattern isn't atomic across concurrent callers — for a real counter you'd use INCR, which nyx-kv runs server-side. The architectural win is that the web tier stays stateless, so any worker in any datacenter can serve any request.

← Previous Next →

Source: examples/by-example/84-serve-fullstack.nx