packages feed

freckle-app 1.18.0.0 → 1.18.1.0

raw patch · 60 files changed

+303/−247 lines, 60 filesdep +asyncPVP ok

version bump matches the API change (PVP)

Dependencies added: async

API changes (from Hackage documentation)

+ Freckle.App.Async: ThreadContext :: KeyMap Value -> Maybe Context -> ThreadContext
+ Freckle.App.Async: [blammoContext] :: ThreadContext -> KeyMap Value
+ Freckle.App.Async: [openTelemetryContext] :: ThreadContext -> Maybe Context
+ Freckle.App.Async: data ThreadContext
+ Freckle.App.Async: foldConcurrently :: (MonadUnliftIO m, MonadMask m, Monoid a, Foldable t) => t (m a) -> m a
+ Freckle.App.Async: getThreadContext :: MonadIO m => m ThreadContext
+ Freckle.App.Async: withThreadContext :: (MonadIO m, MonadMask m) => ThreadContext -> m a -> m a
+ Freckle.App.Http: CONNECT :: StdMethod
+ Freckle.App.Http: DELETE :: StdMethod
+ Freckle.App.Http: GET :: StdMethod
+ Freckle.App.Http: HEAD :: StdMethod
+ Freckle.App.Http: OPTIONS :: StdMethod
+ Freckle.App.Http: PATCH :: StdMethod
+ Freckle.App.Http: POST :: StdMethod
+ Freckle.App.Http: PUT :: StdMethod
+ Freckle.App.Http: TRACE :: StdMethod
+ Freckle.App.Http: data () => StdMethod
+ Freckle.App.Http: setRequestMethod :: StdMethod -> Request -> Request

Files

CHANGELOG.md view
@@ -1,4 +1,12 @@-## [_Unreleased_](https://github.com/freckle/freckle-app/compare/v1.17.0.0...main)+## [_Unreleased_](https://github.com/freckle/freckle-app/compare/v1.18.1.0...main)++## [v1.18.1.0](https://github.com/freckle/freckle-app/compare/v1.18.0.0...v1.18.1.0)++- Add `Freckle.App.Http (setRequestMethod)`+- Add `Freckle.App.Async` (`foldConcurrently`, `ThreadContext (..)`,+  `getThreadContext`, `withThreadContext`)+- Bugfix: Utilities in `Freckle.App.Async` now preserve OpenTelemetry context+  (previously were only passing along Blammo logging context)  ## [v1.18.0.0](https://github.com/freckle/freckle-app/compare/v1.17.1.0...v1.18.0.0) 
freckle-app.cabal view
@@ -1,6 +1,6 @@ cabal-version:      1.18 name:               freckle-app-version:            1.18.0.0+version:            1.18.1.0 license:            MIT license-file:       LICENSE maintainer:         Freckle Education@@ -83,22 +83,19 @@      hs-source-dirs:     library     other-modules:      Paths_freckle_app-    default-language:   Haskell2010+    default-language:   GHC2021     default-extensions:-        BangPatterns DataKinds DeriveAnyClass DeriveFoldable DeriveFunctor-        DeriveGeneric DeriveLift DeriveTraversable DerivingVia-        DerivingStrategies FlexibleContexts FlexibleInstances GADTs-        GeneralizedNewtypeDeriving LambdaCase MultiParamTypeClasses-        NoImplicitPrelude NoMonomorphismRestriction OverloadedStrings-        RankNTypes RecordWildCards ScopedTypeVariables StandaloneDeriving-        TypeApplications TypeFamilies+        DataKinds DeriveAnyClass DerivingVia DerivingStrategies GADTs+        LambdaCase NoImplicitPrelude NoMonomorphismRestriction+        OverloadedStrings RecordWildCards TypeFamilies      ghc-options:         -fignore-optim-changes -fwrite-ide-info -Weverything         -Wno-all-missed-specialisations -Wno-missing-exported-signatures-        -Wno-missing-import-lists -Wno-missing-local-signatures-        -Wno-missing-safe-haskell-mode -Wno-monomorphism-restriction-        -Wno-prepositive-qualified-module -Wno-safe -Wno-unsafe+        -Wno-missing-import-lists -Wno-missing-kind-signatures+        -Wno-missing-local-signatures -Wno-missing-safe-haskell-mode+        -Wno-monomorphism-restriction -Wno-prepositive-qualified-module+        -Wno-safe -Wno-unsafe      build-depends:         Blammo >=1.2.0.0,@@ -184,48 +181,42 @@         yesod-test >=1.6.15      if impl(ghc >=9.8)-        ghc-options: -Wno-missing-role-annotations--    if impl(ghc >=9.2)-        ghc-options: -Wno-missing-kind-signatures+        ghc-options:+            -Wno-missing-role-annotations -Wno-missing-poly-kind-signatures  test-suite doctest     type:               exitcode-stdio-1.0     main-is:            Main.hs     hs-source-dirs:     doctest     other-modules:      Paths_freckle_app-    default-language:   Haskell2010+    default-language:   GHC2021     default-extensions:-        BangPatterns DataKinds DeriveAnyClass DeriveFoldable DeriveFunctor-        DeriveGeneric DeriveLift DeriveTraversable DerivingVia-        DerivingStrategies FlexibleContexts FlexibleInstances GADTs-        GeneralizedNewtypeDeriving LambdaCase MultiParamTypeClasses-        NoImplicitPrelude NoMonomorphismRestriction OverloadedStrings-        RankNTypes RecordWildCards ScopedTypeVariables StandaloneDeriving-        TypeApplications TypeFamilies+        DataKinds DeriveAnyClass DerivingVia DerivingStrategies GADTs+        LambdaCase NoImplicitPrelude NoMonomorphismRestriction+        OverloadedStrings RecordWildCards TypeFamilies      ghc-options:         -fignore-optim-changes -fwrite-ide-info -Weverything         -Wno-all-missed-specialisations -Wno-missing-exported-signatures-        -Wno-missing-import-lists -Wno-missing-local-signatures-        -Wno-missing-safe-haskell-mode -Wno-monomorphism-restriction-        -Wno-prepositive-qualified-module -Wno-safe -Wno-unsafe+        -Wno-missing-import-lists -Wno-missing-kind-signatures+        -Wno-missing-local-signatures -Wno-missing-safe-haskell-mode+        -Wno-monomorphism-restriction -Wno-prepositive-qualified-module+        -Wno-safe -Wno-unsafe      build-depends:         base >=4.16.4.0 && <5,         freckle-app      if impl(ghc >=9.8)-        ghc-options: -Wno-missing-role-annotations--    if impl(ghc >=9.2)-        ghc-options: -Wno-missing-kind-signatures+        ghc-options:+            -Wno-missing-role-annotations -Wno-missing-poly-kind-signatures  test-suite spec     type:               exitcode-stdio-1.0     main-is:            Main.hs     hs-source-dirs:     tests     other-modules:+        Freckle.App.AsyncSpec         Freckle.App.Bugsnag.MetaDataSpec         Freckle.App.BugsnagSpec         Freckle.App.CsvSpec@@ -241,28 +232,25 @@         Spec         Paths_freckle_app -    default-language:   Haskell2010+    default-language:   GHC2021     default-extensions:-        BangPatterns DataKinds DeriveAnyClass DeriveFoldable DeriveFunctor-        DeriveGeneric DeriveLift DeriveTraversable DerivingVia-        DerivingStrategies FlexibleContexts FlexibleInstances GADTs-        GeneralizedNewtypeDeriving LambdaCase MultiParamTypeClasses-        NoImplicitPrelude NoMonomorphismRestriction OverloadedStrings-        RankNTypes RecordWildCards ScopedTypeVariables StandaloneDeriving-        TypeApplications TypeFamilies+        DataKinds DeriveAnyClass DerivingVia DerivingStrategies GADTs+        LambdaCase NoImplicitPrelude NoMonomorphismRestriction+        OverloadedStrings RecordWildCards TypeFamilies      ghc-options:         -fignore-optim-changes -fwrite-ide-info -Weverything         -Wno-all-missed-specialisations -Wno-missing-exported-signatures-        -Wno-missing-import-lists -Wno-missing-local-signatures-        -Wno-missing-safe-haskell-mode -Wno-monomorphism-restriction-        -Wno-prepositive-qualified-module -Wno-safe -Wno-unsafe -threaded-        -rtsopts -with-rtsopts=-N+        -Wno-missing-import-lists -Wno-missing-kind-signatures+        -Wno-missing-local-signatures -Wno-missing-safe-haskell-mode+        -Wno-monomorphism-restriction -Wno-prepositive-qualified-module+        -Wno-safe -Wno-unsafe -threaded -rtsopts -with-rtsopts=-N      build-depends:         Blammo >=1.2.0.0,         QuickCheck >=2.14.3,         aeson >=2.0.3.0,+        async >=2.2.4,         base >=4.16.4.0 && <5,         bugsnag >=1.1.0.0,         bytestring >=0.11.4.0,@@ -291,7 +279,5 @@         zlib >=0.6.3.0      if impl(ghc >=9.8)-        ghc-options: -Wno-missing-role-annotations--    if impl(ghc >=9.2)-        ghc-options: -Wno-missing-kind-signatures+        ghc-options:+            -Wno-missing-role-annotations -Wno-missing-poly-kind-signatures
library/Freckle/App/Async.hs view
@@ -1,26 +1,43 @@ module Freckle.App.Async   ( async+  , foldConcurrently   , immortalCreate   , immortalCreateLogged-  )-where+  , ThreadContext (..)+  , getThreadContext+  , withThreadContext+  ) where  import Freckle.App.Prelude -import Blammo.Logging-import qualified Control.Immortal as Immortal+import Blammo.Logging (Message (..), MonadLogger, MonadMask, logError, (.=))+import Blammo.Logging qualified as Blammo+import Control.Immortal qualified as Immortal import Control.Monad (forever)-import qualified Data.Aeson.Compat as KeyMap-import UnliftIO.Async (Async)-import qualified UnliftIO.Async as UnliftIO+import Data.Aeson (Value)+import Data.Aeson.Compat (KeyMap)+import Data.Aeson.Compat qualified as KeyMap+import OpenTelemetry.Context qualified as OpenTelemetry+import OpenTelemetry.Context.ThreadLocal qualified as OpenTelemetry+import UnliftIO.Async (Async, conc, runConc)+import UnliftIO.Async qualified as UnliftIO import UnliftIO.Concurrent (threadDelay)  -- | 'UnliftIO.Async.async' but passing the thread context along async :: (MonadMask m, MonadUnliftIO m) => m a -> m (Async a) async f = do-  tc <- liftIO $ KeyMap.toList <$> myThreadContext-  UnliftIO.async $ withThreadContext tc f+  context <- getThreadContext+  UnliftIO.async $ withThreadContext context f +-- | Run a list of actions concurrently+--+-- The forked threads will have the current thread context copied to them.+foldConcurrently+  :: (MonadUnliftIO m, MonadMask m, Monoid a, Foldable t) => t (m a) -> m a+foldConcurrently xs = do+  context <- getThreadContext+  runConc $ foldMap (conc . withThreadContext context) xs+ -- | Wrapper around creating "Control.Immortal" processes -- -- Features:@@ -36,11 +53,11 @@   -- ^ The action to run persistently   -> m a immortalCreate onUnexpected act = do-  tc <- liftIO $ KeyMap.toList <$> myThreadContext+  context <- getThreadContext    let-    act' = withThreadContext tc act-    onUnexpected' = withThreadContext tc . onUnexpected+    act' = withThreadContext context act+    onUnexpected' = withThreadContext context . onUnexpected    void $ Immortal.create $ \thread -> do     Immortal.onUnexpectedFinish thread onUnexpected' act'@@ -53,3 +70,20 @@ immortalCreateLogged = immortalCreate $ either logEx pure  where   logEx ex = logError $ "Unexpected Finish" :# ["exception" .= displayException ex]++data ThreadContext = ThreadContext+  { blammoContext :: KeyMap Value+  , openTelemetryContext :: Maybe OpenTelemetry.Context+  }++getThreadContext :: MonadIO m => m ThreadContext+getThreadContext =+  ThreadContext+    <$> liftIO Blammo.myThreadContext+    <*> OpenTelemetry.lookupContext++withThreadContext :: (MonadIO m, MonadMask m) => ThreadContext -> m a -> m a+withThreadContext ThreadContext {blammoContext, openTelemetryContext} continue =+  Blammo.withThreadContext (KeyMap.toList blammoContext) $ do+    traverse_ @Maybe OpenTelemetry.attachContext openTelemetryContext+    continue
library/Freckle/App/Bugsnag.hs view
@@ -19,7 +19,7 @@  import Freckle.App.Prelude -import qualified Control.Exception as Base (Exception)+import Control.Exception qualified as Base (Exception) import Control.Lens (Lens', view) import Control.Monad.Catch (MonadMask) import Control.Monad.Reader (runReaderT)@@ -29,9 +29,9 @@ import Freckle.App.Async (async) import Freckle.App.Bugsnag.HttpException (httpExceptionBeforeNotify) import Freckle.App.Bugsnag.SqlError (sqlErrorBeforeNotify)-import qualified Freckle.App.Env as Env+import Freckle.App.Env qualified as Env import Network.Bugsnag hiding (notifyBugsnag, notifyBugsnagWith)-import qualified Network.Bugsnag as Bugsnag+import Network.Bugsnag qualified as Bugsnag import Yesod.Core.Lens (envL, siteL) import Yesod.Core.Types (HandlerData) 
library/Freckle/App/Bugsnag/HttpException.hs view
@@ -8,9 +8,9 @@ import Freckle.App.Prelude  import Data.Bugsnag (Exception (..))-import qualified Data.ByteString.Char8 as BS8+import Data.ByteString.Char8 qualified as BS8 import Freckle.App.Exception.Types (AnnotatedException)-import qualified Freckle.App.Exception.Types as Annotated+import Freckle.App.Exception.Types qualified as Annotated import Network.Bugsnag   ( BeforeNotify   , setGroupingHash
library/Freckle/App/Bugsnag/MetaData.hs view
@@ -18,7 +18,7 @@ import Blammo.Logging (myThreadContext) import Control.Lens (Lens', lens, to, view, (<>~)) import Data.Aeson (Value (..))-import qualified Data.Aeson.KeyMap as KeyMap+import Data.Aeson.KeyMap qualified as KeyMap import Data.Bugsnag (Event (..)) import Data.String (fromString) import Freckle.App.Stats (HasStatsClient (..), tagsL)
library/Freckle/App/Bugsnag/SqlError.hs view
@@ -17,7 +17,7 @@   , constraintViolation   ) import Freckle.App.Exception.Types (AnnotatedException)-import qualified Freckle.App.Exception.Types as Annotated+import Freckle.App.Exception.Types qualified as Annotated import Network.Bugsnag   ( BeforeNotify   , setGroupingHash
library/Freckle/App/Csv.hs view
@@ -40,9 +40,9 @@   ) import Data.Aeson (KeyValue (..), ToJSON (..), object, pairs, (.=)) import Data.ByteString (ByteString)-import qualified Data.ByteString.Char8 as BS8-import qualified Data.Conduit.Combinators as Conduit-import qualified Data.Conduit.Text as Conduit+import Data.ByteString.Char8 qualified as BS8+import Data.Conduit.Combinators qualified as Conduit+import Data.Conduit.Text qualified as Conduit import Data.Csv   ( DefaultOrdered   , FromNamedRecord (..)@@ -54,17 +54,17 @@   , defaultOptions   , headerOrder   )-import qualified Data.Csv.Incremental as CsvI+import Data.Csv.Incremental qualified as CsvI import Data.Functor.Bind (Bind)-import qualified Data.HashMap.Strict as HashMap-import qualified Data.List.NonEmpty as NE+import Data.HashMap.Strict qualified as HashMap+import Data.List.NonEmpty qualified as NE import Data.Proxy (Proxy (Proxy)) import Data.Sequence (Seq)-import qualified Data.Sequence as Seq+import Data.Sequence qualified as Seq import Data.Sequence.NonEmpty (NESeq)-import qualified Data.Text as T-import qualified Data.Text.Encoding as T-import qualified Data.Vector as V+import Data.Text qualified as T+import Data.Text.Encoding qualified as T+import Data.Vector qualified as V  -- | Treat CSV header line as 1 --
library/Freckle/App/Database.hs view
@@ -39,14 +39,14 @@ import Freckle.App.Prelude  import Blammo.Logging-import qualified Control.Immortal as Immortal+import Control.Immortal qualified as Immortal import Control.Monad.Reader import Data.ByteString (ByteString)-import qualified Data.ByteString.Char8 as BS8-import qualified Data.ByteString.Lazy as BSL-import qualified Data.HashMap.Strict as HashMap+import Data.ByteString.Char8 qualified as BS8+import Data.ByteString.Lazy qualified as BSL+import Data.HashMap.Strict qualified as HashMap import Data.Pool-import qualified Data.Text as T+import Data.Text qualified as T import Database.Persist.Postgresql   ( SqlBackend   , SqlPersistT@@ -66,13 +66,13 @@   ) import Database.PostgreSQL.Simple.SqlQQ (sql) import Freckle.App.Env (Timeout (..))-import qualified Freckle.App.Env as Env+import Freckle.App.Env qualified as Env import Freckle.App.Exception.MonadUnliftIO import Freckle.App.OpenTelemetry import Freckle.App.Stats (HasStatsClient)-import qualified Freckle.App.Stats as Stats+import Freckle.App.Stats qualified as Stats import OpenTelemetry.Instrumentation.Persistent-import qualified OpenTelemetry.Trace as Trace+import OpenTelemetry.Trace qualified as Trace import System.Process.Typed (proc, readProcessStdout_) import UnliftIO.Concurrent (threadDelay) import UnliftIO.IORef
library/Freckle/App/Dotenv.hs view
@@ -7,7 +7,7 @@  import Freckle.App.Prelude -import qualified Configuration.Dotenv as Dotenv+import Configuration.Dotenv qualified as Dotenv import System.FilePath (takeDirectory, (</>)) import UnliftIO.Directory (doesFileExist, getCurrentDirectory) 
library/Freckle/App/Env.hs view
@@ -39,11 +39,11 @@  import Control.Error.Util (note) import Data.Char (isDigit)-import qualified Data.Text as T+import Data.Text qualified as T import Data.Time (defaultTimeLocale, parseTimeM) import Env hiding (flag)-import qualified Env-import qualified Prelude as Unsafe (read)+import Env qualified+import Prelude qualified as Unsafe (read)  -- | Designates the value of a parameter when a flag is not provided. newtype Off a = Off a
library/Freckle/App/Exception.hs view
@@ -12,7 +12,7 @@ import Prelude  import Control.Exception.Annotated (annotatedExceptionCallStack)-import qualified Control.Exception.Annotated as AnnotatedException+import Control.Exception.Annotated qualified as AnnotatedException import Control.Monad.Logger.Aeson (Message (..), (.=)) import Data.Aeson (object) import Freckle.App.Exception.MonadUnliftIO
library/Freckle/App/Exception/MonadThrow.hs view
@@ -34,8 +34,8 @@ import GHC.IO.Exception (userError) import GHC.Stack (withFrozenCallStack) -import qualified Control.Exception.Annotated as Annotated-import qualified Control.Monad.Catch+import Control.Exception.Annotated qualified as Annotated+import Control.Monad.Catch qualified  -- Throws an exception, wrapped in 'AnnotatedException' which includes a call stack throwM :: forall e m a. (Exception e, MonadThrow m, HasCallStack) => e -> m a
library/Freckle/App/Exception/MonadUnliftIO.hs view
@@ -35,8 +35,8 @@ import System.IO (IO) import UnliftIO (MonadIO, MonadUnliftIO) -import qualified Control.Exception.Annotated.UnliftIO as Annotated-import qualified UnliftIO.Exception+import Control.Exception.Annotated.UnliftIO qualified as Annotated+import UnliftIO.Exception qualified  -- Throws an exception, wrapped in 'AnnotatedException' which includes a call stack throwM :: forall e m a. (Exception e, MonadIO m, HasCallStack) => e -> m a
library/Freckle/App/Faktory/ProducerPool.hs view
@@ -17,9 +17,9 @@   , newPool   , setNumStripes   )-import qualified Faktory.Producer as Faktory-import qualified Faktory.Settings as Faktory-import qualified Freckle.App.Env as Env+import Faktory.Producer qualified as Faktory+import Faktory.Settings qualified as Faktory+import Freckle.App.Env qualified as Env import Yesod.Core.Lens (envL, siteL) import Yesod.Core.Types (HandlerData) 
library/Freckle/App/Ghci.hs view
@@ -9,7 +9,7 @@ import Database.Persist.Postgresql (runSqlPool) import Database.Persist.Sql (SqlBackend) import Freckle.App.Database (makePostgresPool)-import qualified Freckle.App.Dotenv as Dotenv+import Freckle.App.Dotenv qualified as Dotenv  -- | Run a db action against .env runDB :: ReaderT SqlBackend IO b -> IO b
library/Freckle/App/Http.hs view
@@ -32,6 +32,7 @@   , setRequestBodyJSON   , setRequestBodyURLEncoded   , setRequestCheckStatus+  , setRequestMethod   , setRequestPath   , disableRequestDecompress @@ -71,6 +72,7 @@   , statusIsRedirection   , statusIsClientError   , statusIsServerError+  , StdMethod (..)   ) where  import Freckle.App.Prelude@@ -82,17 +84,18 @@ import Control.Monad.Validate (ValidateT) import Control.Monad.Writer (WriterT) import Data.Aeson (FromJSON)-import qualified Data.Aeson as Aeson-import qualified Data.ByteString as BS+import Data.Aeson qualified as Aeson+import Data.ByteString qualified as BS import Data.ByteString.Lazy (ByteString)-import qualified Data.ByteString.Lazy.Char8 as BSL8-import qualified Data.List.NonEmpty as NE+import Data.ByteString.Lazy.Char8 qualified as BSL8+import Data.List.NonEmpty qualified as NE import Freckle.App.Http.Paginate import Freckle.App.Http.Retry-import qualified Network.HTTP.Client as HTTP (Request (..))+import Network.HTTP.Client qualified as HTTP (Request (..)) import Network.HTTP.Conduit (HttpExceptionContent (..))-import Network.HTTP.Simple hiding (httpLbs, httpNoBody)-import qualified Network.HTTP.Simple as HTTP+import Network.HTTP.Simple hiding (httpLbs, httpNoBody, setRequestMethod)+import Network.HTTP.Simple qualified as HTTP+import Network.HTTP.Types (StdMethod (..), renderStdMethod) import Network.HTTP.Types.Header (hAccept, hAuthorization) import Network.HTTP.Types.Status   ( Status@@ -250,6 +253,9 @@  addBearerAuthorizationHeader :: BS.ByteString -> Request -> Request addBearerAuthorizationHeader = addRequestHeader hAuthorization . ("Bearer " <>)++setRequestMethod :: StdMethod -> Request -> Request+setRequestMethod method req = req {HTTP.method = renderStdMethod method}  disableRequestDecompress :: Request -> Request disableRequestDecompress req =
library/Freckle/App/Http/Cache.hs view
@@ -16,9 +16,9 @@  import Blammo.Logging (Message (..), (.=)) import Data.ByteString (ByteString)-import qualified Data.ByteString.Char8 as BS8-import qualified Data.ByteString.Lazy as BSL-import qualified Data.CaseInsensitive as CI+import Data.ByteString.Char8 qualified as BS8+import Data.ByteString.Lazy qualified as BSL+import Data.CaseInsensitive qualified as CI import Data.List.Extra (firstJust) import Data.Text.Encoding (decodeUtf8With) import Data.Text.Encoding.Error (lenientDecode)@@ -28,7 +28,7 @@ import Freckle.App.Http.Header import Freckle.App.Memcached import Network.HTTP.Client (Request, Response)-import qualified Network.HTTP.Client as HTTP+import Network.HTTP.Client qualified as HTTP import Network.HTTP.Simple   ( addRequestHeader   , getRequestHeader
library/Freckle/App/Http/Cache/Gzip.hs view
@@ -23,11 +23,11 @@  import Codec.Serialise (Serialise) import Data.ByteString.Lazy (ByteString)-import qualified Data.ByteString.Lazy as BSL+import Data.ByteString.Lazy qualified as BSL import Freckle.App.Http (disableRequestDecompress) import Freckle.App.Http.Header import Network.HTTP.Client (Request, Response)-import qualified Network.HTTP.Client.Internal as HTTP+import Network.HTTP.Client.Internal qualified as HTTP  newtype PotentiallyGzipped a = PotentiallyGzipped   { unwrap :: a
library/Freckle/App/Http/Cache/Memcached.hs view
@@ -13,16 +13,16 @@  import Blammo.Logging (MonadLogger, logDebugNS, logWarnNS) import Codec.Serialise (Serialise (..), deserialiseOrFail, serialise)-import qualified Data.ByteString.Lazy as BSL+import Data.ByteString.Lazy qualified as BSL import Data.CaseInsensitive (CI)-import qualified Data.CaseInsensitive as CI+import Data.CaseInsensitive qualified as CI import Database.Memcache.Types (Value) import Freckle.App.Http.Cache import Freckle.App.Memcached-import qualified Freckle.App.Memcached.Client as Memcached+import Freckle.App.Memcached.Client qualified as Memcached import Freckle.App.OpenTelemetry (MonadTracer) import Network.HTTP.Client (Request)-import qualified Network.HTTP.Client.Internal as HTTP+import Network.HTTP.Client.Internal qualified as HTTP import Network.HTTP.Types.Header (ResponseHeaders) import Network.HTTP.Types.Status (Status (..)) import Network.HTTP.Types.Version (HttpVersion (..))
library/Freckle/App/Http/Cache/State.hs view
@@ -22,7 +22,7 @@ import Control.Monad.State import Data.Text.Encoding (decodeUtf8With) import Data.Text.Encoding.Error (lenientDecode)-import qualified Data.Text.IO as T+import Data.Text.IO qualified as T import Freckle.App.Http.Cache import Freckle.App.Memcached.CacheKey import Freckle.App.Memcached.CacheTTL
library/Freckle/App/Http/Header.hs view
@@ -10,7 +10,7 @@ import Freckle.App.Prelude  import Data.ByteString (ByteString)-import qualified Data.ByteString.Char8 as BS8+import Data.ByteString.Char8 qualified as BS8 import Data.Char (isSpace) import Network.HTTP.Client (Request, Response, requestHeaders, responseHeaders) import Network.HTTP.Simple (getRequestHeader, getResponseHeader)
library/Freckle/App/Http/Retry.hs view
@@ -7,7 +7,7 @@ import Freckle.App.Prelude  import Control.Retry-import qualified Data.ByteString.Char8 as BS8+import Data.ByteString.Char8 qualified as BS8 import Network.HTTP.Client (Request (..)) import Network.HTTP.Simple import Network.HTTP.Types.Status (status429)
library/Freckle/App/Json/Empty.hs view
@@ -5,7 +5,12 @@  import Freckle.App.Prelude -import Autodocodec (Autodocodec (..), HasCodec (..), HasObjectCodec (..), object)+import Autodocodec+  ( Autodocodec (..)+  , HasCodec (..)+  , HasObjectCodec (..)+  , object+  ) import Autodocodec.OpenAPI () import Data.Aeson (FromJSON, ToJSON) import Data.OpenApi (ToSchema (..))
library/Freckle/App/Kafka/Consumer.hs view
@@ -15,10 +15,10 @@ import Control.Monad (forever) import Data.Aeson import Data.ByteString (ByteString)-import qualified Data.List.NonEmpty as NE-import qualified Data.Map.Strict as Map-import qualified Data.Text as T-import qualified Env+import Data.List.NonEmpty qualified as NE+import Data.Map.Strict qualified as Map+import Data.Text qualified as T+import Env qualified import Freckle.App.Async import Freckle.App.Env import Freckle.App.Exception (annotatedExceptionMessageFrom)@@ -32,7 +32,7 @@   , runConsumer   , subscription   )-import qualified Kafka.Consumer as Kafka+import Kafka.Consumer qualified as Kafka import UnliftIO.Exception (bracket)  data KafkaConsumerConfig = KafkaConsumerConfig
library/Freckle/App/Kafka/Producer.hs view
@@ -18,16 +18,16 @@ import Control.Lens (Lens', view) import Data.Aeson (ToJSON, encode) import Data.ByteString.Lazy (toStrict)-import qualified Data.HashMap.Strict as HashMap-import qualified Data.List.NonEmpty as NE+import Data.HashMap.Strict qualified as HashMap+import Data.List.NonEmpty qualified as NE import Data.Pool (Pool)-import qualified Data.Pool as Pool-import qualified Data.Text as T+import Data.Pool qualified as Pool+import Data.Text qualified as T import Freckle.App.Async (async)-import qualified Freckle.App.Env as Env+import Freckle.App.Env qualified as Env import Freckle.App.OpenTelemetry import Kafka.Producer-import qualified OpenTelemetry.Trace as Trace+import OpenTelemetry.Trace qualified as Trace import UnliftIO (withRunInIO) import Yesod.Core.Lens import Yesod.Core.Types (HandlerData)@@ -92,13 +92,13 @@   -> KafkaProducerPoolConfig   -> IO (Pool KafkaProducer) createKafkaProducerPool addresses KafkaProducerPoolConfig {..} =-  Pool.newPool-    $ Pool.setNumStripes (Just kafkaProducerPoolConfigStripes)-    $ Pool.defaultPoolConfig-      mkProducer-      closeProducer-      (realToFrac kafkaProducerPoolConfigIdleTimeout)-      kafkaProducerPoolConfigSize+  Pool.newPool $+    Pool.setNumStripes (Just kafkaProducerPoolConfigStripes) $+      Pool.defaultPoolConfig+        mkProducer+        closeProducer+        (realToFrac kafkaProducerPoolConfigIdleTimeout)+        kafkaProducerPoolConfigSize  where   mkProducer =     either
library/Freckle/App/Memcached.hs view
@@ -28,14 +28,14 @@ import Codec.Serialise (Serialise, deserialiseOrFail, serialise) import Data.Aeson import Data.ByteString (ByteString)-import qualified Data.ByteString.Lazy as BSL+import Data.ByteString.Lazy qualified as BSL import Data.Text.Encoding (decodeUtf8With) import Data.Text.Encoding.Error (lenientDecode) import Freckle.App.Exception (annotatedExceptionMessage) import Freckle.App.Memcached.CacheKey import Freckle.App.Memcached.CacheTTL import Freckle.App.Memcached.Client (HasMemcachedClient (..))-import qualified Freckle.App.Memcached.Client as Memcached+import Freckle.App.Memcached.Client qualified as Memcached import Freckle.App.Memcached.MD5 import Freckle.App.OpenTelemetry 
library/Freckle/App/Memcached/CacheKey.hs view
@@ -8,7 +8,7 @@ import Freckle.App.Prelude  import Data.Char (isControl, isSpace)-import qualified Data.Text as T+import Data.Text qualified as T import Database.Memcache.Types (Key) import OpenTelemetry.Trace (ToAttribute (..)) 
library/Freckle/App/Memcached/Client.hs view
@@ -12,14 +12,14 @@ import Freckle.App.Prelude  import Control.Lens (Lens', view, _1)-import qualified Data.HashMap.Strict as HashMap-import qualified Database.Memcache.Client as Memcache+import Data.HashMap.Strict qualified as HashMap+import Database.Memcache.Client qualified as Memcache import Database.Memcache.Types (Value, Version) import Freckle.App.Memcached.CacheKey import Freckle.App.Memcached.CacheTTL import Freckle.App.Memcached.Servers import Freckle.App.OpenTelemetry-import qualified OpenTelemetry.Trace as Trace+import OpenTelemetry.Trace qualified as Trace import UnliftIO.Exception (finally) import Yesod.Core.Lens import Yesod.Core.Types (HandlerData)
library/Freckle/App/Memcached/MD5.hs view
@@ -6,8 +6,8 @@  import Freckle.App.Prelude -import qualified Data.ByteString.Lazy as BSL-import qualified Data.Digest.Pure.MD5 as Digest+import Data.ByteString.Lazy qualified as BSL+import Data.Digest.Pure.MD5 qualified as Digest import Freckle.App.Memcached.CacheKey  md5CacheKey :: Show a => a -> CacheKey
library/Freckle/App/Memcached/Servers.hs view
@@ -29,8 +29,8 @@ import Freckle.App.Prelude  import Control.Error.Util (note)-import qualified Data.Text as T-import qualified Database.Memcache.Client as Memcache+import Data.Text qualified as T+import Database.Memcache.Client qualified as Memcache import Network.URI (URI (..), URIAuth (..), parseAbsoluteURI)  newtype MemcachedServers = MemcachedServers
library/Freckle/App/OpenTelemetry.hs view
@@ -67,14 +67,14 @@ import Freckle.App.Prelude  import Data.ByteString (ByteString)-import qualified Data.Text as T+import Data.Text qualified as T import Data.Text.Encoding (decodeUtf8With) import Data.Text.Encoding.Error (lenientDecode) import OpenTelemetry.Context (lookupSpan) import OpenTelemetry.Context.ThreadLocal (getContext) import OpenTelemetry.Trace hiding (inSpan) import OpenTelemetry.Trace.Core (getSpanContext)-import qualified OpenTelemetry.Trace.Core as Trace (SpanContext (..))+import OpenTelemetry.Trace.Core qualified as Trace (SpanContext (..)) import OpenTelemetry.Trace.Id   ( Base (..)   , SpanId
library/Freckle/App/OpenTelemetry/Context.hs view
@@ -14,7 +14,7 @@ import Data.Aeson (FromJSON, ToJSON) import Data.ByteString (ByteString) import Data.CaseInsensitive (CI)-import qualified Data.CaseInsensitive as CI+import Data.CaseInsensitive qualified as CI import Faktory.Job (Job, custom, jobOptions) import Faktory.Job.Custom (fromCustom, toCustom) import Faktory.JobOptions (JobOptions (..))
library/Freckle/App/OpenTelemetry/Http.hs view
@@ -7,9 +7,9 @@  import Freckle.App.Prelude -import qualified Data.CaseInsensitive as CI-import qualified Data.HashMap.Strict as HashMap-import qualified Data.Text as T+import Data.CaseInsensitive qualified as CI+import Data.HashMap.Strict qualified as HashMap+import Data.Text qualified as T import Data.Text.Encoding (decodeUtf8With) import Data.Text.Encoding.Error (lenientDecode) import Freckle.App.OpenTelemetry@@ -18,7 +18,7 @@   , clientSpanArguments   ) import Network.HTTP.Client (Request, Response)-import qualified Network.HTTP.Client as HTTP+import Network.HTTP.Client qualified as HTTP import Network.HTTP.Types.Status (statusCode) import OpenTelemetry.Attributes (Attribute, ToAttribute (..)) 
library/Freckle/App/OpenTelemetry/ThreadContext.hs view
@@ -8,7 +8,7 @@  import Blammo.Logging (MonadMask, withThreadContext) import Data.Aeson ((.=))-import qualified Data.Aeson.Key as Key+import Data.Aeson.Key qualified as Key import Data.Aeson.Types (Pair) import Freckle.App.OpenTelemetry (getCurrentSpanContext) import OpenTelemetry.Trace.Core (SpanContext (..))
library/Freckle/App/Prelude.hs view
@@ -88,7 +88,7 @@     -- ** 'UTCTime'   , getCurrentTime -   -- * Exceptions+    -- * Exceptions   , throwM   , throwString   , fromJustNoteM@@ -112,14 +112,14 @@   , head   , init   , last+#if MIN_VERSION_base(4,18,0)+  , liftA2+#endif   , maximum   , minimum   , read   , tail   , (!!)-#if MIN_VERSION_base(4,18,0)-  , liftA2-#endif   )  -- Commonly used types (and their commonly used functions)@@ -135,10 +135,10 @@ import Data.List.NonEmpty (NonEmpty) import Data.Map.Strict (Map) import Data.Set (Set)-import Freckle.App.Exception import Data.Text (Text, pack, unpack) import Data.Time (NominalDiffTime, UTCTime, getCurrentTime) import Data.Vector (Vector)+import Freckle.App.Exception import GHC.Generics (Generic)  -- Safe alternatives to prelude functions
library/Freckle/App/Random.hs view
@@ -16,7 +16,7 @@ import Data.STRef (newSTRef, readSTRef, writeSTRef) import Numeric.Natural (Natural) -import qualified Data.Set as Set+import Data.Set qualified as Set  -- | A possibly-empty contiguous range of integers data Range i
library/Freckle/App/Scientist.hs view
@@ -5,7 +5,7 @@ import Freckle.App.Prelude  import Freckle.App.Stats (HasStatsClient)-import qualified Freckle.App.Stats as Stats+import Freckle.App.Stats qualified as Stats import Scientist import Scientist.Duration 
library/Freckle/App/Stats.hs view
@@ -44,10 +44,10 @@ import Data.String import Data.Time (diffUTCTime) import Freckle.App.Ecs-import qualified Freckle.App.Env as Env-import qualified Network.StatsD.Datadog as Datadog+import Freckle.App.Env qualified as Env+import Network.StatsD.Datadog qualified as Datadog import System.IO (hPutStrLn, stderr)-import qualified System.Metrics.Gauge as EKG+import System.Metrics.Gauge qualified as EKG import UnliftIO.Exception (bracket_) import Yesod.Core.Lens import Yesod.Core.Types (HandlerData)@@ -178,9 +178,9 @@ withGauge getGauge f = do   gauge' <- lookupGauge getGauge   bracket_ (inc gauge') (dec gauge') f-  where-    inc = incGauge-    dec = decGauge+ where+  inc = incGauge+  dec = decGauge  lookupGauge   :: (MonadReader app m, HasStatsClient app)
library/Freckle/App/Stats/Rts.hs view
@@ -5,12 +5,12 @@  import Freckle.App.Prelude -import qualified Control.Immortal as Immortal-import qualified Data.HashMap.Strict as HashMap+import Control.Immortal qualified as Immortal+import Data.HashMap.Strict qualified as HashMap import Freckle.App.Stats (HasStatsClient)-import qualified Freckle.App.Stats as Stats-import qualified System.Metrics as Ekg-import qualified System.Metrics.Distribution.Internal as Ekg+import Freckle.App.Stats qualified as Stats+import System.Metrics qualified as Ekg+import System.Metrics.Distribution.Internal qualified as Ekg import UnliftIO.Concurrent (threadDelay)  -- | Initialize a thread to poll RTS stats
library/Freckle/App/Test.hs view
@@ -37,8 +37,8 @@ import Control.Lens (view) import Control.Monad.Base import Control.Monad.Catch (ExitCase (..), MonadCatch, MonadThrow, mask)-import qualified Control.Monad.Catch-import qualified Control.Monad.Fail as Fail+import Control.Monad.Catch qualified+import Control.Monad.Fail qualified as Fail import Control.Monad.Primitive import Control.Monad.Random (MonadRandom (..)) import Control.Monad.Reader@@ -50,13 +50,13 @@   , MonadSqlTx (..)   , runDB   )-import qualified Freckle.App.Dotenv as Dotenv-import qualified Freckle.App.Exception.MonadThrow as MonadThrow+import Freckle.App.Dotenv qualified as Dotenv+import Freckle.App.Exception.MonadThrow qualified as MonadThrow import Freckle.App.OpenTelemetry-import qualified Test.Hspec as Hspec hiding (expectationFailure)+import Test.Hspec qualified as Hspec hiding (expectationFailure) import Test.Hspec.Core.Spec (Arg, Example, SpecWith, evaluateExample)-import qualified Test.Hspec.Expectations.Lifted as Hspec (expectationFailure)-import qualified UnliftIO.Exception as UnliftIO+import Test.Hspec.Expectations.Lifted qualified as Hspec (expectationFailure)+import UnliftIO.Exception qualified as UnliftIO  -- | An Hspec example over some @App@ value --
library/Freckle/App/Test/DocTest.hs view
@@ -13,10 +13,10 @@  import Control.Monad (filterM) import Data.Aeson-import qualified Data.Text as T-import qualified Data.Text.IO as T+import Data.Text qualified as T+import Data.Text.IO qualified as T import Data.Yaml (decodeFileThrow)-import qualified Test.DocTest as DocTest+import Test.DocTest qualified as DocTest import "Glob" System.FilePath.Glob (globDir1)  -- | Run doctest on files in the given directory
library/Freckle/App/Test/Hspec/Runner.hs view
@@ -29,7 +29,7 @@   , hspecWithResult   , readConfig   )-import qualified Prelude as Unsafe (read)+import Prelude qualified as Unsafe (read)  run :: String -> Spec -> IO () run = runWith defaultConfig
library/Freckle/App/Test/Http.hs view
@@ -49,13 +49,13 @@ import Control.Monad (filterM) import Control.Monad.Reader (runReaderT) import Data.Aeson (ToJSON, encode)-import qualified Data.ByteString.Lazy as BSL+import Data.ByteString.Lazy qualified as BSL import Data.List (stripPrefix) import Data.String (IsString (..)) import Freckle.App.Http (MonadHttp (..)) import Freckle.App.Test.Http.MatchRequest import Network.HTTP.Client (Request, Response)-import qualified Network.HTTP.Client.Internal as HTTP+import Network.HTTP.Client.Internal qualified as HTTP import Network.HTTP.Types.Header (ResponseHeaders, hAccept, hContentType) import Network.HTTP.Types.Status (Status, status200) import System.Directory (doesFileExist)@@ -86,11 +86,11 @@   maybe (error errorMessage) (toResponse req) $ headMay matched  where   (unmatched, matched) =-    partitionEithers $-      map+    partitionEithers+      $ map         ( \stub ->-            bimap (stub,) (const stub.response) $-              matchRequest req stub.match+            bimap (stub,) (const stub.response)+              $ matchRequest req stub.match         )         stubs 
library/Freckle/App/Test/Http/MatchRequest.hs view
@@ -24,13 +24,13 @@ import Freckle.App.Prelude  import Data.ByteString (ByteString)-import qualified Data.ByteString.Char8 as BS8-import qualified Data.ByteString.Lazy as BSL+import Data.ByteString.Char8 qualified as BS8+import Data.ByteString.Lazy qualified as BSL import Data.List (isPrefixOf) import Data.List.NonEmpty (NonEmpty (..))-import qualified Data.List.NonEmpty as NE+import Data.List.NonEmpty qualified as NE import Network.HTTP.Client (Request, RequestBody (..), parseRequest_)-import qualified Network.HTTP.Client.Internal as HTTP+import Network.HTTP.Client.Internal qualified as HTTP import Network.HTTP.Types.Header (Header, RequestHeaders) import Network.HTTP.Types.Method (Method) @@ -80,12 +80,12 @@  hasExplicitPath :: Bool -> ByteString -> Int -> String -> Bool hasExplicitPath secure host port url =-  any ((`isPrefixOf` url) . toUrlPrefix) $-    concat-      [ [Just port]-      , Nothing <$ guard (secure && port == 443)-      , Nothing <$ guard (not secure && port == 80)-      ]+  any+    (any ((`isPrefixOf` url) . toUrlPrefix))+    [ [Just port]+    , Nothing <$ guard (secure && port == 443)+    , Nothing <$ guard (not secure && port == 80)+    ]  where   toUrlPrefix mport =     mconcat
library/Freckle/App/Test/Yesod.hs view
@@ -81,14 +81,14 @@ import Control.Monad.Validate (ValidateT) import Data.Aeson (FromJSON, eitherDecode) import Data.BCP47 (BCP47)-import qualified Data.BCP47 as BCP47+import Data.BCP47 qualified as BCP47 import Data.ByteString (ByteString)-import qualified Data.ByteString as BS-import qualified Data.ByteString.Lazy as BSL+import Data.ByteString qualified as BS+import Data.ByteString.Lazy qualified as BSL import Data.CaseInsensitive (CI) import Data.Csv (FromNamedRecord, decodeByName)-import qualified Data.Text as T-import qualified Data.Vector as V+import Data.Text qualified as T+import Data.Vector qualified as V import Network.HTTP.Types.Header (hAccept, hAcceptLanguage, hContentType) import Network.Wai.Test (SResponse (..)) import Test.Hspec.Expectations.Lifted (expectationFailure)@@ -110,7 +110,7 @@   , setUrl   , withResponse   )-import qualified Yesod.Test+import Yesod.Test qualified  class (MonadIO m, Yesod site) => MonadYesodExample site m | m -> site where   liftYesodExample :: YesodExample site a -> m a
library/Freckle/App/Yesod.hs view
@@ -16,9 +16,9 @@   , withException   ) import Freckle.App.Stats (HasStatsClient)-import qualified Freckle.App.Stats as Stats+import Freckle.App.Stats qualified as Stats import Network.HTTP.Types (ResponseHeaders, status503)-import qualified Network.Wai as W+import Network.Wai qualified as W import Yesod.Core.Handler (HandlerFor, sendWaiResponse) import Yesod.Core.Types (HandlerContents) 
library/Freckle/App/Yesod/Routes.hs view
@@ -4,7 +4,7 @@  import Freckle.App.Prelude -import qualified Language.Haskell.TH as TH+import Language.Haskell.TH qualified as TH import Yesod.Routes.TH.Types  -- | Lambdacase expression to print route names
library/Network/Wai/Middleware/Cors.hs view
@@ -6,8 +6,8 @@ import Freckle.App.Prelude  import Data.ByteString (ByteString)-import qualified Data.ByteString as BS-import qualified Data.CaseInsensitive as CI+import Data.ByteString qualified as BS+import Data.CaseInsensitive qualified as CI import Network.HTTP.Types (ResponseHeaders) import Network.HTTP.Types.Status (status200) import Network.Wai
library/Network/Wai/Middleware/Stats.hs view
@@ -9,9 +9,9 @@ import Control.Lens ((^.)) import Control.Monad.Reader (runReaderT) import Data.Aeson ((.=))-import qualified Data.Aeson.Key as Key+import Data.Aeson.Key qualified as Key import Freckle.App.Stats (HasStatsClient (..), tagsL)-import qualified Freckle.App.Stats as Stats+import Freckle.App.Stats qualified as Stats import Network.HTTP.Types.Status (Status (..)) import Network.Wai (Middleware, Request, requestMethod, responseStatus) 
package.yaml view
@@ -1,5 +1,5 @@ name: freckle-app-version: 1.18.0.0+version: 1.18.1.0 maintainer: Freckle Education category: Utils github: freckle/freckle-app@@ -13,6 +13,8 @@ extra-source-files:   - package.yaml +language: GHC2021+ ghc-options:   - -fignore-optim-changes   - -fwrite-ide-info@@ -20,6 +22,7 @@   - -Wno-all-missed-specialisations   - -Wno-missing-exported-signatures # re-enables missing-signatures   - -Wno-missing-import-lists+  - -Wno-missing-kind-signatures   - -Wno-missing-local-signatures   - -Wno-missing-safe-haskell-mode   - -Wno-monomorphism-restriction@@ -31,38 +34,22 @@   - condition: "impl(ghc >= 9.8)"     ghc-options:       - -Wno-missing-role-annotations-  - condition: "impl(ghc >= 9.2)"-    ghc-options:-      - -Wno-missing-kind-signatures+      - -Wno-missing-poly-kind-signatures  dependencies:   - base < 5  default-extensions:-  - BangPatterns   - DataKinds   - DeriveAnyClass-  - DeriveFoldable-  - DeriveFunctor-  - DeriveGeneric-  - DeriveLift-  - DeriveTraversable   - DerivingVia   - DerivingStrategies-  - FlexibleContexts-  - FlexibleInstances   - GADTs-  - GeneralizedNewtypeDeriving   - LambdaCase-  - MultiParamTypeClasses   - NoImplicitPrelude   - NoMonomorphismRestriction   - OverloadedStrings-  - RankNTypes   - RecordWildCards-  - ScopedTypeVariables-  - StandaloneDeriving-  - TypeApplications   - TypeFamilies  library:@@ -158,6 +145,7 @@       - Blammo       - QuickCheck       - aeson+      - async       - bugsnag       - bytestring       - cassava
+ tests/Freckle/App/AsyncSpec.hs view
@@ -0,0 +1,29 @@+module Freckle.App.AsyncSpec+  ( spec+  ) where++import Freckle.App.Prelude++import Blammo.Logging+import Blammo.Logging qualified as Blammo+import Control.Concurrent.Async (wait)+import Data.Aeson.KeyMap qualified as KeyMap+import Freckle.App.Async (async)+import OpenTelemetry.Context qualified as OpenTelemetry+import OpenTelemetry.Context.ThreadLocal qualified as OpenTelemetry+import Test.Hspec++spec :: Spec+spec = do+  describe "async" $ do+    it @(IO ()) "preserves Blammo context" $ do+      let kvs = ["a" .= ("xyz" :: Text)]+      Blammo.withThreadContext kvs $+        (wait =<< async Blammo.myThreadContext)+          `shouldReturn` KeyMap.fromList kvs+    it @(IO ()) "preserves OpenTelemetry context" $ do+      k <- OpenTelemetry.newKey "a"+      let v = "xyz" :: Text+      OpenTelemetry.adjustContext $ OpenTelemetry.insert k v+      (wait =<< async (OpenTelemetry.lookup k <$> OpenTelemetry.getContext))+        `shouldReturn` Just v
tests/Freckle/App/Bugsnag/MetaDataSpec.hs view
@@ -10,7 +10,7 @@ import Freckle.App.Bugsnag import Freckle.App.Bugsnag.MetaData import Freckle.App.Stats-import qualified Freckle.App.Stats as Stats+import Freckle.App.Stats qualified as Stats  spec :: Spec spec = do
tests/Freckle/App/CsvSpec.hs view
@@ -7,11 +7,11 @@ import Conduit (ConduitT, MonadThrow, ResourceT, yieldMany) import Control.Monad.Validate (Validate, refute, runValidate) import Data.ByteString (ByteString)-import qualified Data.ByteString as BS+import Data.ByteString qualified as BS import Data.Csv hiding (header)-import qualified Data.List.NonEmpty as NE+import Data.List.NonEmpty qualified as NE import Data.Sequence.NonEmpty (NESeq)-import qualified Data.Vector as V+import Data.Vector qualified as V import Data.Void (Void) import Freckle.App.Csv import Test.Hspec
tests/Freckle/App/Http/CacheSpec.hs view
@@ -7,13 +7,13 @@  import Freckle.App.Prelude -import qualified Codec.Compression.GZip as GZip+import Codec.Compression.GZip qualified as GZip import Control.Lens ((&), (.~), (<>~)) import Control.Monad.State (StateT, execStateT) import Data.Aeson (FromJSON, eitherDecode) import Data.ByteString.Lazy (ByteString)-import qualified Data.ByteString.Lazy as BSL-import qualified Data.HashMap.Strict as HashMap+import Data.ByteString.Lazy qualified as BSL+import Data.HashMap.Strict qualified as HashMap import Data.Time (addUTCTime) import Freckle.App.Http import Freckle.App.Http.Cache
tests/Freckle/App/HttpSpec.hs view
@@ -7,7 +7,7 @@ import Control.Lens (to, (^?), _Left, _Right) import Data.Aeson import Data.Aeson.Lens-import qualified Data.List.NonEmpty as NE+import Data.List.NonEmpty qualified as NE import Freckle.App.Http import Freckle.App.Test.Http import Network.HTTP.Types.Status (status200)
tests/Freckle/App/Memcached/ServersSpec.hs view
@@ -6,7 +6,7 @@  import Control.Error.Util (hush) import Data.Either (isLeft, isRight)-import qualified Database.Memcache.Client as Memcache+import Database.Memcache.Client qualified as Memcache import Freckle.App.Memcached.Servers import Freckle.App.Test 
tests/Freckle/App/MemcachedSpec.hs view
@@ -11,12 +11,12 @@ import Control.Lens (lens, to, (^?)) import Data.Aeson (Value (..)) import Data.Aeson.Lens-import qualified Data.List.NonEmpty as NE-import qualified Data.Text as T-import qualified Freckle.App.Env as Env+import Data.List.NonEmpty qualified as NE+import Data.Text qualified as T+import Freckle.App.Env qualified as Env import Freckle.App.Memcached import Freckle.App.Memcached.Client (MemcachedClient, withMemcachedClient)-import qualified Freckle.App.Memcached.Client as Memcached+import Freckle.App.Memcached.Client qualified as Memcached import Freckle.App.Memcached.Servers import Freckle.App.OpenTelemetry 
tests/Freckle/App/OpenTelemetry/ContextSpec.hs view
@@ -7,11 +7,11 @@ import Blammo.Logging import Blammo.Logging.Logger (newTestLogger) import Control.Lens (lens)-import qualified Data.Text as T+import Data.Text qualified as T import Freckle.App.OpenTelemetry import Freckle.App.OpenTelemetry.Context import Network.HTTP.Types.Header (Header)-import qualified OpenTelemetry.Trace.Core as Trace+import OpenTelemetry.Trace.Core qualified as Trace  data App = App   { appLogger :: Logger
tests/Main.hs view
@@ -5,7 +5,7 @@ import Prelude  import Freckle.App.Test.Hspec.Runner (runParConfig)-import qualified Spec+import Spec qualified import Test.Hspec  main :: IO ()