go-vise

Constrained Size Output Virtual Machine
Info | Log | Files | Refs | README | LICENSE

commit e5b5bc34a2be888029024ffa9f8e31e9f0164a49
parent c09a397c9b66d0a9cdf6ecf5a105556aaa92ffe3
Author: lash <dev@holbrook.no>
Date:   Thu,  2 Jan 2025 17:54:29 +0000

Merge branch 'dev-0.2.3' into lash/walk

Diffstat:
MCHANGELOG | 2++
Mdb/dump.go | 14++++++++++++++
Mdb/gdbm/dump.go | 1+
Mdb/postgres/dump.go | 27++++++++++++++++++++-------
Mlogging/vanilla.go | 71++++++++++++++++++++++++++++++++++++++++++-----------------------------
Mvm/runner.go | 6++----
6 files changed, 81 insertions(+), 40 deletions(-)

diff --git a/CHANGELOG b/CHANGELOG @@ -3,6 +3,8 @@ * Developer tool to generate node navigation map. * Expose code to manually trigger state rewind (asm: MOVE ^) * Add gettext resource handler for menu and template. + * Fix premature close of postgres data dumper + * Expose session id in structured logger when using context - 0.2.2 * Customizable menu separator * Make available node movement direction detection in state object. diff --git a/db/dump.go b/db/dump.go @@ -5,9 +5,11 @@ import ( ) type DumperFunc func(ctx context.Context) ([]byte, []byte) +type CloseFunc func() error type Dumper struct { fn DumperFunc + cfn CloseFunc k []byte v []byte nexted bool @@ -29,6 +31,11 @@ func(d *Dumper) WithFirst(k []byte, v []byte) *Dumper { return d } +func(d *Dumper) WithClose(fn func() error) *Dumper { + d.cfn = fn + return d +} + func(d *Dumper) Next(ctx context.Context) ([]byte, []byte) { d.nexted = true k := d.k @@ -40,3 +47,10 @@ func(d *Dumper) Next(ctx context.Context) ([]byte, []byte) { logg.TraceCtxf(ctx, "next value is", "k", d.k, "v", d.v) return k, v } + +func(d *Dumper) Close() error { + if d.cfn != nil { + return d.cfn() + } + return nil +} diff --git a/db/gdbm/dump.go b/db/gdbm/dump.go @@ -11,6 +11,7 @@ import ( ) func(gdb *gdbmDb) Dump(ctx context.Context, key []byte) (*db.Dumper, error) { + key = append([]byte{db.DATATYPE_USERDATA}, key...) gdb.it = gdb.conn.Iterator() for true { k, err := gdb.it() diff --git a/db/postgres/dump.go b/db/postgres/dump.go @@ -13,28 +13,33 @@ func(pdb *pgDb) Dump(ctx context.Context, key []byte) (*db.Dumper, error) { return nil, err } - query := fmt.Sprintf("SELECT key, value FROM %s.kv_vise WHERE key >= $1 AND key < $2", pdb.schema) - rs, err := tx.Query(ctx, query, key, key[0]) + k := append([]byte{db.DATATYPE_USERDATA}, key...) + + query := fmt.Sprintf("SELECT key, value FROM %s.kv_vise WHERE key >= $1", pdb.schema) + logg.TraceCtxf(ctx, "getkey", "q", query, "key", k) + rs, err := tx.Query(ctx, query, k) if err != nil { + logg.Debugf("query fail", "err", err) tx.Rollback(ctx) return nil, err } - defer rs.Close() + //defer rs.Close() if rs.Next() { r := rs.RawValues() - tx.Commit(ctx) //tx.Rollback(ctx) + tx.Commit(ctx) pdb.it = rs - pdb.itBase = key - return db.NewDumper(pdb.dumpFunc).WithFirst(r[0], r[1]), nil + pdb.itBase = k + return db.NewDumper(pdb.dumpFunc).WithClose(pdb.closeFunc).WithFirst(r[0], r[1]), nil } - return nil, db.NewErrNotFound(key) + return nil, db.NewErrNotFound(k) } func(pdb *pgDb) dumpFunc(ctx context.Context) ([]byte, []byte) { if !pdb.it.Next() { + logg.DebugCtxf(ctx, "no more data in pg iterator") pdb.it = nil pdb.itBase = nil return nil, nil @@ -42,3 +47,11 @@ func(pdb *pgDb) dumpFunc(ctx context.Context) ([]byte, []byte) { r := pdb.it.RawValues() return r[0], r[1] } + +func(pdb *pgDb) closeFunc() error { + if pdb.it != nil { + pdb.it.Close() + pdb.it = nil + } + return nil +} diff --git a/logging/vanilla.go b/logging/vanilla.go @@ -16,41 +16,47 @@ var ( // Vanilla is a basic single-line structured output logger for terminal output. type Vanilla struct { - domain string + domain string levelFilter int } // NewVanilla creates a new Vanilla logger. func NewVanilla() Vanilla { return Vanilla{ - domain: "main", + domain: "main", levelFilter: LogLevel, } } // WithDomain sets the logging domain. It is prepended to the caller file/line information. -func(v Vanilla) WithDomain(domain string) Vanilla { +func (v Vanilla) WithDomain(domain string) Vanilla { v.domain = domain return v } // WithLevel overrides the globally set loglevel for the logger instance. -func(v Vanilla) WithLevel(level int) Vanilla { +func (v Vanilla) WithLevel(level int) Vanilla { v.levelFilter = level return v } // Printf logs to the global writer. -func(v Vanilla) Printf(level int, msg string, args ...any) { +func (v Vanilla) Printf(level int, msg string, args ...any) { v.Writef(LogWriter, level, msg, args...) } // compile log line from inputs and send to given writer. -func(v Vanilla) writef(w io.Writer, file string, line int, level int, msg string, args ...any) { +func (v Vanilla) writef(ctx context.Context, w io.Writer, file string, line int, level int, msg string, args ...any) { + var argsStr string if level > v.levelFilter { return } - argsStr := argsToString(args) + if ctx == nil { + argsStr = argsToString(nil, args) + } else { + argsStr = argsToString(ctx, args) + } + if len(msg) > 0 { fmt.Fprintf(w, "[%s] %s:%s:%v %s\t%s\n", AsString(level), v.domain, file, line, msg, argsStr) } else { @@ -59,81 +65,81 @@ func(v Vanilla) writef(w io.Writer, file string, line int, level int, msg string } // Writef logs to the given writer. -func(v Vanilla) Writef(w io.Writer, level int, msg string, args ...any) { +func (v Vanilla) Writef(w io.Writer, level int, msg string, args ...any) { file, line := getCaller(2) - v.writef(w, file, line, level, msg, args) + v.writef(nil, w, file, line, level, msg, args) } // WriteCtxf logs with context to the given writer. -func(v Vanilla) WriteCtxf(ctx context.Context, w io.Writer, level int, msg string, args ...any) { +func (v Vanilla) WriteCtxf(ctx context.Context, w io.Writer, level int, msg string, args ...any) { file, line := getCaller(2) - v.writef(w, file, line, level, msg, args...) + v.writef(ctx, w, file, line, level, msg, args...) } // get caller information and pass on to writef -func(v Vanilla) printf(level int, msg string, args ...any) { +func (v Vanilla) printf(level int, msg string, args ...any) { file, line := getCaller(3) - v.writef(LogWriter, file, line, level, msg, args...) + v.writef(nil, LogWriter, file, line, level, msg, args...) } // get caller information and pass on to writef -func(v Vanilla) printCtxf(ctx context.Context, level int, msg string, args ...any) { +func (v Vanilla) printCtxf(ctx context.Context, level int, msg string, args ...any) { file, line := getCaller(3) - v.writef(LogWriter, file, line, level, msg, args...) + v.writef(ctx, LogWriter, file, line, level, msg, args...) } // PrintCtxf logs with context to the global writer. -func(v Vanilla) PrintCtxf(ctx context.Context, level int, msg string, args ...any) { +func (v Vanilla) PrintCtxf(ctx context.Context, level int, msg string, args ...any) { v.printf(level, msg, args...) } // Tracef logs a line with level TRACE to the global writer. -func(v Vanilla) Tracef(msg string, args ...any) { +func (v Vanilla) Tracef(msg string, args ...any) { v.printf(LVL_TRACE, msg, args...) } // Debugf logs a line with level DEBUG to the global writer. -func(v Vanilla) Debugf(msg string, args ...any) { +func (v Vanilla) Debugf(msg string, args ...any) { v.printf(LVL_DEBUG, msg, args...) } // Infof logs a line with level INFO to the global writer. -func(v Vanilla) Infof(msg string, args ...any) { +func (v Vanilla) Infof(msg string, args ...any) { v.printf(LVL_INFO, msg, args...) } // Warnf logs a line with level WARN to the global writer. -func(v Vanilla) Warnf(msg string, args ...any) { +func (v Vanilla) Warnf(msg string, args ...any) { v.printf(LVL_WARN, msg, args...) } // Errorf logs a line with level ERROR to the global writer. -func(v Vanilla) Errorf(msg string, args ...any) { +func (v Vanilla) Errorf(msg string, args ...any) { v.printf(LVL_ERROR, msg, args...) } // TraceCtxf logs a line with context with level TRACE to the global writer. -func(v Vanilla) TraceCtxf(ctx context.Context, msg string, args ...any) { +func (v Vanilla) TraceCtxf(ctx context.Context, msg string, args ...any) { v.printCtxf(ctx, LVL_TRACE, msg, args...) } // DebugCtxf logs a line with context with level DEBUG to the global writer. -func(v Vanilla) DebugCtxf(ctx context.Context, msg string, args ...any) { +func (v Vanilla) DebugCtxf(ctx context.Context, msg string, args ...any) { v.printCtxf(ctx, LVL_DEBUG, msg, args...) } // InfoCtxf logs a line with context with level INFO to the global writer. -func(v Vanilla) InfoCtxf(ctx context.Context, msg string, args ...any) { +func (v Vanilla) InfoCtxf(ctx context.Context, msg string, args ...any) { v.printCtxf(ctx, LVL_INFO, msg, args...) } // WarnCtxf logs a line with context with level WARN to the global writer. -func(v Vanilla) WarnCtxf(ctx context.Context, msg string, args ...any) { +func (v Vanilla) WarnCtxf(ctx context.Context, msg string, args ...any) { v.printCtxf(ctx, LVL_WARN, msg, args...) } // ErrorCtxf logs a line with context with level ERROR to the global writer. -func(v Vanilla) ErrorCtxf(ctx context.Context, msg string, args ...any) { +func (v Vanilla) ErrorCtxf(ctx context.Context, msg string, args ...any) { v.printCtxf(ctx, LVL_ERROR, msg, args...) } @@ -141,14 +147,21 @@ func(v Vanilla) ErrorCtxf(ctx context.Context, msg string, args ...any) { func getCaller(depth int) (string, int) { var file string var line int - _, file, line,_ = runtime.Caller(depth) + _, file, line, _ = runtime.Caller(depth) baseFile := path.Base(file) return baseFile, line } // string representation of the given structured log args. -func argsToString(args []any) string { +func argsToString(ctx context.Context, args []any) string { var s string + + if ctx != nil { + sessionId, ok := ctx.Value("SessionId").(string) + if ok { + args = append(args, "session-id", sessionId) + } + } c := len(args) var i int for i = 0; i < c; i += 2 { @@ -156,7 +169,7 @@ func argsToString(args []any) string { s += ", " } - if i + 1 < c { + if i+1 < c { var argByte []byte var ok bool argByte, ok = args[i+1].([]byte) diff --git a/vm/runner.go b/vm/runner.go @@ -85,10 +85,8 @@ func(vmi *Vm) Reset() { func Rewind(sym string, st *state.State, ca cache.Memory) (string, error) { var err error - notTop := true - for notTop { - //notTop, err := st.Top() - notTop, err = st.Top() + for true { + notTop, err := st.Top() if notTop { break }