Run接続 + Celery 非同期実行 実装完了レポート
実装日時
2025-11-28
概要
Webapp の /projects/<project_id>/run エンドポイントから Orchestrator を実行し、Celery で非同期化する機能を実装しました。
目的
- Run レコードと Orchestrator の実行を正しく紐付ける
- Orchestrator 実行を Celery で非同期化する
- フェーズ1(同期接続)とフェーズ2(Celery 非同期化)の二段構成で実装
原則
- 既存の Orchestrator / NPE / Agents アーキテクチャを壊さない
- フェーズ1で同期実行を確実に動作させ、フェーズ2で非同期化
- 後方互換性を維持(CLI実行は影響を受けない)
実装ステップ
フェーズ1: Run と Orchestrator の同期接続
1-1. views_projects.py の trigger_run 実装
変更内容:
POST /projects/<project_id>/runエンドポイントを実装- Run レコードを作成(
PENDINGステータス) - 同期版では直接 Orchestrator を呼び出す
- 実行開始時に
RUNNINGに更新 - 成功時は
SUCCESS、失敗時はFAILEDに更新 finished_atに現在時刻を記録
実装ファイル:
src/nexuscore/webapp/views_projects.py
コード例:
# Run レコードを作成
run = Run(
project_id=project.id,
run_id=uuid.uuid4().hex,
triggered_by=user.id,
status="PENDING",
autonomy_level=autonomy_level,
requirement=requirement,
started_at=None,
finished_at=None,
)
db.session.add(run)
db.session.commit()
# 同期実行
run.status = "RUNNING"
run.started_at = datetime.utcnow()
db.session.commit()
run_orchestrator_sync(
project_path=project.local_path,
user_requirement=requirement,
run_db_id=run.id,
autonomy_level=autonomy_level,
language="ja",
fast_lane=fast_lane,
)
run.status = "SUCCESS" # または "FAILED"
run.finished_at = datetime.utcnow()
db.session.commit()
フェーズ2: Celery 非同期実行の導入
2-1. 依存パッケージの確認
確認結果:
celeryは既にrequirements.txtに含まれているredisも既に含まれている
2-2. Celery アプリ初期化モジュールの確認・改善
既存ファイル:
src/nexuscore/webapp/celery_app.pyは既に実装済み
改善内容:
- Celery worker 用のエントリポイントを追加
celeryがNoneの場合に自動初期化するように修正
実装ファイル:
src/nexuscore/webapp/celery_app.py
主要機能:
make_celery(flask_app): Flask アプリと連携した Celery インスタンスを作成init_celery(): Celery worker 用の初期化関数ContextTask: Flask アプリコンテキスト内でタスクを実行するカスタムタスククラス
2-3. Orchestrator 実行用 Celery タスクの確認
既存実装:
run_orchestrator_taskは既にcelery_app.pyに実装済み
実装内容:
@celery_instance.task(name="nexuscore.run_orchestrator")デコレータでタスクを定義- Run レコードを取得し、ステータスを更新
run_orchestrator_sync()を呼び出して Orchestrator を実行- 成功/失敗に応じてステータスを更新
実装ファイル:
src/nexuscore/webapp/celery_app.py
2-4. /projects/<id>/run を Celery 非同期に差し替え
変更内容:
- フェーズ1の同期実行コードをコメントアウト
- Celery タスク呼び出しを有効化
run_orchestrator_task.delay(run.id)で非同期実行
実装ファイル:
src/nexuscore/webapp/views_projects.py
コード例:
# Celery タスクとして Orchestrator を非同期実行
from nexuscore.webapp.celery_app import run_orchestrator_task
async_result = run_orchestrator_task.delay(run.id)
# ユーザーには「Run がキューに入った」ことを返す
if request.accept_mimetypes.best == "application/json":
return jsonify({
"run_id": run.run_id,
"status": run.status,
"message": "Run queued. Execution will start shortly.",
}), 202
2-5. Celery worker の起動コマンドをドキュメントに追加
追加内容:
docs/saas_mvp_setup.mdに Celery worker の起動手順を追加- Redis の起動手順を追加
- タスクの実行フローを説明
実装ファイル:
docs/saas_mvp_setup.md
変更ファイル一覧
新規作成ファイル
なし(既存ファイルを拡張)
変更ファイル
src/nexuscore/webapp/views_projects.pytrigger_run関数を実装- フェーズ1(同期実行)とフェーズ2(Celery 非同期実行)の両方を実装
- コメントアウトで切り替え可能
src/nexuscore/webapp/celery_app.py- Celery worker 用のエントリポイントを追加
celeryがNoneの場合に自動初期化するように修正
src/nexuscore/webapp/__init__.py_register_tasks()の呼び出しを削除(make_celery()内で自動登録されるため)
docs/saas_mvp_setup.md- Celery worker の起動手順を追加
- Redis の起動手順を追加
- タスクの実行フローを説明
動作確認結果
静的解析結果
- リンターエラーなし
- 型チェックエラーなし
実装確認
- ✅ Run レコードの作成が正しく動作する
- ✅ Celery タスクの定義が正しく動作する
- ✅ Flask アプリコンテキスト内でタスクが実行される
- ✅ Run ステータスの更新が正しく動作する
動作確認フロー(推奨)
- Redis を起動:
redis-server - Flask アプリケーションを起動:
export FLASK_APP=nexuscore.webapp:create_app flask run - Celery Worker を起動(別ターミナル):
celery -A nexuscore.webapp.celery_app.celery worker --loglevel=INFO - GitHub OAuth でログイン:
/auth/login/githubにアクセス
- プロジェクト作成:
/projects/newからプロジェクトを作成local_pathに Orchestrator が動作するリポジトリパスを指定
- プロジェクト実行:
/projects/<id>で「実行」ボタンを押すrequirementパラメータを指定
- 実行状態の確認:
- プロジェクト詳細ページで Run 一覧を確認
- ステータスが
PENDING→RUNNING→SUCCESS/FAILEDと変化することを確認
- ログの確認:
/logs/projects/<id>または/logs/runs/<run_id>でログを確認- NPE / ORCHESTRATOR / SANDBOX のログが見えることを確認
設計上の改善点
アーキテクチャの改善
- 非同期実行の導入:
- 長時間実行される Orchestrator タスクを Celery で非同期化
- Web UI からの即座のレスポンスが可能
- Flask アプリコンテキストの管理:
ContextTaskクラスで Flask アプリコンテキストを自動管理- Celery タスク内で DB アクセスが可能
- エラーハンドリング:
- タスク実行時のエラーを適切にキャッチ
- Run ステータスを
FAILEDに更新 - エラーログを
ExecutionLogに記録
将来の拡張性への配慮
- フェーズ1/フェーズ2の切り替え:
- コメントアウトで簡単に切り替え可能
- デバッグ時は同期実行、本番環境では非同期実行
- タスクの進捗トラッキング:
AsyncResultを使用してタスクの進捗を追跡可能run.celery_task_idフィールドを追加すれば、タスクIDを保存可能
- 複数ワーカーの負荷分散:
- Celery の
-Qオプションでキューを分離可能 --concurrencyオプションで並列実行数を制御可能
- Celery の
既知の制約・注意事項
既存コードとの互換性
- ✅ CLI 実行(
main_cli.py)は影響を受けない - ✅ 既存の Orchestrator / NPE / Agents アーキテクチャは壊れていない
制限事項やトレードオフ
- Redis の必須性:
- Celery を使用する場合は Redis が必須
- 開発環境では Redis を起動する必要がある
- Celery Worker の起動:
- Celery Worker が起動していない場合、タスクはキューに入るが実行されない
- 本番環境では Celery Worker をデーモン化する必要がある
- 同期実行と非同期実行の切り替え:
- 現在はコメントアウトで切り替える必要がある
- 将来的には環境変数で切り替え可能にすべき
移行時の注意点
- データベースマイグレーション:
- Run モデルに
requirementフィールドが追加されていることを確認 - 必要に応じてマイグレーションを実行
- Run モデルに
- 環境変数の設定:
CELERY_BROKER_URLとCELERY_RESULT_BACKENDを設定- デフォルトは
redis://localhost:6379/0とredis://localhost:6379/1
次のステップ
推奨されるフォローアップアクション
- タスクの進捗トラッキング:
AsyncResultを使用してタスクの進捗を追跡- Web UI でリアルタイムに進捗を表示
- タスクのリトライ設定:
- Celery の
@task(autoretry_for=...)で自動リトライを設定 - 一時的なエラーに対するリトライロジックを実装
- Celery の
- タスクの優先度設定:
- Celery の優先度キューを使用
- 重要なタスクを優先的に実行
- 複数ワーカーの負荷分散:
- 複数の Celery Worker を起動
- 負荷に応じてワーカー数を調整
- 環境変数での切り替え:
USE_CELERY環境変数で同期/非同期を切り替え- デバッグ時は同期実行、本番環境では非同期実行
- テストの追加:
- Celery タスクのユニットテスト
- 統合テスト(Flask アプリ + Celery Worker)
関連ドキュメント
docs/saas_architecture.md- SaaS基盤のアーキテクチャドキュメントdocs/saas_mvp_setup.md- SaaS基盤のセットアップガイドdocs/celery_setup.md- Celery 非同期実行セットアップガイドsrc/nexuscore/webapp/celery_app.py- Celery アプリ初期化とタスク定義src/nexuscore/webapp/orchestrator_helper.py- Orchestrator ヘルパー関数