refactor: Phase 3a — absorb checkdefaults into core/app as pure Derive
Problem: check derivation logic lived in internal/checkdefaults with the pure decision logic (buildKind, address/user/port resolution) interleaved with tx I/O (entity_status insert, graph host fallback, check upserts) — and internal/db importing it was the plan's called-out inverted dependency. Change: - internal/core/app/checkdefaults.go: Derive(tree, target, lookup) — the full derivation (monitoring overrides, host fallback via an injected HostLookup thunk, per-kind builders) with zero I/O imports. Types renamed for the app surface: CheckTarget, CheckDef, DeriveResult, Skip; LogDeriveResult. - internal/adapters/postgres/checks.go absorbs the I/O half: EnsureChecks (entity_status row + upsert loop), writeCheck, and hostViaGraph. The db→checkdefaults edge is gone — adapters→core is the ADR 0016 direction (the Phase 7 SeedService note anticipated this; the inversion is fixed a phase early). - seed.go pending-checks loop uses app.CheckTarget + EnsureChecks; mcp formatting/tests follow the renamed types; both test files moved to internal/core/app. - Deliberate behavior note: a hostViaGraph read failure inside the thunk now logs a warning and degrades to 'skipped: no address' instead of aborting the whole entity-create tx — a monitoring derivation gap is visible (warn log + coverage sweep) and self-heals on the next mutation; failing the create over a graph-read blip was disproportionate. Verification: go build/vet, full test suite green (app tests exercise every buildKind branch at their new home).
This commit is contained in:
@@ -6,7 +6,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/dtoro/oikos/internal/checkdefaults"
|
||||
"github.com/dtoro/oikos/internal/core/app"
|
||||
"github.com/google/uuid"
|
||||
"github.com/jackc/pgx/v5"
|
||||
)
|
||||
@@ -105,7 +105,7 @@ func IngestInventorySeed(ctx context.Context, tx pgx.Tx, data map[string]any) (*
|
||||
// Entities
|
||||
entities, _ := data["entities"].([]any)
|
||||
entityTypes := make(map[string]string) // slug -> type, for edge validation
|
||||
var pendingChecks []checkdefaults.Target
|
||||
var pendingChecks []app.CheckTarget
|
||||
for _, raw := range entities {
|
||||
eMap, ok := raw.(map[string]any)
|
||||
if !ok {
|
||||
@@ -157,8 +157,8 @@ func IngestInventorySeed(ctx context.Context, tx pgx.Tx, data map[string]any) (*
|
||||
// Default checks are deferred until after relationships are ingested:
|
||||
// a service has no address of its own and inherits its container's,
|
||||
// which means the hosting edge has to exist first.
|
||||
pendingChecks = append(pendingChecks, checkdefaults.Target{
|
||||
ID: entityID, Slug: slug, Type: typeName, Name: name, Attrs: attrsBytes,
|
||||
pendingChecks = append(pendingChecks, app.CheckTarget{
|
||||
ID: entityID.String(), Slug: slug, Type: typeName, Name: name, Attrs: attrsBytes,
|
||||
})
|
||||
|
||||
r.Entities++
|
||||
@@ -228,11 +228,11 @@ func IngestInventorySeed(ctx context.Context, tx pgx.Tx, data map[string]any) (*
|
||||
// transaction while surfacing as an unrelated failure several entities
|
||||
// later.
|
||||
for _, target := range pendingChecks {
|
||||
res, err := checkdefaults.Ensure(ctx, tx, tree, target)
|
||||
res, err := EnsureChecks(ctx, tx, tree, target)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("default checks for %s: %w", target.Slug, err)
|
||||
}
|
||||
checkdefaults.LogResult(target.Slug, target.Type, res)
|
||||
app.LogDeriveResult(target.Slug, target.Type, res)
|
||||
r.Checks += res.Created
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user