mirror of https://github.com/voidlizard/hbs2
so far so good
This commit is contained in:
parent
28731b0a4f
commit
c3891dbd11
|
@ -12,8 +12,7 @@ newtype To a = To (Peer a)
|
||||||
class IsPeer addr => Messaging bus addr msg | bus -> addr, bus -> msg where
|
class IsPeer addr => Messaging bus addr msg | bus -> addr, bus -> msg where
|
||||||
|
|
||||||
sendTo :: MonadIO m => bus -> To addr -> From addr -> msg -> m ()
|
sendTo :: MonadIO m => bus -> To addr -> From addr -> msg -> m ()
|
||||||
receive :: MonadIO m => bus -> To addr -> m [msg]
|
receive :: MonadIO m => bus -> To addr -> m [(From addr, msg)]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
-- data AnyMessaging p m = forall bus . Messaging bus (Peer p)
|
-- data AnyMessaging p m = forall bus . Messaging bus (Peer p)
|
||||||
|
|
|
@ -21,7 +21,7 @@ data FakeP2P peer msg =
|
||||||
FakeP2P
|
FakeP2P
|
||||||
{
|
{
|
||||||
blocking :: Bool
|
blocking :: Bool
|
||||||
, fakeP2p :: Cache (Peer peer) (TChan msg)
|
, fakeP2p :: Cache (Peer peer) (TChan (From peer,msg))
|
||||||
}
|
}
|
||||||
|
|
||||||
newFakeP2P :: Bool -> IO (FakeP2P peer msg)
|
newFakeP2P :: Bool -> IO (FakeP2P peer msg)
|
||||||
|
@ -30,17 +30,12 @@ newFakeP2P block = FakeP2P block <$> Cache.newCache Nothing
|
||||||
instance ( (IsPeer peer, Hashable (Peer peer) )
|
instance ( (IsPeer peer, Hashable (Peer peer) )
|
||||||
) => Messaging (FakeP2P peer msg) peer msg where
|
) => Messaging (FakeP2P peer msg) peer msg where
|
||||||
|
|
||||||
sendTo bus (To whom) _ msg = liftIO do
|
sendTo bus (To whom) who msg = liftIO do
|
||||||
chan <- Cache.fetchWithCache (fakeP2p bus) whom $ const newTChanIO
|
chan <- Cache.fetchWithCache (fakeP2p bus) whom $ const newTChanIO
|
||||||
atomically $ Chan.writeTChan chan msg
|
atomically $ Chan.writeTChan chan (who, msg)
|
||||||
|
|
||||||
-- NOTE: non-blocking version!
|
|
||||||
receive bus (To me) = liftIO do
|
receive bus (To me) = liftIO do
|
||||||
Cache.fetchWithCache (fakeP2p bus)
|
readChan =<< Cache.fetchWithCache (fakeP2p bus) me (const newTChanIO)
|
||||||
me
|
|
||||||
(const newTChanIO)
|
|
||||||
|
|
||||||
>>= readChan
|
|
||||||
|
|
||||||
where
|
where
|
||||||
readChan | blocking bus = atomically . (List.singleton <$>) . Chan.readTChan
|
readChan | blocking bus = atomically . (List.singleton <$>) . Chan.readTChan
|
||||||
|
|
|
@ -6,14 +6,17 @@ import HBS2.Net.Proto
|
||||||
import HBS2.Net.Messaging
|
import HBS2.Net.Messaging
|
||||||
import HBS2.Clock
|
import HBS2.Clock
|
||||||
|
|
||||||
import Data.Foldable
|
import Control.Concurrent.Async
|
||||||
import Data.Functor
|
|
||||||
import Data.Function
|
|
||||||
import Data.Cache (Cache)
|
import Data.Cache (Cache)
|
||||||
import Data.Cache qualified as Cache
|
import Data.Cache qualified as Cache
|
||||||
import Data.Kind
|
import Data.Foldable
|
||||||
|
import Data.Function
|
||||||
|
import Data.Functor
|
||||||
import Data.Hashable
|
import Data.Hashable
|
||||||
|
import Data.Kind
|
||||||
import Data.Proxy
|
import Data.Proxy
|
||||||
|
import Data.Word
|
||||||
|
import Prettyprinter
|
||||||
|
|
||||||
import FakeMessaging
|
import FakeMessaging
|
||||||
|
|
||||||
|
@ -50,9 +53,16 @@ data MessageWithCookie p = MessageWithCookie (Cookie p) (Encoded p)
|
||||||
--
|
--
|
||||||
|
|
||||||
data Handler p m = forall msg . IsEncoded p msg =>
|
data Handler p m = forall msg . IsEncoded p msg =>
|
||||||
Handler ( msg -> m () )
|
Handler ( (From p, Cookie p) -> msg -> m () )
|
||||||
|
|
||||||
data Fabrique p = forall bus . Messaging bus (Peer p) (MessageWithCookie p)
|
-- for convenience
|
||||||
|
handler :: forall msg m p . (IsEncoded p (msg p))
|
||||||
|
=> ((From p, Cookie p) -> msg p -> m ())
|
||||||
|
-> Handler p m
|
||||||
|
|
||||||
|
handler = Handler
|
||||||
|
|
||||||
|
data Fabrique p = forall bus . Messaging bus p (MessageWithCookie p)
|
||||||
=> Fabrique bus
|
=> Fabrique bus
|
||||||
|
|
||||||
data Dispatcher p m =
|
data Dispatcher p m =
|
||||||
|
@ -62,7 +72,7 @@ data Dispatcher p m =
|
||||||
, fabriq :: Fabrique p -- СЮДОЙ ПИХАТЬ СООБЩЕНИЯ
|
, fabriq :: Fabrique p -- СЮДОЙ ПИХАТЬ СООБЩЕНИЯ
|
||||||
}
|
}
|
||||||
|
|
||||||
newDispatcher :: (MonadIO m, (Messaging bus (Peer p) (MessageWithCookie p)))
|
newDispatcher :: (MonadIO m, (Messaging bus p (MessageWithCookie p)))
|
||||||
=> Peer p
|
=> Peer p
|
||||||
-> bus
|
-> bus
|
||||||
-> m (Dispatcher p m)
|
-> m (Dispatcher p m)
|
||||||
|
@ -81,12 +91,13 @@ sendRequest :: forall p msg m. ( MonadIO m
|
||||||
)
|
)
|
||||||
=> Dispatcher p m
|
=> Dispatcher p m
|
||||||
-> Peer p
|
-> Peer p
|
||||||
|
-> Maybe (Cookie p)
|
||||||
-> msg
|
-> msg
|
||||||
-> Handler p m
|
-> Handler p m
|
||||||
-> m ()
|
-> m ()
|
||||||
|
|
||||||
sendRequest d p msg answ = do
|
sendRequest d p mbCoo msg answ = do
|
||||||
cookie <- genCookie p
|
cookie <- maybe (genCookie p) pure mbCoo
|
||||||
timeout <- timeoutFor (Proxy @msg) <&> Just . toTimeSpec
|
timeout <- timeoutFor (Proxy @msg) <&> Just . toTimeSpec
|
||||||
liftIO $ Cache.insert' (handlers d) timeout cookie answ
|
liftIO $ Cache.insert' (handlers d) timeout cookie answ
|
||||||
sendTo (fabriq d) (To p) (From (self d)) (MessageWithCookie cookie (encode msg))
|
sendTo (fabriq d) (To p) (From (self d)) (MessageWithCookie cookie (encode msg))
|
||||||
|
@ -103,7 +114,7 @@ dispatcher d = fix \next -> do
|
||||||
-- FIXME: if receive is blocking - we'll block here forever
|
-- FIXME: if receive is blocking - we'll block here forever
|
||||||
received <- receive (fabriq d) (To (self d))
|
received <- receive (fabriq d) (To (self d))
|
||||||
|
|
||||||
for_ received $ \(MessageWithCookie coo bs) -> do
|
for_ received $ \(who, MessageWithCookie coo bs) -> do
|
||||||
|
|
||||||
-- поискали в мапе по куке
|
-- поискали в мапе по куке
|
||||||
found <- liftIO $ Cache.lookup (handlers d) coo
|
found <- liftIO $ Cache.lookup (handlers d) coo
|
||||||
|
@ -111,13 +122,55 @@ dispatcher d = fix \next -> do
|
||||||
case found of
|
case found of
|
||||||
Nothing -> pure () -- NO HANDLER FOUND FOR COOKIE CASE
|
Nothing -> pure () -- NO HANDLER FOUND FOR COOKIE CASE
|
||||||
-- декодировали сообщение и пихнули в обработчик
|
-- декодировали сообщение и пихнули в обработчик
|
||||||
Just (Handler dispatch) -> maybe (pure ()) dispatch (decode bs)
|
Just (Handler dispatch) -> maybe (pure ()) (dispatch (who,coo)) (decode bs)
|
||||||
-- ^^^^^^^^^ CAN NOT DECODE CASE
|
-- ^^^^^^^^^ CAN NOT DECODE CASE
|
||||||
|
|
||||||
next
|
next
|
||||||
|
|
||||||
|
data PingPong p = Ping
|
||||||
|
| Pong
|
||||||
|
|
||||||
|
|
||||||
|
newtype instance Cookie Fake = CookieFake Word32
|
||||||
|
deriving stock (Eq)
|
||||||
|
deriving newtype (Hashable,Num,Pretty)
|
||||||
|
|
||||||
|
|
||||||
|
instance CookieGenerator Fake IO where
|
||||||
|
genCookie _ = pure 0
|
||||||
|
|
||||||
|
instance IsEncoded Fake (PingPong p) where
|
||||||
|
data instance Encoded Fake = PingPong p
|
||||||
|
encode = undefined
|
||||||
|
decode = undefined
|
||||||
|
|
||||||
|
instance Messaging (Fabrique Fake) Fake (MessageWithCookie Fake) where
|
||||||
|
sendTo = undefined
|
||||||
|
receive = undefined
|
||||||
|
|
||||||
|
instance HasTimeout (PingPong Fake) IO where
|
||||||
|
timeoutFor _ = pure 0.1
|
||||||
|
|
||||||
|
|
||||||
testAbstractDispatch :: IO ()
|
testAbstractDispatch :: IO ()
|
||||||
testAbstractDispatch = do
|
testAbstractDispatch = do
|
||||||
pure ()
|
|
||||||
|
let peers = [1..2] :: [Peer Fake]
|
||||||
|
|
||||||
|
bus <- newFakeP2P @Fake @(MessageWithCookie Fake) True
|
||||||
|
|
||||||
|
for_ peers $ \p -> do
|
||||||
|
disp <- newDispatcher p bus
|
||||||
|
dispThread <- async (dispatcher disp)
|
||||||
|
|
||||||
|
for_ [ px | px <- peers, px /= p ] $ \pip -> do
|
||||||
|
|
||||||
|
sendRequest disp pip Nothing (Ping @Fake) $ handler $ \(From who, coo) ->
|
||||||
|
\case
|
||||||
|
Pong -> liftIO $ print $ "got pong" <+> brackets (pretty coo)
|
||||||
|
Ping -> do
|
||||||
|
liftIO $ print $ "got ping" <+> pretty who <+> brackets (pretty coo)
|
||||||
|
sendRequest disp who (Just coo) (Pong @Fake) $ handler @PingPong (\_ _ -> pure () )
|
||||||
|
|
||||||
|
cancel dispThread
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
module TestFakeMessaging where
|
module TestFakeMessaging where
|
||||||
|
|
||||||
import HBS2.Net.Proto
|
|
||||||
import HBS2.Net.Messaging
|
import HBS2.Net.Messaging
|
||||||
import HBS2.Net.Messaging.Fake
|
import HBS2.Net.Messaging.Fake
|
||||||
|
|
||||||
|
@ -8,7 +7,7 @@ import Test.Tasty.HUnit
|
||||||
|
|
||||||
import Control.Monad
|
import Control.Monad
|
||||||
import Data.Tuple
|
import Data.Tuple
|
||||||
import Data.Hashable
|
import Data.Functor
|
||||||
import System.Random
|
import System.Random
|
||||||
import Data.IORef
|
import Data.IORef
|
||||||
import Data.Word
|
import Data.Word
|
||||||
|
@ -34,7 +33,7 @@ testFakeMessaging1 = do
|
||||||
pure ( to, Set.singleton m )
|
pure ( to, Set.singleton m )
|
||||||
|
|
||||||
received <- forM peers $ \me -> do
|
received <- forM peers $ \me -> do
|
||||||
msg <- replicateM 10 $ receive bus (To me)
|
msg <- replicateM 10 $ receive bus (To me) <&> fmap snd
|
||||||
pure ( me, Set.fromList (mconcat msg) )
|
pure ( me, Set.fromList (mconcat msg) )
|
||||||
|
|
||||||
let s1 = Map.fromListWith (<>) (mconcat sent)
|
let s1 = Map.fromListWith (<>) (mconcat sent)
|
||||||
|
|
Loading…
Reference in New Issue