Add the conversation fingerprint and the v1 config keys
Implemented-By: OpenCode session (model recorded in docs/implementer-log.md)
This commit is contained in:
@@ -15,18 +15,25 @@ import (
|
||||
"os"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/BurntSushi/toml"
|
||||
)
|
||||
|
||||
// Duration is a time.Duration that TOML reads from a string such as "60s" or
|
||||
// "30m".
|
||||
// Duration is a time.Duration that TOML reads from a string such as "60s",
|
||||
// "30m", or "7d" (an integer number of days).
|
||||
type Duration struct{ time.Duration }
|
||||
|
||||
// UnmarshalText implements encoding.TextUnmarshaler via time.ParseDuration.
|
||||
// UnmarshalText implements encoding.TextUnmarshaler. It accepts the "Nd" form
|
||||
// — an integer number of days, so "7d" is 7 × 24h — in addition to
|
||||
// time.ParseDuration syntax.
|
||||
func (d *Duration) UnmarshalText(text []byte) error {
|
||||
if days, ok := parseDays(text); ok {
|
||||
d.Duration = days
|
||||
return nil
|
||||
}
|
||||
dt, err := time.ParseDuration(string(text))
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -35,6 +42,22 @@ func (d *Duration) UnmarshalText(text []byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// dayPattern matches a run of digits followed by "d", e.g. "7d".
|
||||
var dayPattern = regexp.MustCompile(`^[0-9]+d$`)
|
||||
|
||||
// parseDays reports whether text is the "Nd" day form and returns that many
|
||||
// hours. The regex guarantees the prefix is a base-10 integer.
|
||||
func parseDays(text []byte) (time.Duration, bool) {
|
||||
if !dayPattern.MatchString(string(text)) {
|
||||
return 0, false
|
||||
}
|
||||
n, err := strconv.Atoi(string(text[:len(text)-1]))
|
||||
if err != nil {
|
||||
return 0, false
|
||||
}
|
||||
return time.Duration(n) * 24 * time.Hour, true
|
||||
}
|
||||
|
||||
// Model is the per-model tuning carried by a host entry.
|
||||
type Model struct {
|
||||
Parallel int `toml:"parallel"`
|
||||
@@ -58,6 +81,9 @@ type Config struct {
|
||||
Listen string `toml:"listen"`
|
||||
PollInterval Duration `toml:"poll_interval"`
|
||||
QueueMax int `toml:"queue_max"`
|
||||
DB string `toml:"db"`
|
||||
LeaseIdle Duration `toml:"lease_idle"`
|
||||
Retention Duration `toml:"retention"`
|
||||
Hosts map[string]Host `toml:"hosts"`
|
||||
Routes map[string]Route `toml:"routes"`
|
||||
}
|
||||
@@ -76,6 +102,13 @@ const (
|
||||
DefaultPollInterval = 60 * time.Second
|
||||
DefaultQueueMax = 8
|
||||
MinPollInterval = time.Second
|
||||
|
||||
DefaultDB = "crossbar.db"
|
||||
DefaultLeaseIdle = 30 * time.Minute
|
||||
DefaultRetention = 180 * 24 * time.Hour
|
||||
|
||||
MinLeaseIdle = time.Minute
|
||||
MinRetention = 24 * time.Hour
|
||||
)
|
||||
|
||||
var routeName = regexp.MustCompile(`^[a-z0-9][a-z0-9-]*$`)
|
||||
@@ -109,6 +142,15 @@ func Parse(r io.Reader) (*Config, error) {
|
||||
return nil, &Error{Field: keys[0], Msg: "unknown key"}
|
||||
}
|
||||
|
||||
if !md.IsDefined("db") {
|
||||
c.DB = DefaultDB
|
||||
}
|
||||
if !md.IsDefined("lease_idle") {
|
||||
c.LeaseIdle.Duration = DefaultLeaseIdle
|
||||
}
|
||||
if !md.IsDefined("retention") {
|
||||
c.Retention.Duration = DefaultRetention
|
||||
}
|
||||
if c.PollInterval.Duration == 0 {
|
||||
c.PollInterval.Duration = DefaultPollInterval
|
||||
}
|
||||
@@ -152,6 +194,15 @@ func (c *Config) validate() *Error {
|
||||
if e := c.checkQueue(); e != nil {
|
||||
return e
|
||||
}
|
||||
if e := c.checkDB(); e != nil {
|
||||
return e
|
||||
}
|
||||
if e := c.checkLeaseIdle(); e != nil {
|
||||
return e
|
||||
}
|
||||
if e := c.checkRetention(); e != nil {
|
||||
return e
|
||||
}
|
||||
if e := c.checkHosts(); e != nil {
|
||||
return e
|
||||
}
|
||||
@@ -193,6 +244,27 @@ func (c *Config) checkQueue() *Error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Config) checkDB() *Error {
|
||||
if c.DB == "" {
|
||||
return &Error{Field: "db", Msg: "required"}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Config) checkLeaseIdle() *Error {
|
||||
if c.LeaseIdle.Duration < MinLeaseIdle {
|
||||
return &Error{Field: "lease_idle", Msg: "must be at least 1m"}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Config) checkRetention() *Error {
|
||||
if c.Retention.Duration < MinRetention {
|
||||
return &Error{Field: "retention", Msg: "must be at least 1d"}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Config) checkHosts() *Error {
|
||||
if len(c.Hosts) == 0 {
|
||||
return &Error{Field: "hosts", Msg: "at least one required"}
|
||||
|
||||
Reference in New Issue
Block a user