package config import ( "encoding/json" "errors" "math/rand" "strings" "time" ) type Duration struct { least time.Duration most time.Duration } func (d Duration) Get() time.Duration { jitter := d.most - d.least if jitter >= time.Second { jitter = time.Second * time.Duration(rand.Int()%int(jitter.Seconds())) } else { jitter = 0 } return time.Duration(d.least + jitter) } func (d Duration) MarshalJSON() ([]byte, error) { return json.Marshal(d.least.String() + ".." + d.most.String()) } func (d *Duration) UnmarshalJSON(b []byte) error { var s string if err := json.Unmarshal(b, &s); err != nil { return err } if !strings.Contains(s, "..") { s = s + ".." + s } splits := strings.Split(s, "..") if len(splits) != 2 { return errors.New("unexpected ..") } least, err := time.ParseDuration(splits[0]) if err != nil { return err } most, err := time.ParseDuration(splits[1]) if err != nil { return err } if least > most { most, least = least, most } d.most = most d.least = least return nil }