runPeriodically
    :: (MonadIO m, MonadCatch m, WithLogger m, TimeUnit t)
    => t -> s -> StateT s m () -> m ()
runPeriodically delay initState action =
    let loop st = do
            st' <- execStateT action st
                `catchAny` \e -> handler e $> st
            -- toMicroseconds makes an 'Integer'
            liftIO $ threadDelay (fromIntegral (toMicroseconds delay))
            loop st'
    in  loop initState
  where
    handler = logWarning . sformat ("Periodic action failed: "%shown)
runPeriodically
    :: (MonadIO m, MonadCatch m, WithLogger m, TimeUnit t)
    => t -> s -> StateT s m () -> m ()
runPeriodically delay initState action =
    let loop st = do
            st' <- execStateT action st
                `catchAny` \e -> handler e $> st
            -- toMicroseconds makes an 'Integer'
            liftIO $ threadDelay (fromIntegral (toMicroseconds delay))
            loop st'
    in  loop initState
  where
    handler = logWarning . sformat ("Periodic action failed: "%shown)
runPeriodically delay initState action =
    let loop st = do
            st' <- execStateT action st
                `catchAny` \e -> handler e $> st
            -- toMicroseconds makes an 'Integer'
            liftIO $ threadDelay (fromIntegral (toMicroseconds delay))
            loop st'
    in  loop initState
  where
    handler = logWarning . sformat ("Periodic action failed: "%shown)