mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-05-11 08:27:11 +00:00
12d1ada25e
* core: batch send stubs, comments * multiple events in ChatMessage and supporting types * Revert "multiple events in ChatMessage and supporting types" This reverts commit9b239b26ba. * schema, refactor group processing for batched messages * encoding, refactor processing * refactor code to work with updated schema * encoding, remove instances * wip * implement batching * batch introductions * wip * collect and send message history * missing new line * rename * test * rework to build history via chat items * refactor, tests * correctly set member version range, dont include deleted items * tests * fix disappearing messages * check number of errors * comment * check size in encodeChatMessage * fix - don't check msg size for binary * use builder * rename * rename * rework batching * lazy msg body * use withStoreBatch * refactor * reverse batches * comment * possibly fix builder for single msg * refactor batcher * refactor * dont repopulate msg_deliveries on down migration * EncodedChatMessage type * remove type * batcher tests * add tests * group history preference * test group link * fix tests * fix for random update * add test testImageFitsSingleBatch * refactor * rename function * refactor * mconcat * rename feature * catch error on each batch * refactor file inv retrieval * refactor gathering item forward events * refactor message batching * unite migrations * move files * refactor * Revert "unite migrations" This reverts commit0be7a3117a. * refactor splitFileDescr * improve tests * Revert "dont repopulate msg_deliveries on down migration" This reverts commit2944c1cc28. * fix down migration --------- Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>
54 lines
2.2 KiB
Haskell
54 lines
2.2 KiB
Haskell
{-# LANGUAGE DuplicateRecordFields #-}
|
|
{-# LANGUAGE LambdaCase #-}
|
|
{-# LANGUAGE NamedFieldPuns #-}
|
|
{-# LANGUAGE ScopedTypeVariables #-}
|
|
|
|
module Simplex.Chat.Messages.Batch
|
|
( MsgBatch (..),
|
|
batchMessages,
|
|
)
|
|
where
|
|
|
|
import Data.ByteString.Builder (Builder, charUtf8, lazyByteString)
|
|
import qualified Data.ByteString.Lazy as LB
|
|
import Data.Int (Int64)
|
|
import Simplex.Chat.Controller (ChatError (..), ChatErrorType (..))
|
|
import Simplex.Chat.Messages
|
|
|
|
data MsgBatch = MsgBatch Builder [SndMessage]
|
|
deriving (Show)
|
|
|
|
-- | Batches [SndMessage] into batches of ByteString builders in form of JSON arrays.
|
|
-- Does not check if the resulting batch is a valid JSON.
|
|
-- If a single element is passed, it is returned as is (a JSON string).
|
|
-- If an element exceeds maxLen, it is returned as ChatError.
|
|
batchMessages :: Int64 -> [SndMessage] -> [Either ChatError MsgBatch]
|
|
batchMessages maxLen msgs =
|
|
let (batches, batch, _, n) = foldr addToBatch ([], [], 0, 0) msgs
|
|
in if n == 0 then batches else msgBatch batch : batches
|
|
where
|
|
msgBatch batch = Right (MsgBatch (encodeMessages batch) batch)
|
|
addToBatch :: SndMessage -> ([Either ChatError MsgBatch], [SndMessage], Int64, Int) -> ([Either ChatError MsgBatch], [SndMessage], Int64, Int)
|
|
addToBatch msg@SndMessage {msgBody} (batches, batch, len, n)
|
|
| batchLen <= maxLen = (batches, msg : batch, len', n + 1)
|
|
| msgLen <= maxLen = (batches', [msg], msgLen, 1)
|
|
| otherwise = (errLarge msg : (if n == 0 then batches else batches'), [], 0, 0)
|
|
where
|
|
msgLen = LB.length msgBody
|
|
batches' = msgBatch batch : batches
|
|
len'
|
|
| n == 0 = msgLen
|
|
| otherwise = msgLen + len + 1 -- 1 accounts for comma
|
|
batchLen
|
|
| n == 0 = len'
|
|
| otherwise = len' + 2 -- 2 accounts for opening and closing brackets
|
|
errLarge SndMessage {msgId} = Left $ ChatError $ CEInternalError ("large message " <> show msgId)
|
|
|
|
encodeMessages :: [SndMessage] -> Builder
|
|
encodeMessages = \case
|
|
[] -> mempty
|
|
[msg] -> encodeMsg msg
|
|
(msg : msgs) -> charUtf8 '[' <> encodeMsg msg <> mconcat [charUtf8 ',' <> encodeMsg msg' | msg' <- msgs] <> charUtf8 ']'
|
|
where
|
|
encodeMsg SndMessage {msgBody} = lazyByteString msgBody
|