mirror of
https://github.com/ilyakooo0/urbit.git
synced 2025-01-07 07:30:23 +03:00
Merge pull request #3147 from urbit/pp/king-bounded-ames
king: drop ames packets when >1k are unprocessed
This commit is contained in:
commit
88ee19ae13
@ -2,12 +2,12 @@
|
|||||||
Ames IO Driver
|
Ames IO Driver
|
||||||
-}
|
-}
|
||||||
|
|
||||||
module Urbit.Vere.Ames (ames, ames') where
|
module Urbit.Vere.Ames (ames, ames', PacketOutcome(..)) where
|
||||||
|
|
||||||
import Urbit.Prelude
|
import Urbit.Prelude
|
||||||
|
|
||||||
import Network.Socket hiding (recvFrom, sendTo)
|
import Network.Socket hiding (recvFrom, sendTo)
|
||||||
import Urbit.Arvo hiding (Fake)
|
import Urbit.Arvo hiding (Fake)
|
||||||
import Urbit.King.Config
|
import Urbit.King.Config
|
||||||
import Urbit.Vere.Pier.Types
|
import Urbit.Vere.Pier.Types
|
||||||
|
|
||||||
@ -17,15 +17,33 @@ import Urbit.Vere.Ames.DNS (galaxyPort, resolvServ)
|
|||||||
import Urbit.Vere.Ames.UDP (UdpServ(..), fakeUdpServ, realUdpServ)
|
import Urbit.Vere.Ames.UDP (UdpServ(..), fakeUdpServ, realUdpServ)
|
||||||
|
|
||||||
|
|
||||||
|
-- Constants -------------------------------------------------------------------
|
||||||
|
|
||||||
|
-- | How many unprocessed ames packets to allow in the queue before we start
|
||||||
|
-- dropping incoming packets.
|
||||||
|
queueBound :: Word
|
||||||
|
queueBound = 1000
|
||||||
|
|
||||||
|
-- | How often, measured in number of packets dropped, we should announce packet
|
||||||
|
-- loss.
|
||||||
|
packetsDroppedPerComplaint :: Word
|
||||||
|
packetsDroppedPerComplaint = 1000
|
||||||
|
|
||||||
|
|
||||||
-- Types -----------------------------------------------------------------------
|
-- Types -----------------------------------------------------------------------
|
||||||
|
|
||||||
data AmesDrv = AmesDrv
|
data AmesDrv = AmesDrv
|
||||||
{ aTurfs :: TVar (Maybe [Turf])
|
{ aTurfs :: TVar (Maybe [Turf])
|
||||||
|
, aDropped :: TVar Word
|
||||||
, aUdpServ :: UdpServ
|
, aUdpServ :: UdpServ
|
||||||
, aResolvr :: ResolvServ
|
, aResolvr :: ResolvServ
|
||||||
, aRecvTid :: Async ()
|
, aRecvTid :: Async ()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data PacketOutcome
|
||||||
|
= Intake
|
||||||
|
| Ouster
|
||||||
|
|
||||||
|
|
||||||
-- Utils -----------------------------------------------------------------------
|
-- Utils -----------------------------------------------------------------------
|
||||||
|
|
||||||
@ -106,13 +124,34 @@ ames'
|
|||||||
-> (Text -> RIO e ())
|
-> (Text -> RIO e ())
|
||||||
-> RIO e ([Ev], RAcquire e (DriverApi NewtEf))
|
-> RIO e ([Ev], RAcquire e (DriverApi NewtEf))
|
||||||
ames' who isFake stderr = do
|
ames' who isFake stderr = do
|
||||||
|
-- Unfortunately, we cannot use TBQueue because the only behavior
|
||||||
|
-- provided for when full is to block the writer. The implementation
|
||||||
|
-- below uses materially the same data structures as TBQueue, however.
|
||||||
ventQ :: TQueue EvErr <- newTQueueIO
|
ventQ :: TQueue EvErr <- newTQueueIO
|
||||||
|
avail :: TVar Word <- newTVarIO queueBound
|
||||||
|
let
|
||||||
|
enqueuePacket p = do
|
||||||
|
vail <- readTVar avail
|
||||||
|
if vail > 0
|
||||||
|
then do
|
||||||
|
modifyTVar avail (subtract 1)
|
||||||
|
writeTQueue ventQ p
|
||||||
|
pure Intake
|
||||||
|
else do
|
||||||
|
_ <- readTQueue ventQ
|
||||||
|
writeTQueue ventQ p
|
||||||
|
pure Ouster
|
||||||
|
dequeuePacket = do
|
||||||
|
pM <- tryReadTQueue ventQ
|
||||||
|
when (isJust pM) $ modifyTVar avail (+ 1)
|
||||||
|
pure pM
|
||||||
|
|
||||||
env <- ask
|
env <- ask
|
||||||
let (bornEvs, startDriver) = ames env who isFake (writeTQueue ventQ) stderr
|
let (bornEvs, startDriver) = ames env who isFake enqueuePacket stderr
|
||||||
|
|
||||||
let runDriver = do
|
let runDriver = do
|
||||||
diOnEffect <- startDriver
|
diOnEffect <- startDriver
|
||||||
let diEventSource = fmap RRWork <$> tryReadTQueue ventQ
|
let diEventSource = fmap RRWork <$> dequeuePacket
|
||||||
pure (DriverApi {..})
|
pure (DriverApi {..})
|
||||||
|
|
||||||
pure (bornEvs, runDriver)
|
pure (bornEvs, runDriver)
|
||||||
@ -135,7 +174,7 @@ ames
|
|||||||
=> e
|
=> e
|
||||||
-> Ship
|
-> Ship
|
||||||
-> Bool
|
-> Bool
|
||||||
-> (EvErr -> STM ())
|
-> (EvErr -> STM PacketOutcome)
|
||||||
-> (Text -> RIO e ())
|
-> (Text -> RIO e ())
|
||||||
-> ([Ev], RAcquire e (NewtEf -> IO ()))
|
-> ([Ev], RAcquire e (NewtEf -> IO ()))
|
||||||
ames env who isFake enqueueEv stderr = (initialEvents, runAmes)
|
ames env who isFake enqueueEv stderr = (initialEvents, runAmes)
|
||||||
@ -151,20 +190,31 @@ ames env who isFake enqueueEv stderr = (initialEvents, runAmes)
|
|||||||
drv <- mkRAcquire start stop
|
drv <- mkRAcquire start stop
|
||||||
pure (handleEffect drv mode)
|
pure (handleEffect drv mode)
|
||||||
|
|
||||||
start :: RIO e AmesDrv
|
start :: HasLogFunc e => RIO e AmesDrv
|
||||||
start = do
|
start = do
|
||||||
aTurfs <- newTVarIO Nothing
|
aTurfs <- newTVarIO Nothing
|
||||||
|
aDropped <- newTVarIO 0
|
||||||
aUdpServ <- udpServ isFake who
|
aUdpServ <- udpServ isFake who
|
||||||
aRecvTid <- queuePacketsThread aUdpServ
|
aRecvTid <- queuePacketsThread aDropped aUdpServ
|
||||||
aResolvr <- resolvServ aTurfs (usSend aUdpServ) stderr
|
aResolvr <- resolvServ aTurfs (usSend aUdpServ) stderr
|
||||||
pure (AmesDrv { .. })
|
pure (AmesDrv { .. })
|
||||||
|
|
||||||
hearFailed _ = pure ()
|
hearFailed _ = pure ()
|
||||||
|
|
||||||
queuePacketsThread :: UdpServ -> RIO e (Async ())
|
queuePacketsThread :: HasLogFunc e => TVar Word -> UdpServ -> RIO e (Async ())
|
||||||
queuePacketsThread UdpServ {..} = async $ forever $ atomically $ do
|
queuePacketsThread dropCtr UdpServ {..} = async $ forever $ do
|
||||||
(p, a, b) <- usRecv
|
outcome <- atomically $ do
|
||||||
enqueueEv (EvErr (hearEv p a b) hearFailed)
|
(p, a, b) <- usRecv
|
||||||
|
enqueueEv (EvErr (hearEv p a b) hearFailed)
|
||||||
|
case outcome of
|
||||||
|
Intake -> pure ()
|
||||||
|
Ouster -> do
|
||||||
|
d <- atomically $ do
|
||||||
|
d <- readTVar dropCtr
|
||||||
|
writeTVar dropCtr (d + 1)
|
||||||
|
pure d
|
||||||
|
when (d `rem` packetsDroppedPerComplaint == 0) $
|
||||||
|
logWarn "ames: queue full; dropping inbound packets"
|
||||||
|
|
||||||
stop :: AmesDrv -> RIO e ()
|
stop :: AmesDrv -> RIO e ()
|
||||||
stop AmesDrv {..} = io $ do
|
stop AmesDrv {..} = io $ do
|
||||||
|
@ -80,8 +80,8 @@ runGala
|
|||||||
runGala point = do
|
runGala point = do
|
||||||
env <- ask
|
env <- ask
|
||||||
que <- newTQueueIO
|
que <- newTQueueIO
|
||||||
let (_, runAmes) =
|
let enqueue = \p -> writeTQueue que p $> Intake
|
||||||
ames env (fromIntegral point) True (writeTQueue que) noStderr
|
let (_, runAmes) = ames env (fromIntegral point) True enqueue noStderr
|
||||||
cb <- runAmes
|
cb <- runAmes
|
||||||
io (cb turfEf)
|
io (cb turfEf)
|
||||||
pure (que, cb)
|
pure (que, cb)
|
||||||
|
Loading…
Reference in New Issue
Block a user