packages feed

numerus-closus 0.3.0.0 → 0.4.0.0

raw patch · 4 files changed

+51/−41 lines, 4 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

- Control.NumerusClosus.Typed: instance GHC.Base.Semigroup Control.NumerusClosus.Typed.NextDebitable
+ Control.NumerusClosus: First :: a -> First a
+ Control.NumerusClosus: Last :: a -> Last a
+ Control.NumerusClosus: Max :: a -> Max a
+ Control.NumerusClosus: Min :: a -> Min a
+ Control.NumerusClosus: [getFirst] :: First a -> a
+ Control.NumerusClosus: [getLast] :: Last a -> a
+ Control.NumerusClosus: [getMax] :: Max a -> a
+ Control.NumerusClosus: [getMin] :: Min a -> a
+ Control.NumerusClosus: newtype First a
+ Control.NumerusClosus: newtype Last a
+ Control.NumerusClosus: newtype Max a
+ Control.NumerusClosus: newtype Min a
+ Control.NumerusClosus.Typed: First :: a -> First a
+ Control.NumerusClosus.Typed: Last :: a -> Last a
+ Control.NumerusClosus.Typed: Max :: a -> Max a
+ Control.NumerusClosus.Typed: Min :: a -> Min a
+ Control.NumerusClosus.Typed: [getFirst] :: First a -> a
+ Control.NumerusClosus.Typed: [getLast] :: Last a -> a
+ Control.NumerusClosus.Typed: [getMax] :: Max a -> a
+ Control.NumerusClosus.Typed: [getMin] :: Min a -> a
+ Control.NumerusClosus.Typed: instance GHC.Classes.Ord Control.NumerusClosus.Typed.NextDebitable
+ Control.NumerusClosus.Typed: newtype First a
+ Control.NumerusClosus.Typed: newtype Last a
+ Control.NumerusClosus.Typed: newtype Max a
+ Control.NumerusClosus.Typed: newtype Min a

Files

numerus-closus.cabal view
@@ -1,6 +1,6 @@ cabal-version:       3.0 name:                numerus-closus-version:             0.3.0.0+version:             0.4.0.0 author:              Gautier DI FOLCO maintainer:          gautier.difolco@gmail.com category:            Scheduling
src/Control/NumerusClosus.hs view
@@ -62,11 +62,18 @@     scheduleWith,     loopSchedule,     loopScheduleWith,++    -- * Reexports+    First (..),+    Last (..),+    Max (..),+    Min (..),   ) where  import qualified Control.NumerusClosus.Typed as Typed import qualified Data.List.NonEmpty as NE+import Data.Semigroup (First (..), Last (..), Max (..), Min (..)) import Data.Time (UTCTime (..))  -- * Main logic
src/Control/NumerusClosus/Typed.hs view
@@ -61,6 +61,12 @@     scheduleWith,     loopSchedule,     loopScheduleWith,++    -- * Reexports+    First (..),+    Last (..),+    Max (..),+    Min (..),   ) where @@ -68,6 +74,7 @@ import Control.Monad (mfilter) import qualified Data.Map.Strict as Map import Data.Maybe (fromMaybe)+import Data.Semigroup (First (..), Last (..), Max (..), Min (..)) import qualified Data.Set as Set import Data.Time (FormatTime, NominalDiffTime, ParseTime, UTCTime, addUTCTime, diffUTCTime, getCurrentTime) import GHC.Generics (Generic)@@ -82,16 +89,11 @@  -- | Represents when the next request can be debited. data NextDebitable-  = -- | The request will never be debitable again.-    Never-  | -- | The request can be debited from this time onwards.+  = -- | The request can be debited from this time onwards.     DebitableFrom UTCTime-  deriving stock (Eq, Show)--instance Semigroup NextDebitable where-  Never <> _ = Never-  _ <> Never = Never-  DebitableFrom x <> DebitableFrom y = DebitableFrom $ max x y+  | -- | The request will never be debitable again.+    Never+  deriving stock (Eq, Ord, Show)  -- * Base helpers @@ -289,9 +291,9 @@   debit (x :&& y) at =     case (debit x at, debit y at) of       (Right x', Right y') -> Right $ x' :&& y'-      (Left x', Left y') -> Left $ x' <> y'-      (Left x', _) -> Left x'-      (_, Left y') -> Left y'+      (Left x', Left y') -> Left $ getMax $ Max x' <> Max y'+      (Left x', _) -> Left $ getFirst $ First x'+      (_, Left y') -> Left $ getLast $ Last y'  -- | OR combinator type: allows a request if either rate limiter allows it. data a :|| b = a :|| b@@ -303,13 +305,7 @@   debit (x :|| y) at =     case (debit x at, debit y at) of       (Right x', Right y') -> Right $ x' :|| y'-      (Left x', Left y') ->-        Left $-          case (x', y') of-            (Never, Never) -> Never-            (DebitableFrom x'', DebitableFrom y'') -> DebitableFrom $ min x'' y''-            (DebitableFrom x'', _) -> DebitableFrom x''-            (_, DebitableFrom y'') -> DebitableFrom y''+      (Left x', Left y') -> Left $ getMin $ Min x' <> Min y'       (Right x', _) -> Right $ x' :|| y       (_, Right y') -> Right $ x :|| y' 
test/Spec.hs view
@@ -4,18 +4,16 @@  module Main (main) where -import Control.Monad (replicateM_)-import qualified Control.NumerusClosus as NC import Control.NumerusClosus ((.&&), (.||))-import Data.Either (isLeft, isRight)+import qualified Control.NumerusClosus as NC import Data.List.NonEmpty (NonEmpty ((:|)))-import qualified Data.List.NonEmpty as NE-import Data.Time (NominalDiffTime, UTCTime (..), addUTCTime, fromGregorian, secondsToNominalDiffTime)+import Data.Semigroup (Max (..), Min (..))+import Data.Time (UTCTime (..), addUTCTime, fromGregorian, secondsToNominalDiffTime) import qualified Hedgehog import qualified Hedgehog.Gen as Gen import qualified Hedgehog.Range as Range-import Test.Hspec (Expectation, Spec, describe, hspec, it, shouldBe, shouldSatisfy)-import Test.Hspec.Hedgehog (PropertyT, forAll, hedgehog, (===))+import Test.Hspec (Expectation, Spec, describe, hspec, it, shouldBe)+import Test.Hspec.Hedgehog (forAll, hedgehog, (===))  main :: IO () main = hspec spec@@ -42,7 +40,7 @@  debitSequence :: [UTCTime] -> NC.RateLimiter -> Either NC.NextDebitable NC.RateLimiter debitSequence [] rl = Right rl-debitSequence (t:ts) rl = case NC.debit rl t of+debitSequence (t : ts) rl = case NC.debit rl t of   Right rl' -> debitSequence ts rl'   Left nd -> Left nd @@ -232,16 +230,25 @@         assertLeftNever $ NC.debit (NC.anyOf (rlDeny :| [rlDeny])) baseTime         assertRight $ NC.debit (NC.anyOf (rlDeny :| [rlAllow])) baseTime -    describe "NextDebitable Semigroup" do-      it "Never <> anything = Never" do-        NC.Never <> NC.DebitableFrom baseTime `shouldBe` NC.Never-        NC.DebitableFrom baseTime <> NC.Never `shouldBe` NC.Never+    describe "NextDebitable Min / Max" do+      it "Max Never (DebitableFrom t) = Max Never" do+        getMax (Max NC.Never <> Max (NC.DebitableFrom baseTime)) `shouldBe` NC.Never+        getMax (Max (NC.DebitableFrom baseTime) <> Max NC.Never) `shouldBe` NC.Never -      it "DebitableFrom x <> DebitableFrom y = DebitableFrom (max x y)" do+      it "Max (DebitableFrom x) (DebitableFrom y) = DebitableFrom (max x y)" do         let t1 = offsetTime 10             t2 = offsetTime 20-        NC.DebitableFrom t1 <> NC.DebitableFrom t2 `shouldBe` NC.DebitableFrom t2+        getMax (Max (NC.DebitableFrom t1) <> Max (NC.DebitableFrom t2)) `shouldBe` NC.DebitableFrom t2 +      it "Min Never (DebitableFrom t) = Min (DebitableFrom t)" do+        getMin (Min NC.Never <> Min (NC.DebitableFrom baseTime)) `shouldBe` NC.DebitableFrom baseTime+        getMin (Min (NC.DebitableFrom baseTime) <> Min NC.Never) `shouldBe` NC.DebitableFrom baseTime++      it "Min (DebitableFrom x) (DebitableFrom y) = DebitableFrom (min x y)" do+        let t1 = offsetTime 10+            t2 = offsetTime 20+        getMin (Min (NC.DebitableFrom t1) <> Min (NC.DebitableFrom t2)) `shouldBe` NC.DebitableFrom t1+     describe "scheduleWith" do       it "mock PositionInTime pure test" do         let mockPit = NC.PositionInTime {NC.getTime = pure baseTime, NC.delayUntil = \_ -> pure ()}@@ -265,16 +272,16 @@         Right _ -> pure ()         Left _ -> Hedgehog.failure -    it "NextDebitable semigroup associativity" $ hedgehog do+    it "NextDebitable Max semigroup associativity" $ hedgehog do       a <- forAll genNextDebitable       b <- forAll genNextDebitable       c <- forAll genNextDebitable-      (a <> b) <> c === a <> (b <> c)+      Max a <> (Max b <> Max c) === (Max a <> Max b) <> Max c -    it "NextDebitable semigroup Never absorption" $ hedgehog do+    it "NextDebitable Max Never absorption" $ hedgehog do       x <- forAll genNextDebitable-      NC.Never <> x === NC.Never-      x <> NC.Never === NC.Never+      Max NC.Never <> Max x === Max NC.Never+      Max x <> Max NC.Never === Max NC.Never      it "fixedWindow allows exactly maxBucket per window" $ hedgehog do       maxBucket <- forAll (Gen.integral (Range.linear 1 50))@@ -304,6 +311,6 @@ genNextDebitable :: Hedgehog.Gen NC.NextDebitable genNextDebitable =   Gen.choice-    [ pure NC.Never-    , NC.DebitableFrom <$> genUTCTime+    [ pure NC.Never,+      NC.DebitableFrom <$> genUTCTime     ]