module Polysemy.Hasql.Queue.Store where import Data.UUID (UUID) import Generics.SOP (NP (Nil, (:*))) import Polysemy.Db.Data.DbError (DbError) import Polysemy.Db.Effect.Store (Store) import Prelude hiding (Queue, listen) import Sqel.Codec (PrimColumn) import Sqel.Comp (CompName) import Sqel.Data.QuerySchema (QuerySchema) import Sqel.Data.TableSchema (TableSchema) import Sqel.Data.Uid (Uuid) import Sqel.PgType (tableSchema) import qualified Sqel.Prim as Sqel import Sqel.Prim (prim, primAs) import Sqel.Product (prod) import Sqel.Query (checkQuery) import Sqel.Uid (uid) import Polysemy.Hasql.Effect.Database (Database) import Polysemy.Hasql.Interpreter.DbTable (interpretTable) import Polysemy.Hasql.Interpreter.Store (interpretStoreDb) import Polysemy.Hasql.Queue.Data.Queued (Queued) import Sqel.Data.Sel (TSel(TSel)) class StoreTable t d where storeTable :: (TableSchema (Uuid (Queued t d)), QuerySchema UUID (Uuid (Queued t d))) instance ( ToJSON d, FromJSON d, PrimColumn t, CompName d ('TSel prefix name), KnownSymbol (AppendSymbol "Queued" name) ) => StoreTable t d where storeTable :: (TableSchema (Uuid (Queued t d)), QuerySchema UUID (Uuid (Queued t d))) storeTable = (TableSchema (DdType ('DdK 'SelAuto '[] (Uuid (Queued t d)) ('Comp ('TSel 'NoPrefix (AppendSymbol "Queued" name)) ('Prod 'Reg) 'Nest '[ 'DdK ('SelSymbol "id") '[] UUID 'Prim, 'DdK 'SelAuto '[] (Queued t d) ('Comp ('TSel 'NoPrefix (AppendSymbol "Queued" name)) ('Prod 'Reg) 'Merge '[ 'DdK ('SelSymbol "queue_created") '[] t 'Prim, 'DdK ('SelSymbol "queue_payload") '[PgPrimName, PrimValueCodec d] d 'Prim])]))) ts, QuerySchema (DdType ('DdK ('SelSymbol "id") '[] UUID 'Prim)) (DdType ('DdK 'SelAuto '[] (Uuid (Queued t d)) ('Comp ('TSel 'NoPrefix (AppendSymbol "Queued" name)) ('Prod 'Reg) 'Nest '[ 'DdK ('SelSymbol "id") '[] UUID 'Prim, 'DdK 'SelAuto '[] (Queued t d) ('Comp ('TSel 'NoPrefix (AppendSymbol "Queued" name)) ('Prod 'Reg) 'Merge '[ 'DdK ('SelSymbol "queue_created") '[] t 'Prim, 'DdK ('SelSymbol "queue_payload") '[PgPrimName, PrimValueCodec d] d 'Prim])]))) qs) where ts :: TableSchema (DdType ('DdK 'SelAuto '[] (Uuid (Queued t d)) ('Comp ('TSel 'NoPrefix (AppendSymbol "Queued" name)) ('Prod 'Reg) 'Nest '[ 'DdK ('SelSymbol "id") '[] UUID 'Prim, 'DdK 'SelAuto '[] (Queued t d) ('Comp ('TSel 'NoPrefix (AppendSymbol "Queued" name)) ('Prod 'Reg) 'Merge '[ 'DdK ('SelSymbol "queue_created") '[] t 'Prim, 'DdK ('SelSymbol "queue_payload") '[PgPrimName, PrimValueCodec d] d 'Prim])]))) ts = forall (table :: DdK). MkTableSchema table => Dd table -> TableSchema (DdType table) tableSchema forall {i}. Dd ('DdK 'SelAuto '[] (Uid i (Queued t d)) ('Comp ('TSel 'NoPrefix (AppendSymbol "Queued" name)) ('Prod 'Reg) 'Nest '[ 'DdK ('SelSymbol "id") '[] i 'Prim, 'DdK 'SelAuto '[] (Queued t d) ('Comp ('TSel 'NoPrefix (AppendSymbol "Queued" name)) ('Prod 'Reg) 'Merge '[ 'DdK ('SelSymbol "queue_created") '[] t 'Prim, 'DdK ('SelSymbol "queue_payload") '[PgPrimName, PrimValueCodec d] d 'Prim])])) table qs :: QuerySchema (DdType ('DdK ('SelSymbol "id") '[] UUID 'Prim)) (DdType ('DdK 'SelAuto '[] (Uuid (Queued t d)) ('Comp ('TSel 'NoPrefix (AppendSymbol "Queued" name)) ('Prod 'Reg) 'Nest '[ 'DdK ('SelSymbol "id") '[] UUID 'Prim, 'DdK 'SelAuto '[] (Queued t d) ('Comp ('TSel 'NoPrefix (AppendSymbol "Queued" name)) ('Prod 'Reg) 'Merge '[ 'DdK ('SelSymbol "queue_created") '[] t 'Prim, 'DdK ('SelSymbol "queue_payload") '[PgPrimName, PrimValueCodec d] d 'Prim])]))) qs = forall (query :: DdK) (table :: DdK). CheckQuery query table => Dd query -> Dd table -> QuerySchema (DdType query) (DdType table) checkQuery forall {a}. Dd ('DdK ('SelSymbol "id") '[] a 'Prim) query forall {i}. Dd ('DdK 'SelAuto '[] (Uid i (Queued t d)) ('Comp ('TSel 'NoPrefix (AppendSymbol "Queued" name)) ('Prod 'Reg) 'Nest '[ 'DdK ('SelSymbol "id") '[] i 'Prim, 'DdK 'SelAuto '[] (Queued t d) ('Comp ('TSel 'NoPrefix (AppendSymbol "Queued" name)) ('Prod 'Reg) 'Merge '[ 'DdK ('SelSymbol "queue_created") '[] t 'Prim, 'DdK ('SelSymbol "queue_payload") '[PgPrimName, PrimValueCodec d] d 'Prim])])) table query :: Dd ('DdK ('SelSymbol "id") '[] a 'Prim) query = forall (name :: Symbol) a. KnownSymbol name => Dd ('DdK ('SelSymbol name) '[] a 'Prim) primAs @"id" table :: Dd ('DdK 'SelAuto '[] (Uid i (DdType ('DdK 'SelAuto '[] (Queued t d) ('Comp ('TSel 'NoPrefix (AppendSymbol "Queued" name)) ('Prod 'Reg) 'Nest '[ 'DdK ('SelSymbol "queue_created") '[] t 'Prim, 'DdK ('SelSymbol "queue_payload") '[PgPrimName, PrimValueCodec d] d 'Prim])))) ('Comp (DdTypeSel ('DdK 'SelAuto '[] (Queued t d) ('Comp ('TSel 'NoPrefix (AppendSymbol "Queued" name)) ('Prod 'Reg) 'Nest '[ 'DdK ('SelSymbol "queue_created") '[] t 'Prim, 'DdK ('SelSymbol "queue_payload") '[PgPrimName, PrimValueCodec d] d 'Prim]))) ('Prod 'Reg) 'Nest '[ 'DdK ('SelSymbol "id") '[] i 'Prim, 'DdK 'SelAuto '[] (Queued t d) ('Comp ('TSel 'NoPrefix (AppendSymbol "Queued" name)) ('Prod 'Reg) 'Merge '[ 'DdK ('SelSymbol "queue_created") '[] t 'Prim, 'DdK ('SelSymbol "queue_payload") '[PgPrimName, PrimValueCodec d] d 'Prim])])) table = forall i a (si :: DdK) (sa :: DdK) (s :: DdK). UidColumn i a si sa s => Dd si -> Dd sa -> Dd s uid forall a. Dd ('DdK 'SelAuto '[] a 'Prim) prim (forall a arg (s :: DdK). Product a arg s => arg -> Dd s prod (forall a. Dd ('DdK 'SelAuto '[] a 'Prim) prim forall {k} (a :: k -> *) (x :: k) (xs :: [k]). a x -> NP a xs -> NP a (x : xs) :* forall a. (ToJSON a, FromJSON a) => Dd ('DdK 'SelAuto '[PgPrimName, PrimValueCodec a] a 'Prim) Sqel.json forall {k} (a :: k -> *) (x :: k) (xs :: [k]). a x -> NP a xs -> NP a (x : xs) :* forall {k} (a :: k -> *). NP a '[] Nil)) interpretQueueStoreDb :: ∀ d t dt r . StoreTable t d => Members [Database !! DbError, Time t dt, Log, Resource, Async, Race, Embed IO, Final IO] r => InterpreterFor (Store UUID (Queued t d) !! DbError) r interpretQueueStoreDb :: forall d t dt (r :: EffectRow). (StoreTable t d, Members '[Database !! DbError, Time t dt, Log, Resource, Async, Race, Embed IO, Final IO] r) => InterpreterFor (Store UUID (Queued t d) !! DbError) r interpretQueueStoreDb = forall d (r :: EffectRow). Members '[Database !! DbError, Log, Embed IO] r => TableSchema d -> InterpreterFor (DbTable d !! DbError) r interpretTable TableSchema (Uuid (Queued t d)) ts forall b c a. (b -> c) -> (a -> b) -> a -> c . forall i d e (r :: EffectRow). Member (StoreTable i d !! e) r => TableSchema (Uid i d) -> QuerySchema i (Uid i d) -> InterpreterFor (Store i d !! e) r interpretStoreDb TableSchema (Uuid (Queued t d)) ts QuerySchema UUID (Uuid (Queued t d)) qs forall b c a. (b -> c) -> (a -> b) -> a -> c . forall (e2 :: (* -> *) -> * -> *) (e1 :: (* -> *) -> * -> *) (r :: EffectRow) a. Sem (e1 : r) a -> Sem (e1 : e2 : r) a raiseUnder where (TableSchema (Uuid (Queued t d)) ts, QuerySchema UUID (Uuid (Queued t d)) qs) = forall t d. StoreTable t d => (TableSchema (Uuid (Queued t d)), QuerySchema UUID (Uuid (Queued t d))) storeTable @t