feat: add durable schedule management and multi-node crash recovery

This commit is contained in:
2026-09-17 16:28:58 +08:00
parent d65cf96ea7
commit 6805506450
43 changed files with 2952 additions and 29 deletions

27
internal/timezone/LICENSE Normal file
View File

@@ -0,0 +1,27 @@
Copyright 2009 The Go Authors.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google LLC nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

61
internal/timezone/zone.go Normal file
View File

@@ -0,0 +1,61 @@
// Package timezone 提供随计划冻结的时区快照,禁止读取宿主机或 ZONEINFO 环境配置。
package timezone
import (
"archive/zip"
"bytes"
_ "embed"
"errors"
"io"
"sync"
"time"
)
// Version 标识 Go 1.27.1 附带的 IANA 快照及文件摘要;升级时须保留旧版本可读能力。
const Version = "go1.27.1-b2d18a7c8fa8"
//go:embed zoneinfo.zip
var data []byte
var zones sync.Map
var archive = sync.OnceValues(func() (*zip.Reader, error) { return zip.NewReader(bytes.NewReader(data), int64(len(data))) })
// Load 仅接受精确的内置名称,返回只读 Location;不接受 Local 或文件系统路径。
func Load(name, version string) (*time.Location, error) {
if version != Version || name == "" || name == "Local" || len(name) > 64 {
return nil, errors.New("unsupported frozen timezone version or name")
}
if name == "UTC" {
return time.UTC, nil
}
if v, ok := zones.Load(name); ok {
return v.(*time.Location), nil
}
a, err := archive()
if err != nil {
return nil, err
}
for _, entry := range a.File {
if entry.Name != name {
continue
}
r, err := entry.Open()
if err != nil {
return nil, err
}
b, err := io.ReadAll(io.LimitReader(r, 1<<20))
closeErr := r.Close()
if err != nil {
return nil, err
}
if closeErr != nil {
return nil, closeErr
}
loc, err := time.LoadLocationFromTZData(name, b)
if err != nil {
return nil, err
}
actual, _ := zones.LoadOrStore(name, loc)
return actual.(*time.Location), nil
}
return nil, errors.New("unknown IANA timezone")
}

View File

@@ -0,0 +1,38 @@
package timezone
import (
"crypto/sha256"
"fmt"
"testing"
"time"
)
func TestFrozenSnapshot(t *testing.T) {
if got := fmt.Sprintf("%x", sha256.Sum256(data)); got != "b2d18a7c8fa8142097a48c99609fb3c92db5ee98bc740294e57eab8ae9f94779" {
t.Fatal("snapshot changed without a new version")
}
t.Setenv("ZONEINFO", t.TempDir())
for _, name := range []string{"UTC", "Asia/Shanghai", "America/New_York", "Australia/Lord_Howe", "Pacific/Apia"} {
zone, err := Load(name, Version)
if err != nil || zone == nil {
t.Fatalf("load %s: %v", name, err)
}
again, err := Load(name, Version)
if err != nil || again != zone {
t.Fatal("cache changed")
}
}
zone, _ := Load("Asia/Shanghai", Version)
_, offset := time.Date(2026, 1, 1, 0, 0, 0, 0, zone).Zone()
if offset != 8*3600 {
t.Fatal("wrong frozen zone")
}
for _, name := range []string{"", "Local", "../UTC", "/etc/localtime"} {
if _, err := Load(name, Version); err == nil {
t.Fatal("accepted external timezone")
}
}
if _, err := Load("UTC", "unavailable-version"); err == nil {
t.Fatal("silently upgraded frozen version")
}
}

Binary file not shown.