feat(httpapi): harden control plane and speed up prefix refresh

Очередь job получила lease и fencing, телеметрия и прогресс deploy сохраняются, ревизия пишет manifest входов. Обновление префиксов не переписывает неизменённый снимок, большие наборы идут через COPY, а устаревшая ревизия не попадает в deploy. Бандл ноды кэшируется, prune и постановка job больше не держат горячий путь.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
DenozordecandCursor committed 2026-11-02 17:23:59 +07:00
1 parent 924f111e48
commit f8e0520817
197 files changed
+18655 -1416

No files matched your search

+51 -8
View File
@@ -61,13 +61,17 @@ func nodeHTTPClient() *http.Client {
}
func fetchLatestRevision(base, token, speaker string) (string, error) {
return fetchLatestRevisionContext(context.Background(), base, token, speaker)
}
func fetchLatestRevisionContext(parent context.Context, base, token, speaker string) (string, error) {
u := strings.TrimRight(base, "/") + "/v1/speakers/" + speaker + "/revisions/latest"
req, err := http.NewRequest(http.MethodGet, u, nil)
if err != nil {
return "", err
}
req.Header.Set("Authorization", "Bearer "+token)
ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
ctx, cancel := context.WithTimeout(parent, 60*time.Second)
defer cancel()
resp, err := httpclient.DoWithRetry(ctx, nodeHTTPClient(), req, 3)
if err != nil {
@@ -75,13 +79,17 @@ func fetchLatestRevision(base, token, speaker string) (string, error) {
}
defer func() { _ = resp.Body.Close() }()
if resp.StatusCode != http.StatusOK {
b, _ := io.ReadAll(resp.Body)
b, _ := io.ReadAll(io.LimitReader(resp.Body, 4<<10))
return "", fmt.Errorf("latest revision: %s: %s", resp.Status, strings.TrimSpace(string(b)))
}
var out struct {
RevisionID string `json:"revision_id"`
}
if err := json.NewDecoder(resp.Body).Decode(&out); err != nil {
body, err := readHTTPBytes(resp, 64<<10)
if err != nil {
return "", err
}
if err := json.Unmarshal(body, &out); err != nil {
return "", err
}
if out.RevisionID == "" {
@@ -91,13 +99,21 @@ func fetchLatestRevision(base, token, speaker string) (string, error) {
}
func fetchBundle(base, token, speaker, revision string) ([]byte, error) {
return fetchBundleContext(context.Background(), base, token, speaker, revision, bundle.Limits{})
}
func fetchBundleContext(parent context.Context, base, token, speaker, revision string, limits bundle.Limits) ([]byte, error) {
l, err := limits.Normalized()
if err != nil {
return nil, err
}
u := strings.TrimRight(base, "/") + "/v1/speakers/" + speaker + "/bundle/" + revision
req, err := http.NewRequest(http.MethodGet, u, nil)
if err != nil {
return nil, err
}
req.Header.Set("Authorization", "Bearer "+token)
ctx, cancel := context.WithTimeout(context.Background(), 120*time.Second)
ctx, cancel := context.WithTimeout(parent, 120*time.Second)
defer cancel()
resp, err := httpclient.DoWithRetry(ctx, nodeHTTPClient(), req, 3)
if err != nil {
@@ -105,10 +121,37 @@ func fetchBundle(base, token, speaker, revision string) ([]byte, error) {
}
defer func() { _ = resp.Body.Close() }()
if resp.StatusCode != http.StatusOK {
b, _ := io.ReadAll(resp.Body)
b, _ := io.ReadAll(io.LimitReader(resp.Body, 4<<10))
return nil, fmt.Errorf("bundle: %s: %s", resp.Status, strings.TrimSpace(string(b)))
}
return io.ReadAll(resp.Body)
return readHTTPBytes(resp, l.MaxCompressedBytes)
}
func readHTTPBytes(resp *http.Response, limit int64) ([]byte, error) {
if resp.ContentLength > limit {
return nil, bundle.ErrLimit
}
return bundle.ReadCompressed(resp.Body, bundle.Limits{MaxCompressedBytes: limit})
}
func readBundleFile(path string, limits bundle.Limits) ([]byte, error) {
l, err := limits.Normalized()
if err != nil {
return nil, err
}
f, err := os.Open(path)
if err != nil {
return nil, err
}
defer func() { _ = f.Close() }()
info, err := f.Stat()
if err != nil {
return nil, err
}
if info.Size() > l.MaxCompressedBytes {
return nil, bundle.ErrLimit
}
return bundle.ReadCompressed(f, l)
}
func loadPubKey(pubB64, pubHex string) (ed25519.PublicKey, error) {
@@ -146,7 +189,7 @@ func CmdVerifyBundle(args []string) int {
fmt.Fprintln(os.Stderr, err)
return 2
}
raw, err := os.ReadFile(*path)
raw, err := readBundleFile(*path, bundle.Limits{})
if err != nil {
fmt.Fprintln(os.Stderr, err)
return 1
@@ -182,7 +225,7 @@ func CmdApplyBundle(args []string) int {
fmt.Fprintln(os.Stderr, err)
return 2
}
raw, err := os.ReadFile(*path)
raw, err := readBundleFile(*path, bundle.Limits{})
if err != nil {
fmt.Fprintln(os.Stderr, err)
return 1