{-# LANGUAGE TemplateHaskell #-}

module Wire.FederationAPIAccess where

import Data.Kind
import Data.Qualified
import Imports
import Polysemy
import Polysemy.Error
import Wire.API.Federation.Component
import Wire.API.Federation.Error

data FederationAPIAccess (fedM :: Component -> Type -> Type) m a where
  RunFederatedEither ::
    (KnownComponent c) =>
    Remote x ->
    fedM c a ->
    FederationAPIAccess fedM m (Either FederationError a)
  RunFederatedConcurrently ::
    forall (c :: Component) f a m x fedM.
    (KnownComponent c, Foldable f) =>
    f (Remote x) ->
    (Remote x -> fedM c a) ->
    FederationAPIAccess fedM m [Either (Remote x, FederationError) (Remote a)]
  -- | An action similar to 'RunFederatedConcurrently', but the input is
  -- bucketed by domain before the RPCs are sent to the remote backends.
  RunFederatedBucketed ::
    forall (c :: Component) f a m x fedM.
    (KnownComponent c, Foldable f, Functor f) =>
    f (Remote x) ->
    (Remote [x] -> fedM c a) ->
    FederationAPIAccess fedM m [Either (Remote [x], FederationError) (Remote a)]
  IsFederationConfigured :: FederationAPIAccess fedM m Bool

makeSem ''FederationAPIAccess

runFederated ::
  forall c fedM x a r.
  ( Member (FederationAPIAccess fedM) r,
    Member (Error FederationError) r,
    KnownComponent c
  ) =>
  Remote x ->
  fedM c a ->
  Sem r a
runFederated :: forall (c :: Component) (fedM :: Component -> * -> *) x a
       (r :: EffectRow).
(Member (FederationAPIAccess fedM) r,
 Member (Error FederationError) r, KnownComponent c) =>
Remote x -> fedM c a -> Sem r a
runFederated Remote x
rx fedM c a
c = Remote x -> fedM c a -> Sem r (Either FederationError a)
forall (fedM :: Component -> * -> *) (r :: EffectRow)
       (c :: Component) x a.
(Member (FederationAPIAccess fedM) r, KnownComponent c) =>
Remote x -> fedM c a -> Sem r (Either FederationError a)
runFederatedEither Remote x
rx fedM c a
c Sem r (Either FederationError a)
-> (Either FederationError a -> Sem r a) -> Sem r a
forall a b. Sem r a -> (a -> Sem r b) -> Sem r b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Either FederationError a -> Sem r a
forall e (r :: EffectRow) a.
Member (Error e) r =>
Either e a -> Sem r a
fromEither