mirror of
https://github.com/mjl-/mox.git
synced 2024-12-25 16:03:48 +03:00
switch to math/rand/v2 in most places
this allows removing some ugly instantiations of an rng based on the current time. Intn is now IntN for our concurrency-safe prng wrapper to match the randv2 api. v2 exists since go1.22, which we already require.
This commit is contained in:
parent
96a3ecd52c
commit
de435fceba
9 changed files with 24 additions and 30 deletions
|
@ -15,7 +15,7 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
mathrand "math/rand"
|
mathrand2 "math/rand/v2"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/mjl-/mox/dkim"
|
"github.com/mjl-/mox/dkim"
|
||||||
|
@ -257,7 +257,7 @@ func Verify(ctx context.Context, elog *slog.Logger, resolver dns.Resolver, msgFr
|
||||||
|
|
||||||
// Record can request sampling of messages to apply policy.
|
// Record can request sampling of messages to apply policy.
|
||||||
// See ../rfc/7489:1432
|
// See ../rfc/7489:1432
|
||||||
useResult = !applyRandomPercentage || record.Percentage == 100 || mathrand.Intn(100) < record.Percentage
|
useResult = !applyRandomPercentage || record.Percentage == 100 || mathrand2.IntN(100) < record.Percentage
|
||||||
|
|
||||||
// We treat "quarantine" and "reject" the same. Thus, we also don't "downgrade"
|
// We treat "quarantine" and "reject" the same. Thus, we also don't "downgrade"
|
||||||
// from reject to quarantine if this message was sampled out.
|
// from reject to quarantine if this message was sampled out.
|
||||||
|
|
|
@ -252,7 +252,7 @@ var jitterRand = mox.NewPseudoRand()
|
||||||
// Jitter so we don't cause load at exactly whole hours, other processes may
|
// Jitter so we don't cause load at exactly whole hours, other processes may
|
||||||
// already be doing that.
|
// already be doing that.
|
||||||
var jitteredTimeUntil = func(t time.Time) time.Duration {
|
var jitteredTimeUntil = func(t time.Time) time.Duration {
|
||||||
return time.Until(t.Add(time.Duration(30+jitterRand.Intn(60)) * time.Second))
|
return time.Until(t.Add(time.Duration(30+jitterRand.IntN(60)) * time.Second))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start launches a goroutine that wakes up at each whole hour (plus jitter) and
|
// Start launches a goroutine that wakes up at each whole hour (plus jitter) and
|
||||||
|
|
8
junk.go
8
junk.go
|
@ -214,12 +214,12 @@ messages are shuffled, with optional random seed.`
|
||||||
hamFiles := listDir(hamDir)
|
hamFiles := listDir(hamDir)
|
||||||
spamFiles := listDir(spamDir)
|
spamFiles := listDir(spamDir)
|
||||||
|
|
||||||
var rand *mathrand.Rand
|
var seed int64
|
||||||
if a.seed {
|
if a.seed {
|
||||||
rand = mathrand.New(mathrand.NewSource(time.Now().UnixMilli()))
|
seed = time.Now().UnixMilli()
|
||||||
} else {
|
|
||||||
rand = mathrand.New(mathrand.NewSource(0))
|
|
||||||
}
|
}
|
||||||
|
// Still at math/rand (v1 instead of v2) for potential comparison to earlier test results.
|
||||||
|
rand := mathrand.New(mathrand.NewSource(seed))
|
||||||
|
|
||||||
shuffle := func(l []string) {
|
shuffle := func(l []string) {
|
||||||
count := len(l)
|
count := len(l)
|
||||||
|
|
20
mox-/rand.go
20
mox-/rand.go
|
@ -4,19 +4,23 @@ import (
|
||||||
cryptorand "crypto/rand"
|
cryptorand "crypto/rand"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"fmt"
|
"fmt"
|
||||||
mathrand "math/rand"
|
mathrand2 "math/rand/v2"
|
||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
type rand struct {
|
type rand struct {
|
||||||
rand *mathrand.Rand
|
rand *mathrand2.Rand
|
||||||
sync.Mutex
|
sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewPseudoRand returns a new PRNG seeded with random bytes from crypto/rand. Its
|
// NewPseudoRand returns a new PRNG seeded with random bytes from crypto/rand. Its
|
||||||
// functions can be called concurrently.
|
// functions can be called concurrently.
|
||||||
func NewPseudoRand() *rand {
|
func NewPseudoRand() *rand {
|
||||||
return &rand{rand: mathrand.New(mathrand.NewSource(CryptoRandInt()))}
|
var seed [32]byte
|
||||||
|
if _, err := cryptorand.Read(seed[:]); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return &rand{rand: mathrand2.New(mathrand2.NewChaCha8(seed))}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *rand) Float64() float64 {
|
func (r *rand) Float64() float64 {
|
||||||
|
@ -25,16 +29,10 @@ func (r *rand) Float64() float64 {
|
||||||
return r.rand.Float64()
|
return r.rand.Float64()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *rand) Intn(n int) int {
|
func (r *rand) IntN(n int) int {
|
||||||
r.Lock()
|
r.Lock()
|
||||||
defer r.Unlock()
|
defer r.Unlock()
|
||||||
return r.rand.Intn(n)
|
return r.rand.IntN(n)
|
||||||
}
|
|
||||||
|
|
||||||
func (r *rand) Read(buf []byte) (int, error) {
|
|
||||||
r.Lock()
|
|
||||||
defer r.Unlock()
|
|
||||||
return r.rand.Read(buf)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// CryptoRandInt returns a cryptographically random number.
|
// CryptoRandInt returns a cryptographically random number.
|
||||||
|
|
|
@ -5,7 +5,7 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
mathrand "math/rand"
|
mathrand2 "math/rand/v2"
|
||||||
"runtime/debug"
|
"runtime/debug"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -71,12 +71,11 @@ func refresh1(ctx context.Context, log mlog.Log, resolver dns.Resolver, sleep fu
|
||||||
}
|
}
|
||||||
|
|
||||||
// Randomize list.
|
// Randomize list.
|
||||||
rand := mathrand.New(mathrand.NewSource(time.Now().UnixNano()))
|
|
||||||
for i := range prs {
|
for i := range prs {
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
j := rand.Intn(i + 1)
|
j := mathrand2.IntN(i + 1)
|
||||||
prs[i], prs[j] = prs[j], prs[i]
|
prs[i], prs[j] = prs[j], prs[i]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,7 +86,7 @@ func refresh1(ctx context.Context, log mlog.Log, resolver dns.Resolver, sleep fu
|
||||||
go refreshDomain(ctx, log, DB, resolver, pr)
|
go refreshDomain(ctx, log, DB, resolver, pr)
|
||||||
if i < len(prs)-1 {
|
if i < len(prs)-1 {
|
||||||
interval := 3 * int64(time.Hour) / int64(len(prs)-1)
|
interval := 3 * int64(time.Hour) / int64(len(prs)-1)
|
||||||
extra := time.Duration(rand.Int63n(interval) - interval/2)
|
extra := time.Duration(mathrand2.Int64N(interval) - interval/2)
|
||||||
next := start.Add(time.Duration(int64(i+1)*interval) + extra)
|
next := start.Add(time.Duration(int64(i+1)*interval) + extra)
|
||||||
d := next.Sub(timeNow())
|
d := next.Sub(timeNow())
|
||||||
if d > 0 {
|
if d > 0 {
|
||||||
|
|
|
@ -1119,7 +1119,7 @@ func hookDeliver(log mlog.Log, h Hook) {
|
||||||
} else {
|
} else {
|
||||||
backoff = hookIntervals[len(hookIntervals)-1] * time.Duration(2)
|
backoff = hookIntervals[len(hookIntervals)-1] * time.Duration(2)
|
||||||
}
|
}
|
||||||
backoff += time.Duration(jitter.Intn(200)-100) * backoff / 10000
|
backoff += time.Duration(jitter.IntN(200)-100) * backoff / 10000
|
||||||
h.Attempts++
|
h.Attempts++
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
h.NextAttempt = now.Add(backoff)
|
h.NextAttempt = now.Add(backoff)
|
||||||
|
|
|
@ -1370,7 +1370,7 @@ func deliver(log mlog.Log, resolver dns.Resolver, m0 Msg) {
|
||||||
return fmt.Errorf("get message to be delivered: %v", err)
|
return fmt.Errorf("get message to be delivered: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
backoff = time.Duration(7*60+30+jitter.Intn(10)-5) * time.Second
|
backoff = time.Duration(7*60+30+jitter.IntN(10)-5) * time.Second
|
||||||
for i := 0; i < m0.Attempts; i++ {
|
for i := 0; i < m0.Attempts; i++ {
|
||||||
backoff *= time.Duration(2)
|
backoff *= time.Duration(2)
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,7 +73,7 @@ var jitterRand = mox.NewPseudoRand()
|
||||||
// Jitter so we don't cause load at exactly midnight, other processes may
|
// Jitter so we don't cause load at exactly midnight, other processes may
|
||||||
// already be doing that.
|
// already be doing that.
|
||||||
var jitteredTimeUntil = func(t time.Time) time.Duration {
|
var jitteredTimeUntil = func(t time.Time) time.Duration {
|
||||||
return time.Until(t.Add(time.Duration(240+jitterRand.Intn(120)) * time.Second))
|
return time.Until(t.Add(time.Duration(240+jitterRand.IntN(120)) * time.Second))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start launches a goroutine that wakes up just after 00:00 UTC to send TLSRPT
|
// Start launches a goroutine that wakes up just after 00:00 UTC to send TLSRPT
|
||||||
|
|
|
@ -7,7 +7,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
mathrand "math/rand"
|
mathrand2 "math/rand/v2"
|
||||||
"net/http"
|
"net/http"
|
||||||
"runtime/debug"
|
"runtime/debug"
|
||||||
"sync"
|
"sync"
|
||||||
|
@ -71,9 +71,6 @@ func (ew *eventWriter) write(name string, v any) error {
|
||||||
return ew.out.Flush()
|
return ew.out.Flush()
|
||||||
}
|
}
|
||||||
|
|
||||||
// For random wait between min and max delay.
|
|
||||||
var waitGen = mathrand.New(mathrand.NewSource(time.Now().UnixNano()))
|
|
||||||
|
|
||||||
// Schedule an event for writing to the connection. If events get a delay, this
|
// Schedule an event for writing to the connection. If events get a delay, this
|
||||||
// function still returns immediately.
|
// function still returns immediately.
|
||||||
func (ew *eventWriter) xsendEvent(ctx context.Context, log mlog.Log, name string, v any) {
|
func (ew *eventWriter) xsendEvent(ctx context.Context, log mlog.Log, name string, v any) {
|
||||||
|
@ -136,7 +133,7 @@ func (ew *eventWriter) xsendEvent(ctx context.Context, log mlog.Log, name string
|
||||||
}
|
}
|
||||||
// If we have an events channel, we have a goroutine that write the events, delayed.
|
// If we have an events channel, we have a goroutine that write the events, delayed.
|
||||||
if ew.events != nil {
|
if ew.events != nil {
|
||||||
wait := ew.waitMin + time.Duration(waitGen.Intn(1000))*(ew.waitMax-ew.waitMin)/1000
|
wait := ew.waitMin + time.Duration(mathrand2.IntN(1000))*(ew.waitMax-ew.waitMin)/1000
|
||||||
when := time.Now().Add(wait)
|
when := time.Now().Add(wait)
|
||||||
ew.events <- struct {
|
ew.events <- struct {
|
||||||
name string
|
name string
|
||||||
|
|
Loading…
Reference in a new issue