module Control.Flipper.Adapters.Postgres.Models
( module Control.Flipper.Adapters.Postgres.Models
, module Database.Persist.Postgresql
) where
import qualified Data.Map.Strict as Map
import Data.Monoid ((<>))
import Data.Set (Set)
import qualified Data.Set as S
import Data.Text (Text)
import qualified Data.Text as T
import Data.Time (UTCTime (..), getCurrentTime)
import Database.Persist.Postgresql
import Database.Persist.TH
import qualified Control.Flipper.Types as F
share [mkPersist sqlSettings, mkMigrate "migrateAll"] [persistLowerCase|
Actor sql=flipper_actors
actorId F.ActorId sqltype=bytea
featureId FeatureId sqltype=bigint
updated UTCTime default=now()
created UTCTime default=now()
UniqueActorIdFeatureId actorId featureId
deriving Show Eq
Feature sql=flipper_features
name F.FeatureName sqltype=text
enabled Bool sqltype=boolean default=false
enabledPercentage F.Percentage sqltype=int default=0
updated UTCTime default=now()
created UTCTime default=now()
UniqueFeatureName name
deriving Show Eq
|]
instance PersistField F.FeatureName where
toPersistValue = PersistText . F.unFeatureName
fromPersistValue (PersistText name) = Right (F.FeatureName name)
fromPersistValue name = Left ("Not PersistText " <> T.pack (show name))
instance PersistField F.ActorId where
toPersistValue (F.ActorId actorId) = PersistByteString actorId
fromPersistValue (PersistByteString actorId) = Right (F.ActorId actorId)
fromPersistValue e = Left ("Not PersistByteString " <> T.pack (show e))
instance PersistField F.Percentage where
toPersistValue (F.Percentage pct) = PersistInt64 (fromIntegral pct)
fromPersistValue (PersistInt64 pct) = Right (F.Percentage (fromIntegral pct))
fromPersistValue e = Left ("Not PersistInt64 " <> T.pack (show e))
type FeatureWithActorIds = (Feature, Set F.ActorId)
mkFeature :: F.FeatureName -> Bool -> IO Feature
mkFeature fName isEnabled = do
now <- getCurrentTime
return Feature
{ featureName = fName
, featureEnabled = isEnabled
, featureEnabledPercentage = 0
, featureUpdated = now
, featureCreated = now
}
modelsToFeatures :: [Entity Feature] -> F.Features
modelsToFeatures fs = F.Features $ Map.fromList $ map (toFeatureTuple . modelToFeature . entityVal) fs
modelToFeature :: Feature -> F.Feature
modelToFeature feature = F.Feature
{ F.featureName = featureName feature
, F.isEnabled = featureEnabled feature
, F.enabledActors = S.empty
, F.enabledPercentage = featureEnabledPercentage feature
}
actorIdToModel :: F.ActorId -> FeatureId -> IO Actor
actorIdToModel a f = do
now <- getCurrentTime
return Actor
{ actorActorId = a
, actorFeatureId = f
, actorUpdated = now
, actorCreated = now
}
featureToModel :: F.Feature -> IO FeatureWithActorIds
featureToModel f = do
now <- getCurrentTime
return (feature now, actorIds)
where
actorIds :: Set F.ActorId
actorIds = F.enabledActors f
feature :: UTCTime -> Feature
feature now = Feature
{ featureName = F.featureName f
, featureEnabled = F.isEnabled f
, featureEnabledPercentage = F.enabledPercentage f
, featureUpdated = now
, featureCreated = now
}
toFeatureTuple :: F.Feature -> (F.FeatureName, F.Feature)
toFeatureTuple f = (F.featureName f, f)
runMigrations :: ConnectionPool -> IO [Text]
runMigrations = runSqlPool (runMigrationSilent migrateAll)