Fix bug in HTTP delivery actor storage, delivery wasn't working
This commit is contained in:
parent
1c10d3fb03
commit
6e55659410
2 changed files with 34 additions and 9 deletions
|
@ -1,6 +1,6 @@
|
||||||
{- This file is part of Vervis.
|
{- This file is part of Vervis.
|
||||||
-
|
-
|
||||||
- Written in 2023 by fr33domlover <fr33domlover@riseup.net>.
|
- Written in 2023, 2024 by fr33domlover <fr33domlover@riseup.net>.
|
||||||
-
|
-
|
||||||
- ♡ Copying is an act of love. Please copy, reuse and share.
|
- ♡ Copying is an act of love. Please copy, reuse and share.
|
||||||
-
|
-
|
||||||
|
@ -114,6 +114,7 @@ module Database.Persist.Box.Internal
|
||||||
where
|
where
|
||||||
|
|
||||||
import Control.Exception.Base
|
import Control.Exception.Base
|
||||||
|
import Control.Monad
|
||||||
import Control.Monad.IO.Class
|
import Control.Monad.IO.Class
|
||||||
import Control.Monad.IO.Unlift
|
import Control.Monad.IO.Unlift
|
||||||
import Control.Monad.Logger.CallStack
|
import Control.Monad.Logger.CallStack
|
||||||
|
@ -121,6 +122,7 @@ import Control.Monad.Trans.Class
|
||||||
import Data.ByteString (ByteString)
|
import Data.ByteString (ByteString)
|
||||||
import Data.Int
|
import Data.Int
|
||||||
import Data.Kind
|
import Data.Kind
|
||||||
|
import Data.Maybe
|
||||||
import Data.Proxy
|
import Data.Proxy
|
||||||
import Data.Text (Text)
|
import Data.Text (Text)
|
||||||
import Database.Persist
|
import Database.Persist
|
||||||
|
@ -165,7 +167,7 @@ createCellIfNeeded
|
||||||
createCellIfNeeded p = do
|
createCellIfNeeded p = do
|
||||||
r <-
|
r <-
|
||||||
rawSql
|
rawSql
|
||||||
"SELECT name FROM sqlite_schema WHERE type='table' AND name=?"
|
"SELECT name FROM sqlite_master WHERE type='table' AND name=?"
|
||||||
[PersistText "cell"]
|
[PersistText "cell"]
|
||||||
case r of
|
case r of
|
||||||
[] ->
|
[] ->
|
||||||
|
@ -176,7 +178,7 @@ createCellIfNeeded p = do
|
||||||
]
|
]
|
||||||
in rawExecute query []
|
in rawExecute query []
|
||||||
[Single (_ :: a)] -> pure ()
|
[Single (_ :: a)] -> pure ()
|
||||||
_ -> error "Multiple cell tables in sqlite_schema"
|
_ -> error "Multiple cell tables in sqlite_master"
|
||||||
|
|
||||||
model :: QuasiQuoter
|
model :: QuasiQuoter
|
||||||
model = PS.model ""
|
model = PS.model ""
|
||||||
|
@ -198,6 +200,7 @@ class Boxable a where
|
||||||
--type MigrationRecipes a :: * -> *
|
--type MigrationRecipes a :: * -> *
|
||||||
--migrateBox :: (MonadIO m, MonadLogger m, MonadMigrateBox m) => MigrationRecipe a m -> SqlPersistT m (Either Text (Int, Int))
|
--migrateBox :: (MonadIO m, MonadLogger m, MonadMigrateBox m) => MigrationRecipe a m -> SqlPersistT m (Either Text (Int, Int))
|
||||||
createBoxStorageIfNeeded :: MonadIO m => Proxy a -> SqlPersistT m ()
|
createBoxStorageIfNeeded :: MonadIO m => Proxy a -> SqlPersistT m ()
|
||||||
|
getB :: MonadIO m => SqlPersistT m (Maybe a)
|
||||||
bestowB :: MonadIO m => a -> SqlPersistT m ()
|
bestowB :: MonadIO m => a -> SqlPersistT m ()
|
||||||
obtainB :: MonadIO m => SqlPersistT m a
|
obtainB :: MonadIO m => SqlPersistT m a
|
||||||
|
|
||||||
|
@ -220,6 +223,9 @@ bestow = BoxPersistT . bestowB . wrapBF @(BV a) @a
|
||||||
obtain :: forall m a. (MonadIO m, BoxableVia a) => BoxPersistT a m a
|
obtain :: forall m a. (MonadIO m, BoxableVia a) => BoxPersistT a m a
|
||||||
obtain = BoxPersistT $ unwrapBF @(BV a) @a <$> obtainB
|
obtain = BoxPersistT $ unwrapBF @(BV a) @a <$> obtainB
|
||||||
|
|
||||||
|
get_b :: forall m a. (MonadIO m, BoxableVia a) => BoxPersistT a m (Maybe a)
|
||||||
|
get_b = BoxPersistT $ fmap (unwrapBF @(BV a) @a) <$> getB
|
||||||
|
|
||||||
newtype BoxableRecord a = BoxableRecord { unBoxableRecord :: a }
|
newtype BoxableRecord a = BoxableRecord { unBoxableRecord :: a }
|
||||||
|
|
||||||
instance BoxableFormat BoxableRecord where
|
instance BoxableFormat BoxableRecord where
|
||||||
|
@ -236,6 +242,7 @@ instance (PersistRecordBackend a SqlBackend, ToBackendKey SqlBackend a) => Boxab
|
||||||
--type MigrationRecipe (BoxablePersist a) m = [Migration SqlBackend m]
|
--type MigrationRecipe (BoxablePersist a) m = [Migration SqlBackend m]
|
||||||
--migrateBox ms = second (,length ms) <$> runMigrations schemaBackend? "" 1 ms
|
--migrateBox ms = second (,length ms) <$> runMigrations schemaBackend? "" 1 ms
|
||||||
createBoxStorageIfNeeded = createEntityIfNeeded . fmap unBoxableRecord
|
createBoxStorageIfNeeded = createEntityIfNeeded . fmap unBoxableRecord
|
||||||
|
getB = fmap BoxableRecord <$> get key
|
||||||
bestowB (BoxableRecord r) = repsert key r
|
bestowB (BoxableRecord r) = repsert key r
|
||||||
obtainB = BoxableRecord <$> getJust key
|
obtainB = BoxableRecord <$> getJust key
|
||||||
|
|
||||||
|
@ -253,6 +260,14 @@ instance PersistFieldSql a => Boxable (BoxableField a) where
|
||||||
--type MigrationRecipe (BoxablePersist a) = ???
|
--type MigrationRecipe (BoxablePersist a) = ???
|
||||||
--migrateBox ms = ???
|
--migrateBox ms = ???
|
||||||
createBoxStorageIfNeeded = createCellIfNeeded . fmap unBoxableField
|
createBoxStorageIfNeeded = createCellIfNeeded . fmap unBoxableField
|
||||||
|
getB = do
|
||||||
|
r <- rawSql query [toPersistValue keyN]
|
||||||
|
case r of
|
||||||
|
[] -> return Nothing
|
||||||
|
[Single v] -> return $ Just $ BoxableField v
|
||||||
|
_ -> liftIO $ throwIO $ BoxException "getB: multiple rows found"
|
||||||
|
where
|
||||||
|
query = "SELECT value FROM cell WHERE id=?"
|
||||||
bestowB (BoxableField v) =
|
bestowB (BoxableField v) =
|
||||||
rawExecute query [toPersistValue keyN, toPersistValue v]
|
rawExecute query [toPersistValue keyN, toPersistValue v]
|
||||||
where
|
where
|
||||||
|
@ -300,6 +315,7 @@ instance (Typeable a, Show a, Read a) => Boxable (BoxableShow a) where
|
||||||
--migrateBox ms = ???
|
--migrateBox ms = ???
|
||||||
createBoxStorageIfNeeded =
|
createBoxStorageIfNeeded =
|
||||||
createCellIfNeeded . fmap (WrapShow . unBoxableShow)
|
createCellIfNeeded . fmap (WrapShow . unBoxableShow)
|
||||||
|
getB = fmap (BoxableShow . unWrapShow . unBoxableField) <$> getB
|
||||||
bestowB = bestowB . BoxableField . WrapShow . unBoxableShow
|
bestowB = bestowB . BoxableField . WrapShow . unBoxableShow
|
||||||
obtainB = BoxableShow . unWrapShow . unBoxableField <$> obtainB
|
obtainB = BoxableShow . unWrapShow . unBoxableField <$> obtainB
|
||||||
|
|
||||||
|
@ -334,6 +350,7 @@ instance (Typeable a, A.FromJSON a, A.ToJSON a) => Boxable (BoxableJSON a) where
|
||||||
--migrateBox ms = ???
|
--migrateBox ms = ???
|
||||||
createBoxStorageIfNeeded =
|
createBoxStorageIfNeeded =
|
||||||
createCellIfNeeded . fmap (WrapJSON . unBoxableJSON)
|
createCellIfNeeded . fmap (WrapJSON . unBoxableJSON)
|
||||||
|
getB = fmap (BoxableJSON . unWrapJSON . unBoxableField) <$> getB
|
||||||
bestowB = bestowB . BoxableField . WrapJSON . unBoxableJSON
|
bestowB = bestowB . BoxableField . WrapJSON . unBoxableJSON
|
||||||
obtainB = BoxableJSON . unWrapJSON . unBoxableField <$> obtainB
|
obtainB = BoxableJSON . unWrapJSON . unBoxableField <$> obtainB
|
||||||
|
|
||||||
|
@ -362,6 +379,7 @@ instance (Typeable a, S.Serialize a) => Boxable (BoxableSerialize a) where
|
||||||
--migrateBox ms = ???
|
--migrateBox ms = ???
|
||||||
createBoxStorageIfNeeded =
|
createBoxStorageIfNeeded =
|
||||||
createCellIfNeeded . fmap (WrapSerialize . unBoxableSerialize)
|
createCellIfNeeded . fmap (WrapSerialize . unBoxableSerialize)
|
||||||
|
getB = fmap (BoxableSerialize . unWrapSerialize . unBoxableField) <$> getB
|
||||||
bestowB = bestowB . BoxableField . WrapSerialize . unBoxableSerialize
|
bestowB = bestowB . BoxableField . WrapSerialize . unBoxableSerialize
|
||||||
obtainB = BoxableSerialize . unWrapSerialize . unBoxableField <$> obtainB
|
obtainB = BoxableSerialize . unWrapSerialize . unBoxableField <$> obtainB
|
||||||
|
|
||||||
|
@ -382,6 +400,8 @@ loadBox path val = do
|
||||||
let proxy :: a -> Proxy (BV a a)
|
let proxy :: a -> Proxy (BV a a)
|
||||||
proxy _ = Proxy
|
proxy _ = Proxy
|
||||||
BoxPersistT $ createBoxStorageIfNeeded $ proxy val
|
BoxPersistT $ createBoxStorageIfNeeded $ proxy val
|
||||||
|
mval <- get_b
|
||||||
|
when (isNothing mval) $ bestow val
|
||||||
{-
|
{-
|
||||||
r <- migrateBox migrations
|
r <- migrateBox migrations
|
||||||
Left err -> do
|
Left err -> do
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{- This file is part of Vervis.
|
{- This file is part of Vervis.
|
||||||
-
|
-
|
||||||
- Written in 2023 by fr33domlover <fr33domlover@riseup.net>.
|
- Written in 2023, 2024 by fr33domlover <fr33domlover@riseup.net>.
|
||||||
-
|
-
|
||||||
- ♡ Copying is an act of love. Please copy, reuse and share.
|
- ♡ Copying is an act of love. Please copy, reuse and share.
|
||||||
-
|
-
|
||||||
|
@ -47,6 +47,8 @@ import Data.Traversable
|
||||||
import Database.Persist.Sql
|
import Database.Persist.Sql
|
||||||
import Network.HTTP.Client (Manager)
|
import Network.HTTP.Client (Manager)
|
||||||
import Network.HTTP.Types.Header (HeaderName)
|
import Network.HTTP.Types.Header (HeaderName)
|
||||||
|
import Network.HTTP.Types.URI (urlEncode, urlDecode)
|
||||||
|
import System.FilePath ((</>))
|
||||||
import System.Directory
|
import System.Directory
|
||||||
import Web.Hashids
|
import Web.Hashids
|
||||||
|
|
||||||
|
@ -54,6 +56,7 @@ import qualified Data.Aeson as A
|
||||||
import qualified Data.ByteString.Lazy as BL
|
import qualified Data.ByteString.Lazy as BL
|
||||||
import qualified Data.HashSet as HS
|
import qualified Data.HashSet as HS
|
||||||
import qualified Data.Text as T
|
import qualified Data.Text as T
|
||||||
|
import qualified Data.Text.Encoding as TE
|
||||||
|
|
||||||
import Control.Concurrent.Actor
|
import Control.Concurrent.Actor
|
||||||
import Database.Persist.Box
|
import Database.Persist.Box
|
||||||
|
@ -110,6 +113,7 @@ data DeliveryTheater u = DeliveryTheater
|
||||||
, _dtHeaders :: NonEmpty HeaderName
|
, _dtHeaders :: NonEmpty HeaderName
|
||||||
, _dtDelay :: Int
|
, _dtDelay :: Int
|
||||||
, _dtLog :: LogFunc
|
, _dtLog :: LogFunc
|
||||||
|
, _dtDir :: OsPath
|
||||||
, _dtTheater :: TheaterFor (Env u)
|
, _dtTheater :: TheaterFor (Env u)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -189,20 +193,21 @@ startDeliveryTheater headers micros manager logFunc dbRootDir = do
|
||||||
entries <- listDirectory dbRootDir
|
entries <- listDirectory dbRootDir
|
||||||
actors <- for entries $ \ path -> do
|
actors <- for entries $ \ path -> do
|
||||||
path' <- T.pack <$> decodeUtf path
|
path' <- T.pack <$> decodeUtf path
|
||||||
|
path'' <- either throwIO pure $ TE.decodeUtf8' $ urlDecode False $ TE.encodeUtf8 path'
|
||||||
u <-
|
u <-
|
||||||
case parseObjURI path' of
|
case parseObjURI path'' of
|
||||||
Left e ->
|
Left e ->
|
||||||
error $
|
error $
|
||||||
"Failed to parse URI-named SQLite db filename: " ++ e
|
"Failed to parse URI-named SQLite db filename: " ++ e
|
||||||
Right uri -> return uri
|
Right uri -> return uri
|
||||||
env <- mkEnv logFunc path
|
env <- mkEnv logFunc $ dbRootDir </> path
|
||||||
return (u, env, behavior manager headers micros u)
|
return (u, env, behavior manager headers micros u)
|
||||||
DeliveryTheater manager headers micros logFunc <$> startTheater logFunc actors
|
DeliveryTheater manager headers micros logFunc dbRootDir <$> startTheater logFunc actors
|
||||||
|
|
||||||
sendHttp :: UriMode u => DeliveryTheater u -> Method u -> [ObjURI u] -> IO ()
|
sendHttp :: UriMode u => DeliveryTheater u -> Method u -> [ObjURI u] -> IO ()
|
||||||
sendHttp (DeliveryTheater manager headers micros logFunc theater) method recips = do
|
sendHttp (DeliveryTheater manager headers micros logFunc root theater) method recips = do
|
||||||
for_ recips $ \ u ->
|
for_ recips $ \ u ->
|
||||||
let makeEnv = encodeUtf (T.unpack $ renderObjURI u) >>= mkEnv logFunc
|
let makeEnv = either throwIO pure (TE.decodeUtf8' $ urlEncode False $ TE.encodeUtf8 $ renderObjURI u) >>= encodeUtf . (root </>) . T.unpack >>= mkEnv logFunc
|
||||||
behave = behavior manager headers micros u
|
behave = behavior manager headers micros u
|
||||||
in void $ spawnIO theater u makeEnv behave
|
in void $ spawnIO theater u makeEnv behave
|
||||||
sendManyIO theater (HS.fromList recips) method
|
sendManyIO theater (HS.fromList recips) method
|
||||||
|
|
Loading…
Reference in a new issue