lazy.gno
1.53 Kb · 59 lines
1// Package lazy is version 0 of the "lazy migration" upgrade pattern
2// (pattern D of the exploration; see ../README.md).
3//
4// This version is an ordinary record store. It is written without any
5// knowledge of a successor: what makes the pattern work is only that its
6// records are readable from outside, which any avl-backed realm already is.
7package lazy
8
9import (
10 "gno.land/p/nt/avl/v0"
11 "gno.land/p/nt/ufmt/v0"
12)
13
14// Record is v0's shape. v1 changes it, which is the whole reason for a new
15// version: a stored-layout change is never done in place.
16type Record struct {
17 Name string
18 Score int
19}
20
21func (r *Record) String() string {
22 if r == nil {
23 return "nil"
24 }
25 return ufmt.Sprintf("v0{%s %d}", r.Name, r.Score)
26}
27
28var records = avl.NewTree()
29
30func init() {
31 records.Set("ada", &Record{Name: "ada", Score: 1})
32 records.Set("bob", &Record{Name: "bob", Score: 2})
33}
34
35// Get returns a record or nil. Non-crossing: v1 reads through it while
36// migrating, and gnoweb can call it without a transaction.
37func Get(key string) *Record {
38 v := records.Get(key)
39 if v == nil {
40 return nil
41 }
42 return v.(*Record)
43}
44
45// Size is how many records still live here. It never shrinks: lazy migration
46// COPIES forward, it does not move, so v0 keeps paying for every record it
47// ever held.
48func Size() int {
49 return records.Size()
50}
51
52func Render(_ string) string {
53 out := ufmt.Sprintf("lazy/v0: %d records\n", records.Size())
54 records.Iterate("", "", func(k string, v any) bool {
55 out += ufmt.Sprintf("- %s: %s\n", k, v.(*Record).String())
56 return false
57 })
58 return out
59}