packages feed

glue-core-0.7.0: src/Glue/Switching.hs

{-# LANGUAGE BangPatterns        #-}
{-# LANGUAGE FlexibleContexts    #-}
{-# LANGUAGE ScopedTypeVariables #-}

-- | Module containing a switchable service, allowing the possibility of changing
-- a service "live".
module Glue.Switching
  ( switchingService
  ) where

import           Glue.Types
import           UnliftIO       (MonadIO)
import           UnliftIO.IORef (newIORef, readIORef, writeIORef)

-- | Provides a switchable service.
-- Works for both 'BasicService' and 'MultiGetService' (since 'MultiGetService' is a 'BasicService').
switchingService
  :: (MonadIO m, MonadIO n)
  => BasicService m a b
  -- ^ The service to initialise the switching service with.
  -> n (BasicService m a b, BasicService m a b -> n ())
switchingService service = do
  !serviceRef <- newIORef service
  let switching rs = do
        serviceToUse <- readIORef serviceRef
        serviceToUse rs
  let switchingUpdate newService = writeIORef serviceRef newService
  pure (switching, switchingUpdate)