@@ -41,7 +41,7 @@ federationEnabled = not (federationSecret == "")
42-- ============================================
42-- ============================================
44−type PollEvent = {id: Text, eventType: Text, payload: {encryptedBlob: Text, fromKey: Text, timestamp: Timestamp, toKey: Text}}
44+type PollEvent = {id: MessageIdHex, eventType: Text, payload: {encryptedBlob: BlobHex, fromKey: PubkeyHex, timestamp: Timestamp, toKey: PubkeyHex}}
46type GossipEventType = Text where \s -> s == "online" || s == "offline"
46type GossipEventType = Text where \s -> s == "online" || s == "offline"
@@ -379,6 +379,12 @@ clampTtl = \ttl -> if ttl < 1 then 1 else if ttl > maxPresenceTtl then maxPresen
380clampTimestamp = \timestamp t -> if timestamp > t then t else if timestamp < t - messageMaxAge then t - messageMaxAge else timestamp
380clampTimestamp = \timestamp t -> if timestamp > t then t else if timestamp < t - messageMaxAge then t - messageMaxAge else timestamp
382+nextSeqTs = \t seqCounter -> if t > seqCounter then t else seqCounter + 1
384+isFederatedOrigin = \originServer -> not (originServer == "") && not (originServer == serverHostN)
386+takeN = \items n -> fold (\acc e -> if count acc >= n then acc else union acc [e]) [] items
382dedupMessageIds = \messageIds ->
388dedupMessageIds = \messageIds ->
383 fold (\acc mid ->
389 fold (\acc mid ->
384 let nmid = normalizeHex mid in
390 let nmid = normalizeHex mid in
@@ -544,14 +550,12 @@ maybePrune = \t -> do
544 set *lastPrunedAt = t
550 set *lastPrunedAt = t
545 pruneExpired t
551 pruneExpired t
547−sendBatchedGossipToServer : Text -> [{eventType: Text, pubkey: Text, server: Text, timestamp: Timestamp, ttl: Int}] -> IO {network} {}
553+sendBatchedGossipToServer : Text -> [{eventType: GossipEventType, pubkey: Text, server: Text, timestamp: Timestamp, ttl: Int<S>}] -> IO {network} {}
548sendBatchedGossipToServer = \server allEvents ->
554sendBatchedGossipToServer = \server allEvents ->
549 if count allEvents == 0
555 if count allEvents == 0
550 then yield {}
556 then yield {}
552− let batch = fold (\acc e ->
553− if count acc >= maxGossipEvents then acc
558+ let batch = takeN allEvents maxGossipEvents
554− else union acc [e]) [] allEvents
555 let rest = diff allEvents batch
559 let rest = diff allEvents batch
556 batchResult <- fetch (federationScheme ++ server) (RecvGossip {
560 batchResult <- fetch (federationScheme ++ server) (RecvGossip {
557 authorization: "Bearer " ++ federationSecret,
561 authorization: "Bearer " ++ federationSecret,
@@ -561,7 +565,7 @@ sendBatchedGossipToServer = \server allEvents ->
561 Err _ -> yield {}
565 Err _ -> yield {}
562 sendBatchedGossipToServer server rest
566 sendBatchedGossipToServer server rest
564−sendBatchedGossip : [Text] -> [{eventType: Text, pubkey: Text, server: Text, timestamp: Timestamp, ttl: Int}] -> IO {network} {}
568+sendBatchedGossip : [Text] -> [{eventType: GossipEventType, pubkey: Text, server: Text, timestamp: Timestamp, ttl: Int<S>}] -> IO {network} {}
565sendBatchedGossip = \peerServers allEvents ->
569sendBatchedGossip = \peerServers allEvents ->
566 if count allEvents == 0
570 if count allEvents == 0
567 then yield {}
571 then yield {}
@@ -582,7 +586,7 @@ broadcastOfflineGossip = \t peerServers expiredLocal -> do
582 sendBatchedGossip peerServers gossipEvents
586 sendBatchedGossip peerServers gossipEvents
583 else yield {}
587 else yield {}
585−retryForwardsForServer : [{encryptedBlob: Text, fromKey: Text, messageId: Text, timestamp: Timestamp, toKey: Text, toServer: Text}] -> Int -> IO {network} {}
589+retryForwardsForServer : [{encryptedBlob: BlobHex, fromKey: PubkeyHex, messageId: MessageIdHex, timestamp: Timestamp, toKey: PubkeyHex, toServer: ServerName}] -> Int -> IO {network} {}
586retryForwardsForServer = \entries remaining ->
590retryForwardsForServer = \entries remaining ->
587 if count entries == 0 || remaining <= 0
591 if count entries == 0 || remaining <= 0
588 then yield {}
592 then yield {}
@@ -608,21 +612,19 @@ retryForwardsForServer = \entries remaining ->
608 Err _ -> yield {}
612 Err _ -> yield {}
609 retryForwardsForServer rest (remaining - 1)
613 retryForwardsForServer rest (remaining - 1)
611−retryPendingForwards : [{encryptedBlob: Text, fromKey: Text, messageId: Text, timestamp: Timestamp, toKey: Text, toServer: Text}] -> IO {network} {}
615+retryPendingForwards : [{encryptedBlob: BlobHex, fromKey: PubkeyHex, messageId: MessageIdHex, timestamp: Timestamp, toKey: PubkeyHex, toServer: ServerName}] -> IO {network} {}
612retryPendingForwards = \pending -> do
616retryPendingForwards = \pending -> do
613 let servers = collectPeerServers pending (\x -> x.toServer)
617 let servers = collectPeerServers pending (\x -> x.toServer)
614 sendToEach servers (\server ->
618 sendToEach servers (\server ->
615 retryForwardsForServer (do x <- pending; where x.toServer == server; yield x) maxForwardRetriesPerServer)
619 retryForwardsForServer (do x <- pending; where x.toServer == server; yield x) maxForwardRetriesPerServer)
618−sendBatchedAcksToServer : [{messageId: Text, toKey: Text, originServer: Text, | a}] -> Text -> IO {network} {}
622+sendBatchedAcksToServer : [{messageId: MessageIdHex, toKey: PubkeyHex, originServer: Text, | a}] -> Text -> IO {network} {}
619sendBatchedAcksToServer = \serverAcks server ->
623sendBatchedAcksToServer = \serverAcks server ->
620 if count serverAcks == 0
624 if count serverAcks == 0
621 then yield {}
625 then yield {}
623− let batch = fold (\acc a ->
627+ let batch = takeN serverAcks maxMessageIds
624− if count acc >= maxMessageIds then acc
625− else union acc [a]) [] serverAcks
626 let rest = diff serverAcks batch
628 let rest = diff serverAcks batch
627 result <- fetch (federationScheme ++ server) (FederationAck {
629 result <- fetch (federationScheme ++ server) (FederationAck {
628 authorization: "Bearer " ++ federationSecret,
630 authorization: "Bearer " ++ federationSecret,
@@ -639,7 +641,7 @@ sendBatchedAcksToServer = \serverAcks server ->
639 Err _ -> yield {}
641 Err _ -> yield {}
640 sendBatchedAcksToServer rest server
642 sendBatchedAcksToServer rest server
642−sendAcksAndClean : [{messageId: Text, toKey: Text, originServer: Text, | a}] -> [Text] -> IO {network} {}
644+sendAcksAndClean : [{messageId: MessageIdHex, toKey: PubkeyHex, originServer: Text, | a}] -> [Text] -> IO {network} {}
643sendAcksAndClean = \pendingAcks servers ->
645sendAcksAndClean = \pendingAcks servers ->
644 sendToEach servers (\server ->
646 sendToEach servers (\server ->
645 sendBatchedAcksToServer (do a <- pendingAcks; where a.originServer == server; yield a) server)
647 sendBatchedAcksToServer (do a <- pendingAcks; where a.originServer == server; yield a) server)
@@ -655,8 +657,7 @@ pruneAndRetry = \t -> do
655 ackedIds <- *ackedIds
657 ackedIds <- *ackedIds
656 let pendingAcks = do
658 let pendingAcks = do
657 a <- ackedIds
659 a <- ackedIds
658− where not (a.originServer == "")
660+ where isFederatedOrigin a.originServer
659− where not (a.originServer == serverHostN)
661 yield {expiredLocal: pr.expiredLocal, peerServers: pr.peerServers, pendingForwards: pendingForwards, pendingAcks: pendingAcks}
662 yield {expiredLocal: pr.expiredLocal, peerServers: pr.peerServers, pendingForwards: pendingForwards, pendingAcks: pendingAcks}
662 broadcastOfflineGossip t result.peerServers result.expiredLocal
663 broadcastOfflineGossip t result.peerServers result.expiredLocal
@@ -832,7 +833,7 @@ serve = \req -> case req of
832 Just {value: s} -> s.pubkey
833 Just {value: s} -> s.pubkey
833 let authorized = isJust session
834 let authorized = isJust session
834 seqCounter <- *seqCounter
835 seqCounter <- *seqCounter
835− let seqTs = if t > seqCounter then t else seqCounter + 1
836+ let seqTs = nextSeqTs t seqCounter
836 let recipientMsgCount = countMessagesFor messages to t
837 let recipientMsgCount = countMessagesFor messages to t
837 let shouldInsert = authorized && recipientMsgCount < maxMessagesPerRecipient
838 let shouldInsert = authorized && recipientMsgCount < maxMessagesPerRecipient
838 set *seqCounter = if shouldInsert then seqTs else seqCounter
839 set *seqCounter = if shouldInsert then seqTs else seqCounter
@@ -858,9 +859,7 @@ serve = \req -> case req of
858 forwards <- *forwards
859 forwards <- *forwards
859 let forwardsAtCapacity = count forwards >= maxForwardsEntries
860 let forwardsAtCapacity = count forwards >= maxForwardsEntries
860 let forwardSlots = maxForwardsEntries - count forwards
861 let forwardSlots = maxForwardsEntries - count forwards
861− let forwardServers = fold (\acc s ->
862+ let forwardServers = takeN remoteServers forwardSlots
862− if count acc >= forwardSlots then acc
863− else union acc [s]) [] remoteServers
864 set *forwards = if shouldInsert && not forwardsAtCapacity && count forwardServers > 0 && federationEnabled
863 set *forwards = if shouldInsert && not forwardsAtCapacity && count forwardServers > 0 && federationEnabled
865 then union forwards (do s <- forwardServers; yield {messageId: msgId, toServer: s, createdAt: t, toKey: to, fromKey: fromKey, encryptedBlob: encryptedBlob, timestamp: clampedTs})
864 then union forwards (do s <- forwardServers; yield {messageId: msgId, toServer: s, createdAt: t, toKey: to, fromKey: fromKey, encryptedBlob: encryptedBlob, timestamp: clampedTs})
866 else forwards
865 else forwards
@@ -910,8 +909,7 @@ serve = \req -> case req of
910 Just {value: _} -> diff messages ackedMessages
909 Just {value: _} -> diff messages ackedMessages
911 let ackedFederated = do
910 let ackedFederated = do
912 m <- ackedMessages
911 m <- ackedMessages
913− where not (m.originServer == "")
912+ where isFederatedOrigin m.originServer
914− where not (m.originServer == serverHostN)
915 yield {messageId: m.messageId, toKey: m.toKey, ackedAt: t, originServer: m.originServer}
913 yield {messageId: m.messageId, toKey: m.toKey, ackedAt: t, originServer: m.originServer}
916 ackedIds <- *ackedIds
914 ackedIds <- *ackedIds
917 let combinedAckedIds = union ackedIds ackedFederated
915 let combinedAckedIds = union ackedIds ackedFederated
@@ -925,8 +923,7 @@ serve = \req -> case req of
925 yield {ok: ok, ackedMessages: ackedMessages, expiredLocal: pr.expiredLocal, peerServers: pr.peerServers, evictedEntries: evictedEntries}
923 yield {ok: ok, ackedMessages: ackedMessages, expiredLocal: pr.expiredLocal, peerServers: pr.peerServers, evictedEntries: evictedEntries}
926 let fedMessages = do
924 let fedMessages = do
927 m <- result.ackedMessages
925 m <- result.ackedMessages
928− where not (m.originServer == "")
926+ where isFederatedOrigin m.originServer
929− where not (m.originServer == serverHostN)
931 let originServers = collectPeerServers fedMessages (\m -> m.originServer)
928 let originServers = collectPeerServers fedMessages (\m -> m.originServer)
@@ -1063,9 +1060,7 @@ serve = \req -> case req of
1063 where none updatesOnlyAfterOffline (\p -> samePubkeyServer p e)
1060 where none updatesOnlyAfterOffline (\p -> samePubkeyServer p e)
1065 let reclaimedEntries = if withinCapacity then []
1062 let reclaimedEntries = if withinCapacity then []
1066− else fold (\acc e ->
1067− if count acc >= reclaimCapacity then acc
1063+ else takeN newEntries reclaimCapacity
1068− else union acc [e]) [] newEntries
1069 let afterReclaim = if withinCapacity then afterOffline
1064 let afterReclaim = if withinCapacity then afterOffline
1070 else union updatesOnlyAfterOffline reclaimedEntries
1065 else union updatesOnlyAfterOffline reclaimedEntries
1071 let appliedOnlineUpdates = if withinCapacity then appliedOnline
1066 let appliedOnlineUpdates = if withinCapacity then appliedOnline
@@ -1130,7 +1125,7 @@ serve = \req -> case req of
1130 pr <- maybePrune t
1125 pr <- maybePrune t
1131 messages <- *messages
1126 messages <- *messages
1132 seqCounter <- *seqCounter
1127 seqCounter <- *seqCounter
1133− let seqTs = if t > seqCounter then t else seqCounter + 1
1128+ let seqTs = nextSeqTs t seqCounter
1134 let recipientMsgCount = if not (authorized && validOrigin) then 0
1129 let recipientMsgCount = if not (authorized && validOrigin) then 0
1135 else countMessagesFor messages toKey t
1130 else countMessagesFor messages toKey t
1136 let existsInMessages = if not (authorized && validOrigin) then False {}
1131 let existsInMessages = if not (authorized && validOrigin) then False {}