conduitのMonadResource mをIOに変換する方法がわからない
前回出したpull requestに返信
awsパッケージは出来る子でした, 大容量のファイルのS3へのアップロードが出来なくなりました, yesodにpull requestを出しました - ncaq
前回yesod devel
のstack build
の--fast
消して欲しいというpull requestを提出しました.
remove the --fast
flag from stack build
executed by yesod devel
by ncaq · Pull Request #1442 · yesodweb/yesod
これにレスがついていたので返信します. 即座にレスポンスが帰ってきましたが, pull requestを開いた後寝たため1日経っての返信になります. 時差を感じる.
google翻訳で十分理解できる平易な英語で助かりました.
そしてgoogle翻訳で返信を書く. SVOで完結するだけの文章ならともかく, ある程度複雑な文章になるとgoogle翻訳を使わないと全く書けない… 文法というより語彙力の問題なのかな?
原文
レスポンスに感謝します.
@psibi
私は問題の発生源は特定できていません.
しかし,
多分,
問題があるとするなら,
conduitのバグではなく,
ByteStringの問題だと思います.
前に私はyesod-testで大きいサイズのファイルをたくさん投稿するプログラムを書いたことがあります.
最適化を無効にした(-O0
)時のみ,
投稿後にメモリが回収されずにOOM-killerが動くことになりました.
その時は,
まだyesod devel
はstackを使わずにbuildしていたので,
cabalファイルの最適化オプションをデフォルトに戻して,
対処しました.
@paul-rouse
私はcabalファイルでのghc-options: -O
が,
stack build
の--fast
で上書きされてしまうと考えていました.
それを確かめようと思って,
私はstack build --fast
されるとcabalファイルでの最適化オプションは無効化されると思っていました.
それを確かめようとメモリリークを再現させようとしてみたのですが,
今やってみたら再現しなくなりました…
再現性が確かじゃない問題を元にpull requestを建てて, ごめんなさい, このpull requestは閉じます.
何もわからなくなった
私はstack build --fast
するとcabalの記述に関わらず-O0
になると思っていて,
それを確かめようとメモリリーク問題を再現させようと思ったら再現しなくなった…
もう何もわからない…
フロントエンド側のfetchがエラーになってしまう問題を解決
とりあえず, 100MBレベルのファイルのアップロードにサーバ側では成功するのに, フロントエンド側ではfetchがNetwork Errorを送信する問題に手をつけてみることにしました.
サーバーサイドでは
POST /2/file/new
Accept: application/json
Status: 200 OK 145.737839s
で200 OKを返しているのに,
フロントエンドではTypeError: NetworkError when attempting to fetch resource.
エラーになってしまう.
firefoxのネットワークタブを見ると, 応答は空になっている.
とりあえずエラーの文章でググッてみたところ, fetchのリポジトリで同じようなissueがあったのを発見しました.
fetchのpolyfillが悪いのかな… でもfirefoxでは動かないはずだよな…? と思いながら, とりあえずfetchのpolyfillを削除してみます. しかし当然ながら状況は変わりませんでした.
ここのissueコメントにself-signed certとか書かれていたので,
自己署名したhttps://localhost:3443/
でテストしていたのが悪いのかと思ってhttpでテストしてみる.
そうするとちゃんと200の応答を待ってくれるようになりました.
redditにも同じような書き込みがありました. Fetch api not working in firefox addon : firefox
firefoxのbugとして登録されてないかなと思ってbugzillaどこからアクセスするんだっけと思ってWhat to do and what not to do in Bugzilla | MDNを見たらバグがめっちゃバクと書いてあってめっちゃウケた(直した).
冷静にredditの投稿を見なおしたら,
1346447 - Fetch api not working within addonへのリンクが貼られていた.
しかし,
この投稿ではCORSヘッダーの問題であるとして扱われていました.
私の案件は全てhttps://localhost:3443/
で扱っているのでクロスオリジンは関係ないはずなんですよね…
バグ報告を送るべきか? うーん, 前回yesodで失敗しただけに気後れがしますね… 要は自己署名証明書を使わずに開発時は平文で, 本番時は本物の証明書を使えば良い問題で, 実害がほぼないものを多大なコストをかけて報告する気にもならない…
conduitのMonadResource mをIOに変換する方法がわからない
効率のために
requestBodySourceChunked :: Source IO ByteString -> RequestBody
-- Defined in ‘Network.HTTP.Client.Conduit’
に
λ> :t fileSource fileInfo
fileSource fileInfo :: MonadResource m => Source m ByteString
をストリームを全部取得しない方法で渡したくて数日悩んでいた.
普通にやると当然ながら型が合わない.
<interactive>:1:28-46: error:
• No instance for (MonadResource IO)
arising from a use of ‘fileSource’
• In the second argument of ‘($)’, namely ‘fileSource fileInfo’
In the expression: requestBodySourceChunked $ fileSource fileInfo
無理なのでは?
requestBodySourceChunked
のソースを見てみると,
RequestBodyStreamChunked . srcToPopperIO
なので,
srcToPopperIO
ではなくsrcToPopperResource :: MonadResource m => Source m ByteString -> GivesPopper ()
を自作できればなんとかなるのではと思った.
無理だった,
何もわからない.
MonadResource m => Source m ByteString
をRequestBody
に変換する方法あると思うんですけどね…
私には作れなかった…
メモリを爆発させないで大容量ファイルのアップロードを実現する方法
- アップロードだけgoofysを使う(敗北宣言)
- ユーザのブラウザとS3を直接通信させる
- インスタンスのメモリサイズを増やす(物理で殴る)
- 一度
fileMove
でテンポラリファイルを作成して,Network.HTTP.Client.streamFile
で新しいストリームを作成する
今日はあまりにも無だった
ここ数日はうまく行かなくて行ったり戻ったりしていたけれど, 一応コードは書いていた.
今回はブラウザのバグ調べとかやってただけでほとんどコードを書けなかった. 無すぎる.
本当はもう少しやろうと思ってたけどプロファイリングを取ってみようとしてビルドしなおしてみたらメモリ8GBを使いきってPCが止まってしまったので今日はもうやめた. いい加減新しいPCを組みたいな, Ryzenをsegv問題さえなければ買っていたのだが.