🚀
Cypress をサーバ起動まで待機させる Returns
前回、サーバが起動するまで cypress を待機させるために start-server-and-test を導入したが、それでも偶に(時と場合によっては頻繁に)エラーが出てしまう。
環境
- CircleCI 2.0
- cypress 4.12.1
- start-server-and-test 1.11.5
エラーの出力は以下の通り
Error: This socket has been ended by the other party
at Socket.writeAfterFIN [as write] (net.js:455:14)
at PoolWorker.writeJson (/home/circleci/front_workspace/node_modules/thread-loader/dist/WorkerPool.js:89:22)
at PoolWorker.run (/home/circleci/front_workspace/node_modules/thread-loader/dist/WorkerPool.js:69:12)
at WorkerPool.distributeJob (/home/circleci/front_workspace/node_modules/thread-loader/dist/WorkerPool.js:326:20)
at /home/circleci/front_workspace/node_modules/thread-loader/node_modules/async/queue.js:10:5
at Object.process (/home/circleci/front_workspace/node_modules/thread-loader/node_modules/async/internal/queue.js:175:17)
at /home/circleci/front_workspace/node_modules/thread-loader/node_modules/async/internal/queue.js:82:19
at Immediate.<anonymous> (/home/circleci/front_workspace/node_modules/thread-loader/node_modules/async/internal/setImmediate.js:27:16)
at processImmediate (internal/timers.js:456:21)
Emitted 'error' event on Socket instance at:
at emitErrorNT (net.js:1340:8)
at processTicksAndRejections (internal/process/task_queues.js:84:21) {
code: 'EPIPE'
}
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
Error: server closed unexpectedly
at ChildProcess.onClose (/home/circleci/front_workspace/node_modules/start-server-and-test/src/index.js:69:14)
at ChildProcess.emit (events.js:315:20)
at maybeClose (internal/child_process.js:1021:16)
at Process.ChildProcess._handle.onexit (internal/child_process.js:286:5)
- start-server-and-test がサブプロセスとして webpack-dev-server を起動
- プロセスの起動に execa を使っている
- コンパイル中にサブプロセスの stdio が閉じられて start-server-and-test がエラーを発生させる
動作確認のために CircleCI のイメージを使ってローカルでも試してみる。
$ docker run --rm -it -w /code -v $(pwd):/code circleci/node:12.18-browsers /bin/bash
しかし、ローカルで実行すると安定して動いてしまう。
原因は webpack の worker 数
webpack-dev-server の出力を抑えたり、CircleCI で失敗したステップのリトライを実装したり、curl で再実装したりと試行錯誤を繰り返してみたが、なかなか安定しない。しかし、何度か試すうちに webpack-dev-server 単体でも EPIPE が発生していることを確認できた。
Webpack は全くの素人なのだが、Webpackのビルド時間を短くするための取り組み - freee Developers Blog によると、ビルドには worker プロセスを起動しているようなので、このへんが怪しいと推測(サブプロセスと通信しており、それなら EPIPE が発生しそう)。
thread-loader のドキュメントを斜め読みしながら、手元の環境の設定を確認してみると以下のようになっていた。
const workerPool = {
workers: require('os').cpus().length - 1,
poolTimeout: Infinity,
workerParallelJobs: 30,
name: 'build-js-pool'
};
これだと、CI 環境で報告される CPU コア数が多いと簡単にメモリ不足になりそうだ。実際に、CircleCI で実行するときに workerPool
の中身を確認すると workers = 35
だった。さすがにこれは多すぎる。
最終的に、以下のように変更することで対処した。
const workerPool = {
workers: (process.env.CI ? 4 : require('os').cpus().length - 1),
poolTimeout: Infinity,
workerParallelJobs: 30,
name: 'build-js-pool'
};
もちろん、4
は適当な数なので各自の環境に合わせて調整してほしい。
Discussion