Add dedupeBatch: collapse outbound calls per target

This commit is contained in:
2026-08-25 19:33:44 +03:00
parent 6bb96833e1
commit 3f5aa4735c
4 changed files with 85 additions and 23 deletions
+15
View File
@@ -5,6 +5,7 @@ module HomeAssistant.Runtime.Connection
( readerAction
, writerAction
, encodeService
, dedupeBatch
) where
import Control.Concurrent.STM
@@ -23,6 +24,8 @@ import Control.Lens ((^?))
import Control.Monad (forever, forM_)
import Data.Aeson (Value, eitherDecode, encode, object, (.=))
import Data.Aeson.Lens (key, _String)
import Data.List (sort)
import qualified Data.Map.Strict as M
import qualified Data.Set as S
import qualified Data.Text as T
import Data.Void (Void)
@@ -119,6 +122,18 @@ encodeService callId Service{..} = object $
, "target" .= targetObject serviceTarget
] <> maybe [] (\d -> ["service_data" .= d]) serviceData
-- | Collapse a drained batch of outbound calls: the newest call per
-- `(domain, service, sorted-targets)` survives; older duplicates are
-- dropped. `serviceData` is not part of the key, so a newer `turn_on`
-- with different brightness supersedes an older one to the same target.
dedupeBatch :: [(Request, Service)] -> [(Request, Service)]
dedupeBatch = M.elems . foldl' ins M.empty
where
ins m (req, svc) = M.insert (dedupeKey svc) (req, svc) m
dedupeKey :: Service -> (T.Text, T.Text, [Target])
dedupeKey Service{..} = (serviceDomain, serviceName, sort serviceTarget)
-- | A single target encodes as a scalar; multiple encode as a list. Empty
-- lists are omitted so Home Assistant receives only populated keys.
targetObject :: [Target] -> Value