packages feed

unleash-client-haskell 0.6.0 → 0.7.0

raw patch · 5 files changed

+95/−23 lines, 5 filesdep ~mtldep ~servantdep ~servant-client

Dependency ranges changed: mtl, servant, servant-client, unleash-client-haskell-core

Files

CHANGELOG.md view
@@ -1,3 +1,17 @@+## <small>0.7.0 (2024-06-24)</small>++* Format all ([0910331](https://github.com/finn-no/unleash-client-haskell/commit/0910331))+* Reformat flake.nix ([42cd35a](https://github.com/finn-no/unleash-client-haskell/commit/42cd35a))+* Relax mtl and servant-* constraints ([82f3e1f](https://github.com/finn-no/unleash-client-haskell/commit/82f3e1f))+* Simplify isEnabled and add isEnabledWithContext ([6d67d38](https://github.com/finn-no/unleash-client-haskell/commit/6d67d38))+* Support custom strategies (#12) ([bf56170](https://github.com/finn-no/unleash-client-haskell/commit/bf56170)), closes [#12](https://github.com/finn-no/unleash-client-haskell/issues/12)+* unleash-client-haskell-core: 0.11.0 ([1685750](https://github.com/finn-no/unleash-client-haskell/commit/1685750))+* Update flake-compat ([4fcfc9a](https://github.com/finn-no/unleash-client-haskell/commit/4fcfc9a))+* Update nixpkgs ([0498877](https://github.com/finn-no/unleash-client-haskell/commit/0498877))+* Update unleash-client-haskell-core ([f147f09](https://github.com/finn-no/unleash-client-haskell/commit/f147f09))+++ ## <small>0.6.0 (2023-10-16)</small>  * Set version to 0.6.0 ([925b4f6](https://github.com/finn-no/unleash-client-haskell/commit/925b4f6))
example/Main.hs view
@@ -18,7 +18,6 @@ import Data.Void (Void) import Servant.Client (BaseUrl (BaseUrl), Scheme (Http)) import System.Exit (die)-import Unleash (emptyContext) import Unleash.Client (     HasUnleash (..),     UnleashConfig (..),@@ -60,7 +59,7 @@ application :: Program Void application =     forever do-        enabled <- isEnabled featureToggle emptyContext+        enabled <- isEnabled featureToggle         liftIO . putStrLn $ T.unpack featureToggle <> " is " <> (if enabled then "enabled" else "disabled")         liftIO . threadDelay $ 2 * 1000 * 1000 
src/Unleash/Client.hs view
@@ -13,15 +13,23 @@     UnleashConfig (..),     HasUnleash (..),     registerClient,+    registerClientWithCustomStrategies,     pollToggles,+    pollTogglesWithCustomStrategies,     pushMetrics,     isEnabled,+    isEnabledWithContext,     tryIsEnabled,+    tryIsEnabledWithContext,     getVariant,     tryGetVariant,     -- Re-exports     Context (..),     emptyContext,+    FeatureToggleName,+    Strategy (..),+    StrategyEvaluator,+    SupportedStrategies,     VariantResponse (..), ) where @@ -33,12 +41,28 @@ import Data.Time (UTCTime, getCurrentTime) import Network.HTTP.Client.TLS (newTlsManager) import Servant.Client (BaseUrl, ClientEnv, ClientError, mkClientEnv)-import Unleash (Context (..), Features, MetricsPayload (..), RegisterPayload (..), VariantResponse (..), emptyContext, emptyVariantResponse, featureGetVariant, featureIsEnabled)+import Unleash (+    Context (..),+    FeatureToggleName,+    Features,+    MetricsPayload (..),+    RegisterPayload (..),+    Strategy (..),+    StrategyEvaluator,+    SupportedStrategies,+    VariantResponse (..),+    defaultStrategyEvaluator,+    defaultSupportedStrategies,+    emptyContext,+    emptyVariantResponse,+    featureGetVariant,+    featureIsEnabled,+ ) import Unleash.Internal.HttpClient (getAllClientFeatures, register, sendMetrics)  -- | Smart constructor for Unleash client configuration. Initializes the mutable variables properly. makeUnleashConfig ::-    MonadIO m =>+    (MonadIO m) =>     -- | Application name.     Text ->     -- | Instance identifier.@@ -96,7 +120,11 @@  -- | Register client for the Unleash server. Call this on application startup before calling the state poller and metrics pusher functions. registerClient :: (HasUnleash r, MonadReader r m, MonadIO m) => m (Either ClientError ())-registerClient = do+registerClient = registerClientWithCustomStrategies defaultSupportedStrategies++-- | Register client for the Unleash server. Custom strategies are added to default strategies. Call this on application startup before calling the state poller and metrics pusher functions.+registerClientWithCustomStrategies :: (HasUnleash r, MonadReader r m, MonadIO m) => SupportedStrategies -> m (Either ClientError ())+registerClientWithCustomStrategies customSupportedStrategies = do     config <- asks getUnleashConfig     now <- liftIO getCurrentTime     let registrationPayload :: RegisterPayload@@ -104,6 +132,7 @@             RegisterPayload                 { appName = config.applicationName,                   instanceId = config.instanceId,+                  strategies = defaultSupportedStrategies <> customSupportedStrategies,                   started = now,                   intervalSeconds = config.metricsPushIntervalInSeconds                 }@@ -111,16 +140,28 @@  -- | Fetch the most recent feature toggle set from the Unleash server. Meant to be run every statePollIntervalInSeconds. Non-blocking. pollToggles :: (HasUnleash r, MonadReader r m, MonadIO m) => m (Either ClientError ())-pollToggles = do+pollToggles = pollTogglesWithCustomStrategies defaultStrategyEvaluator++-- | Fetch the most recent feature toggle set from the Unleash server. Custom strategies are added to default strategies. Meant to be run every statePollIntervalInSeconds. Non-blocking.+pollTogglesWithCustomStrategies :: (HasUnleash r, MonadReader r m, MonadIO m) => StrategyEvaluator -> m (Either ClientError ())+pollTogglesWithCustomStrategies customStrategyEvaluator = do     config <- asks getUnleashConfig-    eitherFeatures <- getAllClientFeatures config.httpClientEnvironment config.apiKey+    eitherFeatures <- getAllClientFeatures config.httpClientEnvironment strategyEvaluator config.apiKey     either (const $ pure ()) (updateState config.state) eitherFeatures     pure . void $ eitherFeatures     where+        strategyEvaluator :: StrategyEvaluator+        strategyEvaluator = withCustomStrategyEvaluator customStrategyEvaluator         updateState state value = do             isUpdated <- liftIO $ tryPutMVar state value             liftIO . unless isUpdated . void $ swapMVar state value +withCustomStrategyEvaluator :: StrategyEvaluator -> StrategyEvaluator+withCustomStrategyEvaluator customStrategyEvaluator featureToggleName jsonStrategy ctx = do+    defaultResult <- defaultStrategyEvaluator featureToggleName jsonStrategy ctx+    customResult <- customStrategyEvaluator featureToggleName jsonStrategy ctx+    pure $ defaultResult || customResult+ -- | Push metrics to the Unleash server. Meant to be run every metricsPushIntervalInSeconds. Blocks if the mutable metrics variables are empty. pushMetrics :: (HasUnleash r, MonadReader r m, MonadIO m) => m (Either ClientError ()) pushMetrics = do@@ -144,10 +185,19 @@     -- | Feature toggle name.     Text ->     -- | Client context.+    m Bool+isEnabled feature = isEnabledWithContext feature emptyContext++-- | Check if a feature is enabled or not. Blocks until first feature toggle set is received. Blocks if the mutable metrics variables are empty.+isEnabledWithContext ::+    (HasUnleash r, MonadReader r m, MonadIO m) =>+    -- | Feature toggle name.+    Text ->+    -- | Client context.     Context ->     -- | Whether or not the feature toggle is enabled.     m Bool-isEnabled feature context = do+isEnabledWithContext feature context = do     config <- asks getUnleashConfig     state <- liftIO . readMVar $ config.state     enabled <- featureIsEnabled state feature context@@ -160,10 +210,19 @@     -- | Feature toggle name.     Text ->     -- | Client context.+    m Bool+tryIsEnabled feature = tryIsEnabledWithContext feature emptyContext++-- | Check if a feature is enabled or not. Returns false for all toggles until first toggle set is received. Blocks if the mutable metrics variables are empty.+tryIsEnabledWithContext ::+    (HasUnleash r, MonadReader r m, MonadIO m) =>+    -- | Feature toggle name.+    Text ->+    -- | Client context.     Context ->     -- | Whether or not the feature toggle is enabled.     m Bool-tryIsEnabled feature context = do+tryIsEnabledWithContext feature context = do     config <- asks getUnleashConfig     maybeState <- liftIO . tryReadMVar $ config.state     case maybeState of
src/Unleash/Internal/HttpClient.hs view
@@ -22,7 +22,8 @@ import Paths_unleash_client_haskell (version) import Servant.API (Accept (contentTypes), Get, Header, JSON, MimeRender (mimeRender), NoContent, PostNoContent, ReqBody, type (:<|>) (..), type (:>)) import Servant.Client (ClientEnv, ClientError, client, runClientM)-import Unleash.Internal.DomainTypes (Features, fromJsonFeatures, supportedStrategies)+import Unleash (Features, StrategyEvaluator)+import Unleash.Internal.DomainTypes (fromJsonFeatures) import Unleash.Internal.JsonTypes (FullMetricsBucket (..), FullMetricsPayload (..), FullRegisterPayload (..), MetricsPayload, RegisterPayload, YesAndNoes (..)) import qualified Unleash.Internal.JsonTypes as UJT @@ -46,28 +47,28 @@         "application" M.// "json"             NE.:| ["application" M.// "json"] -instance {-# OVERLAPPABLE #-} ToJSON a => MimeRender CustomJSON a where+instance {-# OVERLAPPABLE #-} (ToJSON a) => MimeRender CustomJSON a where     mimeRender _ = encode -register :: MonadIO m => ClientEnv -> Maybe ApiKey -> RegisterPayload -> m (Either ClientError NoContent)+register :: (MonadIO m) => ClientEnv -> Maybe ApiKey -> RegisterPayload -> m (Either ClientError NoContent) register clientEnv apiKey registerPayload = do     let fullRegisterPayload =             FullRegisterPayload                 { appName = registerPayload.appName,                   instanceId = registerPayload.instanceId,                   sdkVersion = "unleash-client-haskell:" <> (T.pack . showVersion) version,-                  strategies = supportedStrategies,+                  strategies = registerPayload.strategies,                   started = registerPayload.started,                   interval = registerPayload.intervalSeconds * 1000                 }     liftIO $ runClientM (register' apiKey (Just "application/json") fullRegisterPayload) clientEnv -getAllClientFeatures :: MonadIO m => ClientEnv -> Maybe ApiKey -> m (Either ClientError Features)-getAllClientFeatures clientEnv apiKey = do+getAllClientFeatures :: (MonadIO m) => ClientEnv -> StrategyEvaluator -> Maybe ApiKey -> m (Either ClientError Features)+getAllClientFeatures clientEnv strategyEvaluator apiKey = do     eitherFeatures <- liftIO $ runClientM (getAllClientFeatures' apiKey) clientEnv-    pure $ fromJsonFeatures <$> eitherFeatures+    pure $ fromJsonFeatures strategyEvaluator <$> eitherFeatures -sendMetrics :: MonadIO m => ClientEnv -> Maybe ApiKey -> MetricsPayload -> m (Either ClientError NoContent)+sendMetrics :: (MonadIO m) => ClientEnv -> Maybe ApiKey -> MetricsPayload -> m (Either ClientError NoContent) sendMetrics clientEnv apiKey metricsPayload = do     liftIO $ runClientM (sendMetrics' apiKey fullMetricsPayload) clientEnv     where
unleash-client-haskell.cabal view
@@ -1,7 +1,7 @@ cabal-version: 3.0  name: unleash-client-haskell-version: 0.6.0+version: 0.7.0 synopsis: Unleash feature toggle client description:     This is an [Unleash](https://www.getunleash.io/) client SDK for Haskell.@@ -65,14 +65,14 @@         aeson >= 2.0.3 && < 2.2,         base >= 4.7 && < 5,         containers >= 0.6.4 && < 0.7,-        mtl >= 2.2.2 && < 2.3,+        mtl >= 2.2.2 && < 2.4,         text >= 1.2.5 && < 2.1,         time >= 1.9.3 && < 1.13,         http-client-tls >= 0.3.6 && < 0.4,         http-media >= 0.8.0 && < 0.9,-        servant >= 0.19.1 && < 0.20,-        servant-client >= 0.19 && < 0.20,-        unleash-client-haskell-core >= 0.8.7 && < 0.11,+        servant >= 0.19.1 && < 0.21,+        servant-client >= 0.19 && < 0.21,+        unleash-client-haskell-core >= 0.11.0 && < 0.12,  executable example     import: all@@ -85,4 +85,3 @@         servant-client,         text,         unleash-client-haskell,-        unleash-client-haskell-core,