Proton/ja

Proton を使う利用者はウィキペディアの記事を PDF 化してダウンロードできます. デスクトップとモバイルビューと、出力はどちらにも対応します.

技術的な詳細
Proton は構造が単純なサービスで、PDF化に Puppeteer ライブラリ駆動の Chromium を使います. 構成要素は2件です.
 * すべてのリクエストを処理するキューシステム (PDF 作成のジョブはリソースと使用時間の両方を消費するため)
 * レンダラコードにより、Puppeteer にリクエストされたページの PDF 化を指示.

Proton はウェブ サービスとして提供中で記述は JavaScript、Node.js を利用します. 見た目が整って読みやすい書式の PDF 化を目指しました. ウィキメディアのウィキ群では Proton のプロキシは RESTBase 後方に置く予定です. ライブラリは puppeteer-core を使用、chromium ブラウザ機能を同梱しないので別途、ダウンロードしてください. chromium を実行可能に指定するため  環境変数を使用しています.

Article PDF の生成に最適な方法は、ブラウザにビルドインされたPDF機能を使うことです. その方法であれば出力結果も最良で、その上、私たちウィキペディアの利用者はデスクトップ版でもモバイル版でも、既存の印刷スタイルを再利用できます. システムは要求されたHTMLファイルのポストプロセスをしません. 記事は、ブラウザで印刷プレビュー表示したときと同じ見た目で印刷されます. 生成したPDF類はChromeブラウザでPrint to PDFを使った結果と（まったく同じではないにしても）ほぼ同じになります. 最良の結果を得るには、ProtonではJavaScriptを無効にします. これは動的なコンテンツの変換がまったく起こらないようにするためで、モバイル版のページで遅延読み込みした画像などがその一例です.

注記：利用者の中にはブラウザの印刷機能で得るPDFと、Protonサービスの利用結果がわずかに異なることがあり、利用者のシステムに固有のフォント最適化や字間調節設定の影響があります.

QueueSystem
Queue システムはProtonレンダラの心臓部です. それぞれのジョブの流れを待機・処理・タイムアウトの理論で扱います. キュー上のジョブ単位で2つの状態に切り替わります - 待機・処理中. 待ち行列を使うことで、特定のデータ量のジョブを並列処理できるばかりか、ジョブのタイムアウト、キャンセルにも対処します. Because of the queue complexity, we had to implement the solution that allows us to:


 * limit the number of waiting jobs
 * after a defined amount of seconds reject the waiting job
 * limit the number of rendering jobs (as PDF rendering requires lots of resources)
 * a safety net to reject rendering jobs that takes too much time
 * to save resources, when the request is aborted queue will try to cancel the job, doesn't matter which state the aborted job is (processing/rendering).

The queue system is based on Bluebird promises, and utilizes the cancellation feature (about which see #Known hacks below).

Renderer
The Renderer is a simple facade to access  method from puppeteer library. Renderer is responsible for setting proper chromium environment and browser viewport, requesting the Wikipedia page, calling the  function. Plus it keeps an eye on the browser process. Each render starts new Chromium instance, and after successful render, the chromium process exits. To save resources, and keep our system in good state Renderer asks Chromium to shut down and if because of any reason browser still keeps processing the request it will send the  to browser process to make sure it doesn't use any more CPU nor the memory.

その他の機能
キューがいっぱい、またはどこかの段階でタイムアウトしてジョブが完了しない時は、Proton サービスから Retry-After ヘッダ付きのコード  を返します. Retry-After ヘッダーはロード バランサーに当該の Proton ノードを回避させて現在のジョブ処理が終了します. システムは Retry-After ヘッダーを  設定値に設定します. その時点以降、処理ジョブはすべて終了され、システムは新しいジョブに取り掛かる流れです.

既知の問題点
Proton は BBPromise 拒否機能を採用します. キャンセル機能は既定で無効にしてあり、promise キャンセル機能を有効にするには、BBPromise.config の呼び出しに フラグを使います. ここでコツは、promise 作成の前に BBPromise 設定を済ませることです. ただし Proton が利用するService-runnerはすべての処理にBBPromisesを使い、設定ファイルの読み込みもその対象のため、前述の実行は簡単ではありません. フラグをProton アプリケーションに設定できない理由は、Proton コードの実行前にService-runnerが初期化されるからです. またconfig設定で指定もできず、Service-runner がconfig読み込みに promiseを使用するからです. Service-runnerのバージョン2.6.6では 環境変数の利用を導入しており、値は真 true に設定する必要があります. 環境変数が未設定の場合、Proton初期化は失敗し エラー通知が表示されます.

多言語をサポートするには、以下のフォントを実装時にインストールするよう推奨されます.


 * fonts-liberation
 * fonts-noto
 * fonts-noto-cjk
 * fonts-noto-cjk-extra
 * fonts-noto-color-emoji
 * fonts-noto-extra
 * fonts-noto-mono
 * fonts-noto-ui-core
 * fonts-noto-ui-extra
 * fonts-noto-unhinted

開発
Proton サービス Git リポジトリで開発を行います. コード レビューの場所は Gerrit です. アカウント登録は Getting started を参照してください. このサービスはプロジェクト テンプレートの ServiceTemplateNode を使用し、サービス開発規約すべてに準拠します.

テストを実行するには
To run all swagger tests and mocha tests:

npm test

To run all coverage tests:

npm run coverage

技術的な説明文書

 * README.MD には Proton 内部変数と設定変数の説明を記載.


 * ServiceTemplateNode/Deployment Proton サービスの実装手順
 * Reading/Web/Projects/Print_Styles 出力書式とできることの限界は Browser 印刷書式と同一.

Proton 開発者向けリンク

 * Proton Github リポジトリ
 * Puppeteer documentation
 * BBPromise 説明文書

関連項目

 * RESTBase: Proton を使って作成する PDF 向けのキャッシュ / 保存 API プロキシ
 * Proton: 状況の追跡、実装、データフローの詳細
 * Proton: 状況の追跡、実装、データフローの詳細

お問い合わせ
ヘルプが必要なとき、ご質問やフィードバックは、チャットルーム または wikitech-l メーリングリストにお問い合わせください.