Как запустить действие после того, как ответ был полностью отправлен в Scotty/WAI

По запросу GET мое веб-приложение Scotty выполнит некоторые вычисления и сохранит результат во временном файле, который будет отправлен в качестве ответа с использованием file.

Теперь я хотел бы выполнить некоторую очистку (т.е. удалить временный файл) после отправки файла. Скотти, кажется, не включает способ сделать это.

Есть ли в WAI какие-либо функции для достижения этой цели?


person theory_student    schedule 08.08.2020    source источник


Ответы (1)


wai дает нам функцию responseStream

responseStream :: Status -> ResponseHeaders -> StreamingBody -> Response

который создает Response из StreamingBody , что на самом деле является функцией

type StreamingBody = (Builder -> IO ()) -> IO () -> IO ()

что, учитывая действие записи и действие сброса, находит где-то несколько байтов и выполняет всю запись и сброс.

wai также предоставляет нам готовый файл responseFile функция:

responseFile :: Status -> ResponseHeaders -> FilePath -> Maybe FilePart -> Response

но он не удаляет файл в конце. Можем ли мы его как-то изменить? Кажется, что мы можем, с помощью responseToStream вспомогательная функция

responseToStream :: Response -> (Status, ResponseHeaders, (StreamingBody -> IO a) -> IO a)

это открывает уже построенный Response, позволяя нам настраивать вещи.

Как это:

import Network.Wai
import Network.HTTP.Types.Status (status200)
import System.Directory (removeFile)

responseFileDeleting' :: FilePath -> Response
responseFileDeleting' filepath = 
    let (status,header,streamer) = 
            responseToStream $ responseFile status200 [] filepath Nothing
     in responseStream status header (\write flush ->
             -- this would be a good place to put a bracket, if needed
             do streamer (\body -> body write flush)
                removeFile filepath)

(Примечание: тип streamer немного сбивает с толку из-за всего этого более высокого порядка.)

Недостатком этого решения является то, что запросы должны ждать, пока файл не будет удален для завершения. Другим вариантом может быть отправка путей к файлам в какой-то параллельная очередь, выполняющая удаление в другом потоке .

person danidiaz    schedule 08.08.2020