diff --git a/music-lab/app/main.py b/music-lab/app/main.py index 568c0aa..906f398 100644 --- a/music-lab/app/main.py +++ b/music-lab/app/main.py @@ -953,7 +953,7 @@ def create_pipeline(req: PipelineCreate): job = _db_module.get_compile_job(req.compile_job_id) if not job: raise HTTPException(404, f"compile job {req.compile_job_id} 없음") - if job.get("status") != "succeeded": + if job.get("status") not in ("done", "succeeded"): raise HTTPException(400, f"compile job {req.compile_job_id} not ready (status={job.get('status')})") # 동일 입력으로 이미 active 파이프라인 있으면 409 diff --git a/music-lab/app/pipeline/orchestrator.py b/music-lab/app/pipeline/orchestrator.py index ec27ed2..b49957f 100644 --- a/music-lab/app/pipeline/orchestrator.py +++ b/music-lab/app/pipeline/orchestrator.py @@ -71,7 +71,7 @@ def _resolve_input(p: dict) -> dict: if compile_id is not None: job = db.get_compile_job(compile_id) - if not job or job.get("status") != "succeeded": + if not job or job.get("status") not in ("done", "succeeded"): raise ValueError( f"compile job {compile_id} not ready " f"(status={job.get('status') if job else None})" diff --git a/music-lab/tests/test_orchestrator_resolve.py b/music-lab/tests/test_orchestrator_resolve.py index ed1b1a5..c08b7f5 100644 --- a/music-lab/tests/test_orchestrator_resolve.py +++ b/music-lab/tests/test_orchestrator_resolve.py @@ -59,3 +59,19 @@ def test_resolve_input_neither(): pipeline = {"id": 4, "track_id": None, "compile_job_id": None} with pytest.raises(ValueError): _resolve_input(pipeline) + + +def test_resolve_input_compile_job_done_status(): + """compile job status='done'도 accept (production convention).""" + pipeline = {"id": 5, "track_id": None, "compile_job_id": 7} + job = { + "id": 7, "status": "done", "title": "Done Mix", + "audio_path": "/app/data/compiles/7.mp3", + "track_ids": [1], "crossfade_sec": 0, + } + track = {"id": 1, "title": "T1", "duration_sec": 100} + with patch("app.pipeline.orchestrator.db.get_compile_job", return_value=job), \ + patch("app.pipeline.orchestrator.db.get_track_by_id", return_value=track): + result = _resolve_input(pipeline) + assert result["audio_path"] == "/app/data/compiles/7.mp3" + assert result["title"] == "Done Mix" diff --git a/music-lab/tests/test_pipeline_endpoints.py b/music-lab/tests/test_pipeline_endpoints.py index 13e19b8..abbcad7 100644 --- a/music-lab/tests/test_pipeline_endpoints.py +++ b/music-lab/tests/test_pipeline_endpoints.py @@ -174,3 +174,27 @@ def test_create_pipeline_with_visual_options(client): assert body["visual_style"] == "single" assert body["background_mode"] == "video_loop" assert body["background_keyword"] == "rain" + + +def test_create_pipeline_with_done_compile_job(client): + """compile job status='done' (production convention) — accept as ready.""" + import sqlite3 + conn = sqlite3.connect(db.DB_PATH) + cur = conn.cursor() + try: + cur.execute(""" + INSERT INTO compile_jobs (title, track_ids, crossfade_sec, + output_path, status, created_at) + VALUES ('Done Mix', '[1,2]', 3, '/app/data/compiles/X.mp3', + 'done', datetime()) + """) + except sqlite3.OperationalError: + pytest.skip("compile_jobs schema mismatch") + conn.commit() + cid = cur.lastrowid + conn.close() + + r = client.post("/api/music/pipeline", json={"compile_job_id": cid}) + assert r.status_code == 201, r.text + body = r.json() + assert body["compile_job_id"] == cid