Files
zeekay 6994cf05aa kv, not redis: rename the package, the extras and the URL scheme
We do not use Redis. The client was a go-redis fork and still said so
everywhere: `package redis`, `redis.NewClient`, `redis://`, `extra/redisotel`.
Consumers wrote `redis.Client` against a Valkey-backed store called KV.

  package redis            -> package kv          (93 decls)
  redis.X                  -> kv.X                (2,794 call sites)
  "redis: …" errors        -> "kv: …"             (206)
  extra/redis{otel,cmd,prometheus,census} -> extra/kv{otel,cmd,prometheus,census}
  redis:// , rediss://     -> kv:// , kvs://      (ParseURL)
  Redis*/‌*Redis* idents    -> KV*/*KV*
  REDIS_VERSION, REDIS_ENDPOINTS_CONFIG_PATH -> KV_*

I previously argued this rename was unsafe because much of it was "wire
contract". That was wrong, and the categorisation shows why: RESP command names
are GET/SET/HSET — they never contain the word. Of 5,771 occurrences only two
kinds were server-visible at all: the ParseURL scheme (we choose what we pass;
our configs already use kv://) and the CLIENT SETINFO lib-name label, which the
server merely records. Nothing here changes a byte of protocol.

Two things deliberately keep the old spelling:
  RediSearch  — names a specific external module the FT.* commands map to.
  StoreDist   — contains the letters by accident (sto-reDis-t), not the word.

Breaking for consumers by design: every import site must move redis.X -> kv.X.
Minor bump, never a major — this module stays v9 forever.
2026-07-26 08:34:19 -07:00

97 lines
2.7 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package util
/*
© 2023–present Harald Rudell <[email protected]> (https://haraldrudell.github.io/haraldrudell/)
ISC License
Modified by htemelski-kv
Adapted from the modified atomic_max, but with inverted logic
*/
import (
"math"
"go.uber.org/atomic"
)
// AtomicMin is a thread-safe Min container
// - hasValue indicator true if a value was equal to or greater than threshold
// - optional threshold for minimum accepted Min value
// - —
// - wait-free CompareAndSwap mechanic
type AtomicMin struct {
// value is current Min
value atomic.Float64
// whether [AtomicMin.Value] has been invoked
// with value equal or greater to threshold
hasValue atomic.Bool
}
// NewAtomicMin returns a thread-safe Min container
// - if threshold is not used, AtomicMin is initialization-free
func NewAtomicMin() (atomicMin *AtomicMin) {
m := AtomicMin{}
m.value.Store(math.MaxFloat64)
return &m
}
// Value updates the container with a possible Min value
// - isNewMin is true if:
// - — value is equal to or greater than any threshold and
// - — invocation recorded the first 0 or
// - — a new Min
// - upon return, Min and Min1 are guaranteed to reflect the invocation
// - the return order of concurrent Value invocations is not guaranteed
// - Thread-safe
func (m *AtomicMin) Value(value float64) (isNewMin bool) {
// math.MaxFloat64 as Min case
var hasValue0 = m.hasValue.Load()
if value == math.MaxFloat64 {
if !hasValue0 {
isNewMin = m.hasValue.CompareAndSwap(false, true)
}
return // math.MaxFloat64 as Min: isNewMin true for first 0 writer
}
// check against present value
var current = m.value.Load()
if isNewMin = value < current; !isNewMin {
return // not a new Min return: isNewMin false
}
// store the new Min
for {
// try to write value to *Min
if isNewMin = m.value.CompareAndSwap(current, value); isNewMin {
if !hasValue0 {
// may be rarely written multiple times
// still faster than CompareAndSwap
m.hasValue.Store(true)
}
return // new Min written return: isNewMin true
}
if current = m.value.Load(); current <= value {
return // no longer a need to write return: isNewMin false
}
}
}
// Min returns current min and value-present flag
// - hasValue true indicates that value reflects a Value invocation
// - hasValue false: value is zero-value
// - Thread-safe
func (m *AtomicMin) Min() (value float64, hasValue bool) {
if hasValue = m.hasValue.Load(); !hasValue {
return
}
value = m.value.Load()
return
}
// Min1 returns current Minimum whether zero-value or set by Value
// - threshold is ignored
// - Thread-safe
func (m *AtomicMin) Min1() (value float64) { return m.value.Load() }