chore: remove Airflow completely from the stack
Drop all four Airflow containers (db, init, webserver, scheduler) from the mlops compose profile, leaving MLflow as the sole mlops service. Remove AIRFLOW_* env vars, config fields, health-check entries, DAG trigger code in admin/bench routes, the airflow_dag_run_id schema column, Airflow nav links and DAG-run links in the admin UI, the two Airflow DAG files (bench_dag.py, sim_dag.py), and all related docs/ADR references. Simulations now run exclusively via the subprocess path. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -389,7 +389,7 @@ describe('GET /api/admin/events', () => {
|
||||
// Health endpoint — mock fetch so tests don't depend on running services.
|
||||
// ---------------------------------------------------------------------------
|
||||
describe('GET /api/admin/health', () => {
|
||||
const EXPECTED_HTTP_SERVICES = ['api', 'ml-serving', 'mlflow', 'airflow'] as const;
|
||||
const EXPECTED_HTTP_SERVICES = ['api', 'ml-serving', 'mlflow'] as const;
|
||||
const EXPECTED_INTERNAL = ['sqlite', 'event-bus'] as const;
|
||||
const VALID_STATUSES = new Set(['ok', 'degraded', 'down']);
|
||||
|
||||
@@ -404,7 +404,6 @@ describe('GET /api/admin/health', () => {
|
||||
let name: string;
|
||||
if (s.includes(':8000')) name = 'ml-serving';
|
||||
else if (s.includes(':5000')) name = 'mlflow';
|
||||
else if (s.includes(':8080')) name = 'airflow';
|
||||
else name = 'api';
|
||||
|
||||
if (!upServices.has(name)) throw new Error(`ECONNREFUSED ${name}`);
|
||||
@@ -415,7 +414,7 @@ describe('GET /api/admin/health', () => {
|
||||
afterEach(() => vi.unstubAllGlobals());
|
||||
|
||||
it('shape: 200, typed fields, all expected services present', async () => {
|
||||
mockFetch(new Set(['api', 'ml-serving', 'mlflow', 'airflow']));
|
||||
mockFetch(new Set(['api', 'ml-serving', 'mlflow']));
|
||||
const { server, call } = await startServer(buildApp());
|
||||
try {
|
||||
const { status, body } = await call('GET', '/api/admin/health');
|
||||
@@ -440,7 +439,7 @@ describe('GET /api/admin/health', () => {
|
||||
});
|
||||
|
||||
it('ok=true when all HTTP services respond 200', async () => {
|
||||
mockFetch(new Set(['api', 'ml-serving', 'mlflow', 'airflow']));
|
||||
mockFetch(new Set(['api', 'ml-serving', 'mlflow']));
|
||||
const { server, call } = await startServer(buildApp());
|
||||
try {
|
||||
const { body } = await call('GET', '/api/admin/health');
|
||||
@@ -456,7 +455,7 @@ describe('GET /api/admin/health', () => {
|
||||
});
|
||||
|
||||
it('ml-serving=down and ok=false when ml-serving is unreachable', async () => {
|
||||
mockFetch(new Set(['api', 'mlflow', 'airflow'])); // ml-serving absent
|
||||
mockFetch(new Set(['api', 'mlflow'])); // ml-serving absent
|
||||
const { server, call } = await startServer(buildApp());
|
||||
try {
|
||||
const { body } = await call('GET', '/api/admin/health');
|
||||
@@ -469,22 +468,8 @@ describe('GET /api/admin/health', () => {
|
||||
}
|
||||
});
|
||||
|
||||
it('airflow=down and ok=false when airflow is unreachable', async () => {
|
||||
mockFetch(new Set(['api', 'ml-serving', 'mlflow'])); // airflow absent
|
||||
const { server, call } = await startServer(buildApp());
|
||||
try {
|
||||
const { body } = await call('GET', '/api/admin/health');
|
||||
const b = body as HealthBody;
|
||||
const svc = b.services.find((s) => s.name === 'airflow');
|
||||
expect(svc?.status).toBe('down');
|
||||
expect(b.ok).toBe(false);
|
||||
} finally {
|
||||
server.close();
|
||||
}
|
||||
});
|
||||
|
||||
it('mlflow=down and ok=false when mlflow is unreachable', async () => {
|
||||
mockFetch(new Set(['api', 'ml-serving', 'airflow'])); // mlflow absent
|
||||
mockFetch(new Set(['api', 'ml-serving'])); // mlflow absent
|
||||
const { server, call } = await startServer(buildApp());
|
||||
try {
|
||||
const { body } = await call('GET', '/api/admin/health');
|
||||
|
||||
Reference in New Issue
Block a user