fix: cache lag retry, go.work, провайдер rollback, test v4 no -target
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
// Изменено: 2026-03-20 (merge: FunctionJob теперь самодостаточен — убран FunctionRef, добавлены Runtime/Entrypoint/Env)
|
||||
// Изменено: 2026-03-21 (fix: DeleteJob возвращает 404 вместо 204 при отсутствующем объекте)
|
||||
// Изменено: 2026-03-22 (fix: UploadJobCode retry loop против cache lag controller-runtime)
|
||||
// jobs.go — CRUD handlers для FunctionJob CRD.
|
||||
// Создаёт/читает/удаляет k8s FunctionJob ресурсы.
|
||||
// Namespace берётся из URL: /v1/namespaces/{namespace}/jobs/{name}
|
||||
@@ -12,6 +13,7 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
@@ -186,14 +188,24 @@ func (h *Handler) UploadJobCode(w http.ResponseWriter, r *http.Request) {
|
||||
ns := namespace(r)
|
||||
name := pathVar(r, "name")
|
||||
|
||||
// Читаем FunctionJob для получения runtime
|
||||
// Читаем FunctionJob для получения runtime.
|
||||
// Retry до 5 раз с задержкой 200мс — защита от cache lag controller-runtime:
|
||||
// сразу после POST /jobs (201) informer cache может ещё не синхронизировать новый CR.
|
||||
fj := &slessv1alpha1.FunctionJob{}
|
||||
if err := h.K8s.Get(r.Context(), client.ObjectKey{Name: name, Namespace: ns}, fj); err != nil {
|
||||
if errors.IsNotFound(err) {
|
||||
var getJobErr error
|
||||
for i := 0; i < 5; i++ {
|
||||
getJobErr = h.K8s.Get(r.Context(), client.ObjectKey{Name: name, Namespace: ns}, fj)
|
||||
if getJobErr == nil || !errors.IsNotFound(getJobErr) {
|
||||
break
|
||||
}
|
||||
time.Sleep(200 * time.Millisecond)
|
||||
}
|
||||
if getJobErr != nil {
|
||||
if errors.IsNotFound(getJobErr) {
|
||||
writeJSON(w, http.StatusNotFound, errResp("job not found"))
|
||||
return
|
||||
}
|
||||
writeJSON(w, http.StatusInternalServerError, errResp(err.Error()))
|
||||
writeJSON(w, http.StatusInternalServerError, errResp(getJobErr.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Создано: 2026-03-20 (function-service-split)
|
||||
// Изменено: 2026-03-21 (fix: DeleteService возвращает 404 вместо 204 при отсутствующем объекте)
|
||||
// Изменено: 2026-03-22 (fix: CreateService 409 при пересоздании сервиса через terraform -replace)
|
||||
// Изменено: 2026-03-23 (fix: UploadServiceCode retry при 404 из-за cache lag controller-runtime)
|
||||
// services.go — CRUD handlers для Service CRD (sless_service).
|
||||
// sless_service = long-running Deployment + URL. Каждый вызов проксируется к поду.
|
||||
// Namespace берётся из URL: /v1/namespaces/{namespace}/services/{name}
|
||||
@@ -352,13 +353,24 @@ func (h *Handler) UploadServiceCode(w http.ResponseWriter, r *http.Request) {
|
||||
ns := namespace(r)
|
||||
name := pathVar(r, "name")
|
||||
|
||||
// Retry до 5 раз с задержкой 200мс — защита от cache lag controller-runtime.
|
||||
// Проблема: после POST /services (201) кеш informer может не успеть обновиться,
|
||||
// и Get возвращает IsNotFound в течение ~100-400мс после создания CR.
|
||||
svc := &slessv1alpha1.Service{}
|
||||
if err := h.K8s.Get(r.Context(), client.ObjectKey{Name: name, Namespace: ns}, svc); err != nil {
|
||||
if errors.IsNotFound(err) {
|
||||
var getErr error
|
||||
for i := 0; i < 5; i++ {
|
||||
getErr = h.K8s.Get(r.Context(), client.ObjectKey{Name: name, Namespace: ns}, svc)
|
||||
if getErr == nil || !errors.IsNotFound(getErr) {
|
||||
break
|
||||
}
|
||||
time.Sleep(200 * time.Millisecond)
|
||||
}
|
||||
if getErr != nil {
|
||||
if errors.IsNotFound(getErr) {
|
||||
writeJSON(w, http.StatusNotFound, errResp("service not found"))
|
||||
return
|
||||
}
|
||||
writeJSON(w, http.StatusInternalServerError, errResp(err.Error()))
|
||||
writeJSON(w, http.StatusInternalServerError, errResp(getErr.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user