-- residency — databasev2 2's per-table storage, demonstrated across a restart -- with the workload the feature exists for: a product catalogue whose stock -- moves every time an order is placed. -- -- Before this iteration, durability was ONE environment variable for a whole -- process: WO_DATA set and every @table is WAL-logged, or unset and none are. -- Real applications are not uniform. A cart session is disposable; a product's -- stock level is not; and a catalogue large enough to matter does not fit in -- RAM at all. One global switch forces "everything is precious" or "nothing -- is", and the developer pays for whichever is wrong. -- -- Run it twice against the same WO_DATA directory: -- -- mkdir -p /tmp/residency-data -- WO_DATA must exist already -- WO_DATA=/tmp/residency-data wovm residency.wob seed -- WO_DATA=/tmp/residency-data wovm residency.wob order -- -- The second run places an order. Stock comes back decremented after a -- restart; the cart does not come back at all. -- Precious AND read-selectively resident: WAL-logged, replayed at boot, but -- only the id -> log-offset map lives in RAM — each row's payload is read -- back from the log. A real catalogue is the table that outgrows RAM first, -- so this is the mode you would actually reach for one. Storage, reads, -- scans through the `sku` index below (a Text column — exercised here, not -- just the scalar columns other tests stuck to), `@unique`, deletes and -- checkpoint survival all work, and so does UPDATE: `place_order` below moves -- `stock` through a WAL delta record — read-modify-APPEND, not a slab -- mutation, since a keys-resident row has no slab slot to mutate. See the -- README for what a delta update costs a reader. -- -- Only `stock` changes when an order is placed; `sku`, `name` and `price` do -- not. Appending the whole row on every sale would rewrite every field to -- change one integer, on the hottest write path a shop has — which is why -- the delta is one field, not a full-row rewrite. @table(name: "products", index: [sku], durable: true, resident: keys) class Product { sku: Text name: Text price: Int stock: Int } -- Scratch: never written to the WAL, so it costs no disk and no fsync, and it -- is EMPTY after a restart. That is the point — not a bug to work around. @table(name: "carts", index: [token], durable: false) class Cart { token: Text sku: Text } fn count_products() -> Int { let n = 0; for _p in from p in Product select p { n = n + 1; } return n; } fn count_carts() -> Int { let n = 0; for _c in from c in Cart select c { n = n + 1; } return n; } fn stock_of(sku: Text) -> Int { for p in from p in Product where p.sku == sku select p { return p.stock; } return 0 - 1; } -- The update this example exists to show: one field of one row moves, and the -- other three do not. fn place_order(sku: Text, qty: Int) -> Int { for p in from p in Product where p.sku == sku select p { if p.stock < qty { return 0 - 1; } p.stock = p.stock - qty; -- writes through to the engine return p.stock; } return 0 - 1; } fn main(args: multi Text) -> Int { if len(args) > 0 { if args[0] == "seed" { insert Product { sku: "SKU-1", name: "kettle", price: 2999, stock: 10 }; insert Product { sku: "SKU-2", name: "mug", price: 799, stock: 40 }; -- a cart is scratch: same insert, different annotation, different fate insert Cart { token: "cart-a", sku: "SKU-1" }; print("seeded: products=${count_products()} carts=${count_carts()} SKU-1 stock=${stock_of("SKU-1")}"); return 0; } if args[0] == "order" { -- second run: no inserts. Whatever is here came from the log. let before = stock_of("SKU-1"); let after = place_order("SKU-1", 3); print("after restart: products=${count_products()} carts=${count_carts()}"); print("order: SKU-1 stock ${before} -> ${after}"); if count_carts() != 0 { print("UNEXPECTED: a durable:false table survived a restart"); return 1; } if after != before - 3 { print("UNEXPECTED: the stock update did not apply"); return 1; } -- Run `order` more than once and this is the interesting line: a stock -- level below the seeded 10 can only mean an EARLIER order's update -- survived a restart. The decrement is durable, not just the insert. if before < 10 { print("ok: an earlier order's decrement replayed from the log"); } else { print("ok: first order placed; run `order` again to see it replay"); } return 0; } } print("usage: residency seed | residency order"); return 0; }