最終更新: a few seconds agoRemove Netlify-related code from main (grafted, HEAD)

Linux 版 CIRCUS CS

概要

CIRCUS CS はオンライン CAD 実行プラットフォーム。

Outline

新 CIRCUS CS では以下の技術を使う。

  • Linux
  • Docker
  • MongoDB
  • JavaScript (Node.js, NPM)
  • DCMTK (C++; DICOM 通信に限る)

新 CIRCUS CS では以下の技術は使わない

  • Windows
  • PHP
  • Apache
  • PostgreSQL

CIRCUS CS Core (旧 Plugin Job Manager に相当)

circus-cs-core という NPM パッケージを作成して、CIRCUS CS のコア機能を実装する。基本的には npm install circus-cs-core とするだけで CIRCUS CS のコア管理機能が使えるようにする。

  • Core が Docker の逐次実行を担当する。
  • GUI/CUI は一切含まず、JavaScript API のみをエキスポートするモジュールを作成する。
  • CUI も別パッケージとして含めるが、上記の API を呼び出すだけの簡易的なラッパに過ぎない。

API(案)

すべての関数は非同期(Promise を返す)で実装すること。

  • start();
  • stop();
  • status();
  • pushToQueue(); 新しいジョブを発行
  • removeFromQueue(); ジョブをキャンセル
  • listQueue();

プラグイン

CIRCUS CS の CAD プラグインは、特定の規約(後述)に従って画像を処理する Docker のコンテナである。目的は大きく 2 つ。「CAD 実行のためのバイナリ依存物(JVM, Perl, Node など)をパッケージ化してインストールやメンテナンスコストを下げる」ことと、「無関係なネットワーク通信やディスクアクセスを禁止して仮想的に隔離された環境でプラグインを実行することでセキュリティを高める」こと。

プラグインは CIRCUS CS Core から(非デーモンとして)起動され、プラグイン処理が終了したら実行を終える。プラグインは正常終了した場合には 0、異常終了した場合にはそれ以外の終了コードを返す。

プラグイン実行の流れ

  1. Web UI などからキューにジョブ情報を登録
  2. Core がキューからジョブ情報を取得
  3. 前処理(作業用ディレクトリの /in にボリュームを作成)
    • 処理中であると CIRCUS のデータベース(MongoDB)に書き込み
    • JavaScript の DICOM パーサでタグを読み取って上記の *.raw, *.mhd, *.txt ファイルたちを作成する
  4. プラグイン実行(作業用ディレクトリをマウントして Docker コンテナを起動)
    • Docker を起動して死活監視を行う
  5. 後処理(作業用ディレクトリの /out から結果を取得して DB に登録)
    • 処理結果ステータスを CIRCUS のデータベース(MongoDB)に書き込み
    • 処理が成功していた場合は数値データをデータベースに書き込み
    • その他の結果ファイルについて結果ディレクトリに保存
  6. Core がキューからジョブ情報を削除
sequenceDiagram participant Core participant Docker participant DB as MongoDB Core ->> DB: キュー確認 Note over Core: 前処理 Core ->> DB: `processing` 書き込み Note right of Core: 作業領域作成 Note right of Core: ボリューム作成 Note over Core: プラグイン処理 Core ->>+ Docker: プラグイン起動 Core ->>- Docker: プラグイン実行状況監視 Note over Core: 後処理 Note right of Core: データvalidation Core ->> DB: JSON形式のジョブデータ保存 Note right of Core: 作業領域から保存 Note right of Core: 作業領域削除 Core ->> DB: キュー削除 Core ->> DB: `finished` 書き込み

将来的には前処理や後処理自体も Docker 化してキューに入れた方がスケーラビリティは上がるので、前処理・後処理は可能な限り独立して設計することが望ましい。

マウントするディレクトリについて

プラグインが起動する際に、その CAD の実行に必要なボリュームデータを含んだディレクトリがマウントされている。

プラグインコンテナは以下のようなディレクトリをマウントされた状態で起動される。

/circus/
  + in/
    + 0.vol   DICOM画像本体
    + 0.mhd   DICOM MHDメタデータ
    + 0.txt   DICOMタグ情報
  + out/
    + (CAD実行結果)
    + error.log

ジョブのステータス

すべての CAD ジョブの状態は以下のように遷移し、データベース内に書き込まれる。

graph LR in_queue ==> processing processing ==> finished processing -.-> failed in_queue -.-> cancelled finished -.-> invalidated
  • in_queue: ジョブが投入されており実行待ちの状態。
  • processing: ジョブが実行中の状態(前処理・本番処理・後処理を含む)。
  • finished: ジョブが正しく終了した状態。
  • invalidated: 何らかの理由でジョブを無効化した状態。
  • failed: ジョブが正しく終了しなかった状態。これには以下のようなパターンがあり、その詳細はエラーログに記録される。
    • 前処理中にシリーズに変更があった
    • プラグインが終了コード 0 で終了しなかった
    • プラグインが規定時間以内に終了しなかった
    • プラグインが終了したが out に結果が何も存在しなかった
    • 後処理中のファイルコピーなどで何らかの問題が生じた
  • cancelled: ジョブ開始前にキャンセルされた状態。キューからは削除されるが、ジョブ ID は記録として残る。

このうちジョブマネージャーは processing, finished, failed への遷移を担当する。他の遷移については

前処理について

前処理として行うことは以下の 3 つ。

  • MongoDB の pluginJobs の該当するジョブの status, startedAt, updatedAt をそれぞれ適切に更新する。
  • Docker コンテナにマウントするための作業ディレクトリを作成する(とりあえず /var/tmp 以下で)。
  • その下に画像ファイル、タグテキストファイルなどを作成する。各ファイルの仕様は http://www.ut-radiology.umin.jp/ical/CIRCUS/doc/html/plugin/exe.html にある通り。

後処理について

後処理として行うことは以下の 3 つ。

  • MongoDB の pluginJobs の該当するジョブの status, finishedAt, updatedAt をそれぞれ適切に更新する。
  • 作業ディレクトリの /out 配下の内容をジョブ結果ディレクトリにコピーする。
  • 作業ディレクトリの /out/results.txt を読み込んで JSON として解釈する。
  • /out/results.txt の内容について JSON Schema によるバリデーションをかける。
  • 作業ディレクトリを適切に削除する。
  • (キューからジョブを削除する)

データ型

CIRCUS CS データ構造を参照。

キュー管理/ジョブ管理について

とりあえず MongoDb のコレクションを使う。将来的には何らかのクラウドベースのキューシステムなどに移行する可能性あり。

画像リポジトリ(ほぼ実装済み)

CIRCUS RS / CIRCUS DB / CIRCUS CS で共通の画像リポジトリをそのまま採用する。

  • DICOM ファイル自体はファイルシステムに置く。
  • MongoDB でメタデータを管理する。
  • 実装を差し替えることでクラウドにも対応する。

Web UI 部分

CIRCUS DB とリポジトリレベルでほぼ共通とする。

  • React, Webpack, LESS, ...
  • ユーザ管理、権限システム

CIRCUS CS Dicom Storage Server

DICOM Storage Server はまだ C++で書く必要がある。現状の Windows 版を Linux に移植する。