mirror of
https://github.com/kopia/kopia.git
synced 2026-01-01 11:07:50 -05:00
- upgrade to golangci-lint 2.6.1 - updates for gosec - updates for govet - updates for perfsprint - updates modernize Leaves out modernize:omitempty due to conflicts with tests
78 lines
2.0 KiB
Go
78 lines
2.0 KiB
Go
//go:build testing
|
|
|
|
package clock
|
|
|
|
import (
|
|
"encoding/json"
|
|
"log"
|
|
"net/http"
|
|
"os"
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
const refreshServerTimeEvery = 3 * time.Second
|
|
|
|
// Now is overridable function that returns current wall clock time.
|
|
var Now = func() time.Time {
|
|
return discardMonotonicTime(time.Now()) //nolint:forbidigo
|
|
}
|
|
|
|
func init() {
|
|
fakeTimeServer := os.Getenv("KOPIA_FAKE_CLOCK_ENDPOINT")
|
|
if fakeTimeServer == "" {
|
|
return
|
|
}
|
|
|
|
Now = getTimeFromServer(fakeTimeServer)
|
|
}
|
|
|
|
// getTimeFromServer returns a function that will return timestamp as returned by the server
|
|
// increasing it client-side by certain interval until maximum is reached, at which point
|
|
// it will ask the server again for new timestamp.
|
|
//
|
|
// The server endpoint must be HTTP and be set using KOPIA_FAKE_CLOCK_ENDPOINT environment
|
|
// variable.
|
|
func getTimeFromServer(endpoint string) func() time.Time {
|
|
var mu sync.Mutex
|
|
|
|
var timeInfo struct {
|
|
Time time.Time `json:"time"`
|
|
ValidFor time.Duration `json:"validFor"`
|
|
}
|
|
|
|
var (
|
|
nextRefreshRealTime time.Time //nolint:forbidigo
|
|
localTimeOffset time.Duration // offset to be added to time.Now() to produce server time
|
|
)
|
|
|
|
return func() time.Time {
|
|
mu.Lock()
|
|
defer mu.Unlock()
|
|
|
|
localTime := time.Now() //nolint:forbidigo
|
|
if localTime.After(nextRefreshRealTime) {
|
|
resp, err := http.Get(endpoint) //nolint:gosec,noctx
|
|
if err != nil {
|
|
log.Fatalf("unable to get fake time from server: %v", err)
|
|
}
|
|
defer resp.Body.Close() //nolint:errcheck
|
|
|
|
if resp.StatusCode != http.StatusOK {
|
|
log.Fatalf("unable to get fake time from server: %v", resp.Status)
|
|
}
|
|
|
|
if err := json.NewDecoder(resp.Body).Decode(&timeInfo); err != nil {
|
|
log.Fatalf("invalid time received from fake time server: %v", err)
|
|
}
|
|
|
|
nextRefreshRealTime = localTime.Add(timeInfo.ValidFor) //nolint:forbidigo
|
|
|
|
// compute offset such that localTime + localTimeOffset == serverTime
|
|
localTimeOffset = timeInfo.Time.Sub(localTime)
|
|
}
|
|
|
|
return discardMonotonicTime(localTime.Add(localTimeOffset))
|
|
}
|
|
}
|