axiosのソケットリークでハマった
このシンプルなコードでソケットリークが起こる事に気付いた。
実際には膨大なコードの中からココに疑いも持った段階で9合目って感じだが・・・
const axios = require('axios'); const consumers = require('stream/consumers'); const get = (url) => { return new Promise(async (resolve, reject) => { try { const res = await axios.get(url, {responseType: 'stream'}); resolve(await consumers.buffer(res.data)); } catch (e) { reject(e); } }); };
responseType: 'stream'
を指定した場合は、Stream (Socket)がまだ開いていて自前で処理してあげなきゃならない。
consumers.buffer(res.data)
は、普通にchunk処理してBlobに渡してるだけだが、Streamを最後まで読んでいるのでcloseまで到達しているはずである。
ここは問題ない
問題はここ
} catch (e) { reject(e); }
盲点だったのだが、接続エラーで到達するならば問題ないが、なんとBad Request などでも到達するのだ。当然ペイロードがある。
そして responseType: 'stream'
ならば未処理のStreamである。
コイツがリークする!!
例外で飛んできてるので、response が受け取れてないが、例外の中に埋められている。
const _ = require('lodash'); const axios = require('axios'); const consumers = require('stream/consumers'); const get = (url) => { return new Promise(async (resolve, reject) => { try { const res = await axios.get(url, {responseType: 'stream'}); resolve(await consumers.buffer(res.data)); } catch (e) { const socket = _.get(e, 'response.data.socket'); if (socket) { socket.destroy(); } reject(e); } }); };
これで解決。
全然情報が無かったのだけど、、
レスポンスが正常に返ってくれば問題ないから気付き難いだけで、みんなリーク喰らってるんじゃないかな?