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:
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
}