У меня есть код, который использует дескриптор файла для имитации приемника потоковой передачи Bytestring
из источника (AWS S3
). Если мы хотим использовать Network.Websocket
в качестве приемника , достаточно ли заменить LBS.writeFile
в приведенном ниже коде на sendBinaryData
(с дескриптором подключения)?
{-# LANGUAGE OverloadedStrings,ScopedTypeVariables #-}
import qualified Aws
import qualified Aws.S3 as S3
import Data.Conduit (($$+-))
import qualified Data.Conduit.List as CL (mapM_)
import qualified Data.ByteString.Streaming.HTTP as SP
import qualified Data.ByteString.Lazy as LBS
import Streaming as S
import Streaming.Prelude as S hiding (show,print)
import Control.Concurrent.Async (async,waitCatch)
import Data.Text as T (Text)
data AwsConfig a = AwsConfig { _aws_cfg :: Aws.Configuration, _aws_s3cfg :: S3.S3Configuration a, _aws_httpmgr :: SP.Manager }
getObject :: AwsConfig Aws.NormalQuery -> T.Text -> T.Text -> IO Int
getObject cfg bucket key = do
req <- waitCatch =<< async (runResourceT $ do
{- Create a request object with S3.getObject and run the request with pureAws. -}
S3.GetObjectResponse { S3.gorResponse = rsp, S3.gorMetadata = mdata } <-
Aws.pureAws (_aws_cfg cfg) (_aws_s3cfg cfg) (_aws_httpmgr cfg) $
S3.getObject bucket key
{- Stream the response to a lazy bytestring -}
liftIO $ LBS.writeFile "testaws" LBS.empty -- this will be replaced by content-length of the bytes
let obj = (($$+- CL.mapM_ S.yield) . hoist lift ) (SP.responseBody rsp)
S.mapM_ (liftIO . (LBS.appendFile "testaws") . LBS.fromStrict) obj
return $ lookup "content-length" (S3.omUserMetadata mdata))
case req of
Left _ -> return 2 -- perhaps, we could use this to send an error message over websocket
Right _ -> return 0
Источником путаницы для меня является то, как определяется завершение потока? В случае файлов об этом заботится writeFile
API. А как насчет sendBinaryData
? Обрабатывает ли он завершение так же, как writeFile
? Или это определяется парсером данных на стороне клиента?
Обновить
Этот вопрос касается того, как передать данные в дескриптор веб-сокета (допустим, дескриптор был предоставлен), как мы делаем с дескриптором файла в приведенном выше примере, а не о том, как управлять дескриптором в resourceT
. conduit
действительно занимает mapM_
< /a> подход к приему данных. Так что, кажется, это действительно путь.
Вопрос об завершении связан с моим ходом мыслей: если у нас есть функция, прослушивающая данные на другой стороне дескриптора веб-сокета, то определение конца сообщения, по-видимому, имеет значение в контексте потоковой передачи. Учитывая функцию, как показано ниже:
f :: LBS.ByteString -> a
если мы делаем S.mapM_
для потоковой передачи данных в дескриптор веб-сокета, позаботится ли он о добавлении какого-либо маркера end of stream
, чтобы f
прослушивание на другой стороне могло прекратить обработку ленивой строки байтов. В противном случае f
не узнает, когда сообщение будет готово.
websockets
- person Michael   schedule 14.06.2016