Add history-based state changes and recompute pipeline
This commit is contained in:
@@ -5,12 +5,14 @@ import (
|
||||
"strings"
|
||||
|
||||
"reanimator/internal/domain"
|
||||
historysvc "reanimator/internal/history"
|
||||
"reanimator/internal/repository/registry"
|
||||
)
|
||||
|
||||
type RegistryDependencies struct {
|
||||
Assets *registry.AssetRepository
|
||||
Components *registry.ComponentRepository
|
||||
History *historysvc.Service
|
||||
}
|
||||
|
||||
type registryHandlers struct {
|
||||
@@ -136,25 +138,61 @@ func (h registryHandlers) handleAssetByID(w http.ResponseWriter, r *http.Request
|
||||
writeError(w, http.StatusBadRequest, "vendor_serial is required")
|
||||
return
|
||||
}
|
||||
item, err := h.deps.Assets.Update(r.Context(), domain.Asset{
|
||||
ID: id,
|
||||
Name: strings.TrimSpace(req.Name),
|
||||
Vendor: normalizeOptionalString(req.Vendor),
|
||||
Model: normalizeOptionalString(req.Model),
|
||||
VendorSerial: strings.TrimSpace(req.VendorSerial),
|
||||
MachineTag: normalizeOptionalString(req.AssetTag),
|
||||
})
|
||||
var item domain.Asset
|
||||
var err error
|
||||
if h.deps.History != nil {
|
||||
patch := []historysvc.PatchOp{
|
||||
{Op: "replace", Path: "/identity/name", Value: strings.TrimSpace(req.Name)},
|
||||
{Op: "replace", Path: "/identity/vendor_serial", Value: strings.TrimSpace(req.VendorSerial)},
|
||||
{Op: "replace", Path: "/identity/vendor", Value: valueOrNil(normalizeOptionalString(req.Vendor))},
|
||||
{Op: "replace", Path: "/identity/model", Value: valueOrNil(normalizeOptionalString(req.Model))},
|
||||
{Op: "replace", Path: "/identity/machine_tag", Value: valueOrNil(normalizeOptionalString(req.AssetTag))},
|
||||
}
|
||||
idem := strings.TrimSpace(r.Header.Get("Idempotency-Key"))
|
||||
var idemPtr *string
|
||||
if idem != "" {
|
||||
idemPtr = &idem
|
||||
}
|
||||
_, err = h.deps.History.ApplyAssetPatch(r.Context(), historysvc.ApplyPatchCommand{
|
||||
EntityID: id,
|
||||
ChangeType: "ASSET_REGISTRY_UPDATED",
|
||||
SourceType: "user",
|
||||
ActorType: "user",
|
||||
IdempotencyKey: idemPtr,
|
||||
Patch: patch,
|
||||
})
|
||||
} else {
|
||||
item, err = h.deps.Assets.Update(r.Context(), domain.Asset{
|
||||
ID: id,
|
||||
Name: strings.TrimSpace(req.Name),
|
||||
Vendor: normalizeOptionalString(req.Vendor),
|
||||
Model: normalizeOptionalString(req.Model),
|
||||
VendorSerial: strings.TrimSpace(req.VendorSerial),
|
||||
MachineTag: normalizeOptionalString(req.AssetTag),
|
||||
})
|
||||
}
|
||||
if err != nil {
|
||||
switch err {
|
||||
case registry.ErrNotFound:
|
||||
writeError(w, http.StatusNotFound, "asset not found")
|
||||
case registry.ErrConflict:
|
||||
writeError(w, http.StatusConflict, "asset conflict")
|
||||
case historysvc.ErrNotFound:
|
||||
writeError(w, http.StatusNotFound, "asset not found")
|
||||
case historysvc.ErrConflict:
|
||||
writeError(w, http.StatusConflict, "history conflict")
|
||||
default:
|
||||
writeError(w, http.StatusInternalServerError, "update asset failed")
|
||||
}
|
||||
return
|
||||
}
|
||||
if h.deps.History != nil {
|
||||
item, err = h.deps.Assets.Get(r.Context(), id)
|
||||
if err != nil {
|
||||
writeError(w, http.StatusInternalServerError, "get asset failed")
|
||||
return
|
||||
}
|
||||
}
|
||||
writeJSON(w, http.StatusOK, item)
|
||||
default:
|
||||
w.WriteHeader(http.StatusMethodNotAllowed)
|
||||
@@ -242,18 +280,48 @@ func (h registryHandlers) handleComponentByID(w http.ResponseWriter, r *http.Req
|
||||
return
|
||||
}
|
||||
|
||||
item, err := h.deps.Components.Update(r.Context(), domain.Component{
|
||||
ID: id,
|
||||
Vendor: normalizeOptionalString(req.Vendor),
|
||||
Model: normalizeOptionalString(req.Model),
|
||||
VendorSerial: strings.TrimSpace(req.VendorSerial),
|
||||
})
|
||||
var item domain.Component
|
||||
var err error
|
||||
if h.deps.History != nil {
|
||||
patch := []historysvc.PatchOp{
|
||||
{Op: "replace", Path: "/identity/vendor_serial", Value: strings.TrimSpace(req.VendorSerial)},
|
||||
{Op: "replace", Path: "/identity/vendor", Value: valueOrNil(normalizeOptionalString(req.Vendor))},
|
||||
{Op: "replace", Path: "/identity/model", Value: valueOrNil(normalizeOptionalString(req.Model))},
|
||||
}
|
||||
idem := strings.TrimSpace(r.Header.Get("Idempotency-Key"))
|
||||
var idemPtr *string
|
||||
if idem != "" {
|
||||
idemPtr = &idem
|
||||
}
|
||||
_, err = h.deps.History.ApplyComponentPatch(r.Context(), historysvc.ApplyPatchCommand{
|
||||
EntityID: id,
|
||||
ChangeType: "COMPONENT_REGISTRY_UPDATED",
|
||||
SourceType: "user",
|
||||
ActorType: "user",
|
||||
IdempotencyKey: idemPtr,
|
||||
Patch: patch,
|
||||
})
|
||||
if err == nil {
|
||||
item, err = h.deps.Components.Get(r.Context(), id)
|
||||
}
|
||||
} else {
|
||||
item, err = h.deps.Components.Update(r.Context(), domain.Component{
|
||||
ID: id,
|
||||
Vendor: normalizeOptionalString(req.Vendor),
|
||||
Model: normalizeOptionalString(req.Model),
|
||||
VendorSerial: strings.TrimSpace(req.VendorSerial),
|
||||
})
|
||||
}
|
||||
if err != nil {
|
||||
switch err {
|
||||
case registry.ErrNotFound:
|
||||
writeError(w, http.StatusNotFound, "component not found")
|
||||
case registry.ErrConflict:
|
||||
writeError(w, http.StatusConflict, "component conflict")
|
||||
case historysvc.ErrNotFound:
|
||||
writeError(w, http.StatusNotFound, "component not found")
|
||||
case historysvc.ErrConflict:
|
||||
writeError(w, http.StatusConflict, "history conflict")
|
||||
default:
|
||||
writeError(w, http.StatusInternalServerError, "update component failed")
|
||||
}
|
||||
@@ -275,3 +343,10 @@ func normalizeOptionalString(value *string) *string {
|
||||
}
|
||||
return &trimmed
|
||||
}
|
||||
|
||||
func valueOrNil(value *string) any {
|
||||
if value == nil {
|
||||
return nil
|
||||
}
|
||||
return *value
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user