Skip to content

Latest commit

 

History

History
81 lines (65 loc) · 4.25 KB

MeshPhase1ControlPlane.md

File metadata and controls

81 lines (65 loc) · 4.25 KB

Phase 1 — Mesh control plane (MVP)

Phase 1 adds an in-process director on any host that runs AddAshlar(): fleet node registry, mesh task store, and greedy placement (no migration, no external etcd).

Depends on: MeshPhase0NorthStar.md.

What is implemented

Component Behavior
IFleetNodeRegistry In-memory register/update/list/remove workers; heartbeat timestamp; drained flag excludes node from new placements.
IMeshTaskRegistry In-memory tasks with Pending → Assigned → Running → Succeeded/Failed; server-generated taskId.
IMeshTaskPlacementService Picks a node with non-empty ApiBaseUrl, not drained, affinity label match, and all RequiredBrickIds present in AdvertisedBrickIds (or label value brick:{id}). Retry skips the previously assigned peer when another candidate exists.
HTTP API (Ashlar.API) Under /api/mesh — see table below.

HTTP routes

Base path: /api/mesh (same auth middleware as other /api/* routes when enabled).

Method Path Purpose
GET /fleet/nodes List registered workers
POST /fleet/nodes Register or update worker (MeshFleetNodeRequest)
DELETE /fleet/nodes/{peerId} Remove worker
POST /fleet/nodes/{peerId}/heartbeat Heartbeat; optional body { "queueDepth": n } (Phase 5)
GET /elastic/status Phase 5: task counts + worker queue snapshot
POST /fleet/nodes/{peerId}/drain Body { "drained": true/false }
GET /tasks List tasks
POST /tasks Create task (MeshTaskCreateRequest)
GET /tasks/{taskId} Get task
POST /tasks/{taskId}/schedule Run placement (optional body: scheduleIdempotencyKey, correlationId, leaseSeconds)
POST /tasks/{taskId}/retry Re-place on different peer when possible (same optional body)
POST /tasks/{taskId}/lease/extend Phase 6: extend lease (leaseToken, optional extendSeconds)
POST /tasks/{taskId}/migrate-for-checkpoint Phase 6: record checkpointHandle, release assignment
GET /tasks/{taskId}/result Phase 3: stream bytes when resultHandle is a file path on director
PATCH /tasks/{taskId}/status Worker reports Running / Succeeded / Failed / Pending (optional resultSummary, resultHandle; Phase 6: leaseToken when task has a lease)
GET /knowledge/export Phase 4: JSON export of adaptations + patterns
POST /knowledge/import Phase 4: import payload into local stores

Worker registration example

POST /api/mesh/fleet/nodes
{
  "peerId": "worker-01",
  "apiBaseUrl": "https://worker-01.tailnet:8080/",
  "labels": { "region": "us-west" },
  "advertisedBrickIds": ["generation.capability-routing", "my-custom-brick"],
  "drained": false
}

Task + schedule example

POST /api/mesh/tasks
{
  "name": "batch-step-1",
  "steps": 1,
  "requiredBrickIds": ["my-custom-brick"],
  "affinity": { "region": "us-west" },
  "priority": 0,
  "deadlineUtc": null
}

Then POST /api/mesh/tasks/{taskId}/schedule. Response includes assignedPeerId and assignedApiBaseUrl for the caller to dispatch work (e.g. HTTP brick execute on that base URL — Phase 0 north star A).

Explicit limitations (next phases)

Tests

  • Ashlar.Tests.Infrastructure → Tests/Fleet/MeshTaskPlacementServiceTests.cs