Add server-side solver service module with REST API endpoints, database
schema, job definitions, and runner result caching.
New files:
- migrations/021_solver_results.sql: solver_results table with upsert constraint
- internal/db/solver_results.go: SolverResultRepository (Upsert, GetByItem, GetByItemRevision)
- internal/api/solver_handlers.go: solver API handlers and maybeCacheSolverResult hook
- jobdefs/assembly-solve.yaml: manual solve job definition
- jobdefs/assembly-validate.yaml: auto-validate on revision creation
- jobdefs/assembly-kinematic.yaml: manual kinematic simulation job
Modified:
- internal/config/config.go: SolverConfig struct with max_context_size_mb, default_timeout
- internal/modules/modules.go, loader.go: register solver module (depends on jobs)
- internal/db/jobs.go: ListSolverJobs helper with definition_name prefix filter
- internal/api/handlers.go: wire SolverResultRepository into Server
- internal/api/routes.go: /api/solver/* routes + /api/items/{partNumber}/solver/results
- internal/api/runner_handlers.go: async result cache hook on job completion
API endpoints:
- POST /api/solver/jobs — submit solver job (editor)
- GET /api/solver/jobs — list solver jobs with filters
- GET /api/solver/jobs/{id} — get solver job status
- POST /api/solver/jobs/{id}/cancel — cancel solver job (editor)
- GET /api/solver/solvers — registry of available solvers
- GET /api/items/{pn}/solver/results — cached results for item
Also fixes pre-existing test compilation errors (missing workflows param
in NewServer calls across 6 test files).
30 lines
1.1 KiB
PL/PgSQL
30 lines
1.1 KiB
PL/PgSQL
-- Migration 021: Solver result cache table
|
|
--
|
|
-- Stores the latest solve/diagnose/kinematic result per item revision.
|
|
-- The UNIQUE constraint means re-running an operation overwrites the previous result.
|
|
-- See docs/SOLVER.md Section 9.
|
|
|
|
BEGIN;
|
|
|
|
CREATE TABLE solver_results (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
item_id UUID NOT NULL REFERENCES items(id) ON DELETE CASCADE,
|
|
revision_number INTEGER NOT NULL,
|
|
job_id UUID REFERENCES jobs(id) ON DELETE SET NULL,
|
|
operation TEXT NOT NULL, -- 'solve', 'diagnose', 'kinematic'
|
|
solver_name TEXT NOT NULL,
|
|
status TEXT NOT NULL, -- SolveStatus string ('Success', 'Failed', etc.)
|
|
dof INTEGER,
|
|
diagnostics JSONB DEFAULT '[]',
|
|
placements JSONB DEFAULT '[]',
|
|
num_frames INTEGER DEFAULT 0,
|
|
solve_time_ms DOUBLE PRECISION,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
UNIQUE(item_id, revision_number, operation)
|
|
);
|
|
|
|
CREATE INDEX idx_solver_results_item ON solver_results(item_id);
|
|
CREATE INDEX idx_solver_results_status ON solver_results(status);
|
|
|
|
COMMIT;
|