[ngrams] some more nodestory work (simplification and refactoring)

parent f348606c
...@@ -138,9 +138,6 @@ instance HasNodeStoryEnv Env where ...@@ -138,9 +138,6 @@ instance HasNodeStoryEnv Env where
instance HasNodeStoryVar Env where instance HasNodeStoryVar Env where
hasNodeStoryVar = hasNodeStory . nse_getter hasNodeStoryVar = hasNodeStory . nse_getter
instance HasNodeStorySaver Env where
hasNodeStorySaver = hasNodeStory . nse_saver
instance HasNodeStoryImmediateSaver Env where instance HasNodeStoryImmediateSaver Env where
hasNodeStoryImmediateSaver = hasNodeStory . nse_saver_immediate hasNodeStoryImmediateSaver = hasNodeStory . nse_saver_immediate
...@@ -310,9 +307,6 @@ instance HasNodeStoryEnv DevEnv where ...@@ -310,9 +307,6 @@ instance HasNodeStoryEnv DevEnv where
instance HasNodeStoryVar DevEnv where instance HasNodeStoryVar DevEnv where
hasNodeStoryVar = hasNodeStory . nse_getter hasNodeStoryVar = hasNodeStory . nse_getter
instance HasNodeStorySaver DevEnv where
hasNodeStorySaver = hasNodeStory . nse_saver
instance HasNodeStoryImmediateSaver DevEnv where instance HasNodeStoryImmediateSaver DevEnv where
hasNodeStoryImmediateSaver = hasNodeStory . nse_saver_immediate hasNodeStoryImmediateSaver = hasNodeStory . nse_saver_immediate
......
...@@ -173,10 +173,10 @@ mkChildrenGroups addOrRem nt patches = ...@@ -173,10 +173,10 @@ mkChildrenGroups addOrRem nt patches =
------------------------------------------------------------------------ ------------------------------------------------------------------------
saveNodeStory :: ( MonadReader env m, MonadBase IO m, HasNodeStorySaver env ) saveNodeStory :: ( MonadReader env m, MonadBase IO m, HasNodeStoryImmediateSaver env )
=> m () => m ()
saveNodeStory = do saveNodeStory = do
saver <- view hasNodeStorySaver saver <- view hasNodeStoryImmediateSaver
liftBase $ do liftBase $ do
--Gargantext.Prelude.putStrLn "---- Running node story saver ----" --Gargantext.Prelude.putStrLn "---- Running node story saver ----"
saver saver
...@@ -336,7 +336,7 @@ commitStatePatch listId (Versioned _p_version p) = do ...@@ -336,7 +336,7 @@ commitStatePatch listId (Versioned _p_version p) = do
-- NOTE This is changed now. Before we used MVar's, now it's TVars -- NOTE This is changed now. Before we used MVar's, now it's TVars
-- (MVar's blocked). It was wrapped in withMVar before, now we read -- (MVar's blocked). It was wrapped in withMVar before, now we read
-- the TVar, modify archive with archiveSaver, then write the tvar. -- the TVar, modify archive with archiveSaver, then write the TVar.
-- pure (newNs', snd newNs) -- pure (newNs', snd newNs)
-- writeTVar var newNs' -- writeTVar var newNs'
......
...@@ -52,8 +52,6 @@ module Gargantext.Core.NodeStory ...@@ -52,8 +52,6 @@ module Gargantext.Core.NodeStory
, hasNodeStory , hasNodeStory
, HasNodeStoryVar , HasNodeStoryVar
, hasNodeStoryVar , hasNodeStoryVar
, HasNodeStorySaver
, hasNodeStorySaver
, HasNodeStoryImmediateSaver , HasNodeStoryImmediateSaver
, hasNodeStoryImmediateSaver , hasNodeStoryImmediateSaver
, HasNodeArchiveStoryImmediateSaver , HasNodeArchiveStoryImmediateSaver
...@@ -61,11 +59,11 @@ module Gargantext.Core.NodeStory ...@@ -61,11 +59,11 @@ module Gargantext.Core.NodeStory
, NodeStory(..) , NodeStory(..)
, NgramsStatePatch' , NgramsStatePatch'
, NodeListStory , NodeListStory
, ArchiveList
, initNodeListStoryMock , initNodeListStoryMock
, NodeStoryEnv(..) , NodeStoryEnv(..)
, initNodeStory , initNodeStory
, nse_getter , nse_getter
, nse_saver
, nse_saver_immediate , nse_saver_immediate
, nse_archive_saver_immediate , nse_archive_saver_immediate
, nse_var , nse_var
...@@ -93,9 +91,8 @@ module Gargantext.Core.NodeStory ...@@ -93,9 +91,8 @@ module Gargantext.Core.NodeStory
where where
import Codec.Serialise.Class import Codec.Serialise.Class
-- import Control.Debounce (mkDebounce, defaultDebounceSettings, debounceFreq, debounceAction)
import Control.Exception (throw) import Control.Exception (throw)
import Control.Lens (makeLenses, Getter, (^.), (.~), (%~), _Just, at, view) import Control.Lens (makeLenses, Getter, (^.), (.~), (%~), non, _Just, at, view)
import Control.Monad.Except import Control.Monad.Except
import Control.Monad.Reader import Control.Monad.Reader
import Data.Aeson hiding ((.=), decode) import Data.Aeson hiding ((.=), decode)
...@@ -112,7 +109,9 @@ import Data.Text qualified as Text ...@@ -112,7 +109,9 @@ import Data.Text qualified as Text
import Database.PostgreSQL.Simple qualified as PGS import Database.PostgreSQL.Simple qualified as PGS
import Database.PostgreSQL.Simple.FromField (FromField(fromField), fromJSONField) import Database.PostgreSQL.Simple.FromField (FromField(fromField), fromJSONField)
import Database.PostgreSQL.Simple.SqlQQ (sql) import Database.PostgreSQL.Simple.SqlQQ (sql)
import Database.PostgreSQL.Simple.ToField qualified as PGS
import Database.PostgreSQL.Simple.Types (Values(..), QualifiedIdentifier(..)) import Database.PostgreSQL.Simple.Types (Values(..), QualifiedIdentifier(..))
import GHC.Conc (TVar, newTVar, readTVar, writeTVar)
import Gargantext.API.Ngrams.Types import Gargantext.API.Ngrams.Types
import Gargantext.Core.Types (ListId, NodeId(..), NodeType) import Gargantext.Core.Types (ListId, NodeId(..), NodeType)
import Gargantext.Core.Utils.Prefix (unPrefix) import Gargantext.Core.Utils.Prefix (unPrefix)
...@@ -122,14 +121,11 @@ import Gargantext.Database.Query.Table.Ngrams qualified as TableNgrams ...@@ -122,14 +121,11 @@ import Gargantext.Database.Query.Table.Ngrams qualified as TableNgrams
import Gargantext.Database.Query.Table.Node.Error (HasNodeError()) import Gargantext.Database.Query.Table.Node.Error (HasNodeError())
import Gargantext.Database.Schema.Ngrams (NgramsType) import Gargantext.Database.Schema.Ngrams (NgramsType)
import Gargantext.Prelude import Gargantext.Prelude
import GHC.Conc (TVar, newTVar, readTVar, writeTVar)
import Opaleye (DefaultFromField(..), SqlJsonb, fromPGSFromField) import Opaleye (DefaultFromField(..), SqlJsonb, fromPGSFromField)
import qualified Database.PostgreSQL.Simple.ToField as PGS
------------------------------------------------------------------------ ------------------------------------------------------------------------
data NodeStoryEnv = NodeStoryEnv data NodeStoryEnv = NodeStoryEnv
{ _nse_var :: !(TVar NodeListStory) { _nse_var :: !(TVar NodeListStory)
, _nse_saver :: !(IO ())
, _nse_saver_immediate :: !(IO ()) , _nse_saver_immediate :: !(IO ())
, _nse_archive_saver_immediate :: !(NodeListStory -> IO NodeListStory) , _nse_archive_saver_immediate :: !(NodeListStory -> IO NodeListStory)
, _nse_getter :: !([NodeId] -> IO (TVar NodeListStory)) , _nse_getter :: !([NodeId] -> IO (TVar NodeListStory))
...@@ -145,16 +141,13 @@ type HasNodeStory env err m = ( DbCmd' env err m ...@@ -145,16 +141,13 @@ type HasNodeStory env err m = ( DbCmd' env err m
, HasNodeError err , HasNodeError err
) )
class (HasNodeStoryVar env, HasNodeStorySaver env) class (HasNodeStoryVar env, HasNodeStoryImmediateSaver env)
=> HasNodeStoryEnv env where => HasNodeStoryEnv env where
hasNodeStory :: Getter env NodeStoryEnv hasNodeStory :: Getter env NodeStoryEnv
class HasNodeStoryVar env where class HasNodeStoryVar env where
hasNodeStoryVar :: Getter env ([NodeId] -> IO (TVar NodeListStory)) hasNodeStoryVar :: Getter env ([NodeId] -> IO (TVar NodeListStory))
class HasNodeStorySaver env where
hasNodeStorySaver :: Getter env (IO ())
class HasNodeStoryImmediateSaver env where class HasNodeStoryImmediateSaver env where
hasNodeStoryImmediateSaver :: Getter env (IO ()) hasNodeStoryImmediateSaver :: Getter env (IO ())
...@@ -168,7 +161,7 @@ class HasNodeArchiveStoryImmediateSaver env where ...@@ -168,7 +161,7 @@ class HasNodeArchiveStoryImmediateSaver env where
is implemented already is implemented already
-} -}
newtype NodeStory s p = NodeStory { _unNodeStory :: Map NodeId (Archive s p) } newtype NodeStory s p = NodeStory { _unNodeStory :: Map NodeId (Archive s p) }
deriving (Generic, Show, Eq) deriving (Generic, Show, Eq, Semigroup)
instance (FromJSON s, FromJSON p) => FromJSON (NodeStory s p) instance (FromJSON s, FromJSON p) => FromJSON (NodeStory s p)
instance (ToJSON s, ToJSON p) => ToJSON (NodeStory s p) instance (ToJSON s, ToJSON p) => ToJSON (NodeStory s p)
...@@ -195,6 +188,7 @@ instance (Serialise s, Serialise p) => Serialise (Archive s p) ...@@ -195,6 +188,7 @@ instance (Serialise s, Serialise p) => Serialise (Archive s p)
type NodeListStory = NodeStory NgramsState' NgramsStatePatch' type NodeListStory = NodeStory NgramsState' NgramsStatePatch'
-- NOTE: 'type NgramsTableMap = Map NgramsTerm NgramsRepoElement'
type NgramsState' = Map TableNgrams.NgramsType NgramsTableMap type NgramsState' = Map TableNgrams.NgramsType NgramsTableMap
type NgramsStatePatch' = PatchMap TableNgrams.NgramsType NgramsTablePatch type NgramsStatePatch' = PatchMap TableNgrams.NgramsType NgramsTablePatch
instance Serialise NgramsStatePatch' instance Serialise NgramsStatePatch'
...@@ -381,9 +375,6 @@ getNodesArchiveHistory c nodesId = do ...@@ -381,9 +375,6 @@ getNodesArchiveHistory c nodesId = do
ORDER BY (version, node_story_archive_history.id) DESC ORDER BY (version, node_story_archive_history.id) DESC
|] |]
ngramsIdQuery :: PGS.Query
ngramsIdQuery = [sql| SELECT id FROM ngrams WHERE terms = ? |]
insertNodeArchiveHistory :: PGS.Connection -> NodeId -> Version -> [NgramsStatePatch'] -> IO () insertNodeArchiveHistory :: PGS.Connection -> NodeId -> Version -> [NgramsStatePatch'] -> IO ()
insertNodeArchiveHistory _ _ _ [] = pure () insertNodeArchiveHistory _ _ _ [] = pure ()
...@@ -392,22 +383,23 @@ insertNodeArchiveHistory c nodeId version (h:hs) = do ...@@ -392,22 +383,23 @@ insertNodeArchiveHistory c nodeId version (h:hs) = do
(\(term, p) -> (\(term, p) ->
(nodeId, nType, term, p)) <$> PM.toList patch) <$> PM.toList h :: [(NodeId, TableNgrams.NgramsType, NgramsTerm, NgramsPatch)] (nodeId, nType, term, p)) <$> PM.toList patch) <$> PM.toList h :: [(NodeId, TableNgrams.NgramsType, NgramsTerm, NgramsPatch)]
tuplesM <- mapM (\(nId, nType, term, patch) -> do tuplesM <- mapM (\(nId, nType, term, patch) -> do
ngrams <- runPGSQuery c ngramsIdQuery (PGS.Only term) [PGS.Only ngramsId] <- runPGSReturning c qInsert [PGS.Only term] :: IO [PGS.Only Int]
pure $ (\(PGS.Only termId) -> (nId, nType, termId, term, patch)) <$> (headMay ngrams) pure (nId, nType, ngramsId, term, patch)
) tuples :: IO [Maybe (NodeId, TableNgrams.NgramsType, Int, NgramsTerm, NgramsPatch)] ) tuples :: IO [(NodeId, TableNgrams.NgramsType, Int, NgramsTerm, NgramsPatch)]
_ <- runPGSExecuteMany c query $ ((\(nId, nType, termId, _term, patch) -> (nId, nType, termId, patch, version)) <$> catMaybes tuplesM) _ <- runPGSExecuteMany c query $ ((\(nId, nType, termId, _term, patch) -> (nId, nType, termId, patch, version)) <$> tuplesM)
_ <- insertNodeArchiveHistory c nodeId version hs _ <- insertNodeArchiveHistory c nodeId version hs
pure () pure ()
where where
qInsert :: PGS.Query
qInsert = [sql|INSERT INTO ngrams (terms) VALUES (?)
ON CONFLICT (terms) DO UPDATE SET terms = excluded.terms
RETURNING id|]
-- https://stackoverflow.com/questions/39224438/postgresql-insert-if-foreign-key-exists -- https://stackoverflow.com/questions/39224438/postgresql-insert-if-foreign-key-exists
query :: PGS.Query query :: PGS.Query
query = [sql| INSERT INTO node_story_archive_history(node_id, ngrams_type_id, ngrams_id, patch, version) query = [sql| INSERT INTO node_story_archive_history(node_id, ngrams_type_id, ngrams_id, patch, version)
SELECT node_id, ngrams_type_id, ngrams_id, patch::jsonb, version FROM ( VALUES (?, ?, ?, ?, ?)
VALUES (?, ?, ?, ?, ?) |]
) AS i(node_id, ngrams_type_id, ngrams_id, patch, version)
WHERE EXISTS (
SELECT * FROM nodes where nodes.id = node_id
)|]
getNodeStory :: PGS.Connection -> NodeId -> IO NodeListStory getNodeStory :: PGS.Connection -> NodeId -> IO NodeListStory
getNodeStory c nId = do getNodeStory c nId = do
...@@ -443,7 +435,8 @@ nodeStoriesQuery :: PGS.Query ...@@ -443,7 +435,8 @@ nodeStoriesQuery :: PGS.Query
nodeStoriesQuery = [sql| SELECT version, ngrams_type_id, terms, ngrams_repo_element nodeStoriesQuery = [sql| SELECT version, ngrams_type_id, terms, ngrams_repo_element
FROM node_stories FROM node_stories
JOIN ngrams ON ngrams.id = ngrams_id JOIN ngrams ON ngrams.id = ngrams_id
WHERE node_id = ? |] WHERE node_id = ?
|]
type ArchiveStateList = [(TableNgrams.NgramsType, NgramsTerm, NgramsRepoElement)] type ArchiveStateList = [(TableNgrams.NgramsType, NgramsTerm, NgramsRepoElement)]
type ArchiveStateSet = Set.Set (TableNgrams.NgramsType, NgramsTerm) type ArchiveStateSet = Set.Set (TableNgrams.NgramsType, NgramsTerm)
...@@ -467,48 +460,18 @@ archiveStateListFilterFromSet set = ...@@ -467,48 +460,18 @@ archiveStateListFilterFromSet set =
insertNodeStory :: PGS.Connection -> NodeId -> ArchiveList -> IO () insertNodeStory :: PGS.Connection -> NodeId -> ArchiveList -> IO ()
insertNodeStory c nId a = do insertNodeStory c nId a = do
insertArchiveStateList c nId (a ^. a_version) (archiveStateToList $ a ^. a_state) insertArchiveStateList c nId (a ^. a_version) (archiveStateToList $ a ^. a_state)
-- mapM_ (\(ngramsType, ngrams, ngramsRepoElement) -> do
-- [PGS.Only termId] <- runPGSReturning c qInsert [PGS.Only ngrams] :: IO [PGS.Only Int]
-- runPGSExecuteMany c query [(PGS.toField nId, a ^. a_version, ngramsType, termId, ngramsRepoElement)]) $ archiveStateToList $ a ^. a_state
-- -- runInsert c $ insert ngramsType ngrams ngramsRepoElement) $ archiveStateToList _a_state
-- where
-- qInsert :: PGS.Query
-- qInsert = [sql|INSERT INTO ngrams (terms) VALUES (?)
-- ON CONFLICT (terms) DO UPDATE SET terms = excluded.terms
-- RETURNING id|]
-- -- https://stackoverflow.com/questions/39224438/postgresql-insert-if-foreign-key-exists
-- query :: PGS.Query
-- query = [sql| INSERT INTO node_stories(node_id, ngrams_type_id, ngrams_id, ngrams_repo_element)
-- SELECT * FROM (
-- VALUES (?, ?, ?, ?)
-- ) AS i(node_id, ngrams_type_id, ngrams_id, ngrams_repo_element)
-- WHERE EXISTS (
-- SELECT * FROM nodes where nodes.id = node_id
-- )|]
-- insert ngramsType ngrams ngramsRepoElement =
-- Insert { iTable = nodeStoryTable
-- , iRows = [NodeStoryDB { node_id = sqlInt4 nId
-- , version = sqlInt4 _a_version
-- , ngrams_type_id = sqlInt4 $ TableNgrams.ngramsTypeId ngramsType
-- , ngrams_id = ...
-- , ngrams_repo_element = sqlValueJSONB ngramsRepoElement
-- }]
-- , iReturning = rCount
-- , iOnConflict = Nothing }
insertArchiveStateList :: PGS.Connection -> NodeId -> Version -> ArchiveStateList -> IO () insertArchiveStateList :: PGS.Connection -> NodeId -> Version -> ArchiveStateList -> IO ()
insertArchiveStateList c nodeId version as = do insertArchiveStateList c nodeId version as = do
mapM_ performInsert as mapM_ performInsert as
where where
performInsert (nt, n, nre) = do performInsert (ngramsType, ngrams, ngramsRepoElement) = do
_ <- tryInsertTerms n [PGS.Only ngramsId] <- tryInsertTerms ngrams
_ <- case nre ^. nre_root of _ <- case ngramsRepoElement ^. nre_root of
Nothing -> pure [] Nothing -> pure []
Just r -> tryInsertTerms r Just r -> tryInsertTerms r
mapM_ tryInsertTerms $ nre ^. nre_children mapM_ tryInsertTerms $ ngramsRepoElement ^. nre_children
runPGSExecute c query (nodeId, version, nt, nre, n) runPGSExecute c query (nodeId, ngramsId, version, ngramsType, ngramsRepoElement)
tryInsertTerms :: NgramsTerm -> IO [PGS.Only Int] tryInsertTerms :: NgramsTerm -> IO [PGS.Only Int]
tryInsertTerms t = runPGSReturning c qInsert [PGS.Only t] tryInsertTerms t = runPGSReturning c qInsert [PGS.Only t]
...@@ -519,11 +482,9 @@ insertArchiveStateList c nodeId version as = do ...@@ -519,11 +482,9 @@ insertArchiveStateList c nodeId version as = do
RETURNING id|] RETURNING id|]
query :: PGS.Query query :: PGS.Query
query = [sql| WITH s AS (SELECT ? AS sid, ? sversion, ? sngrams_type_id, ngrams.id as sngrams_id, ?::jsonb AS srepo FROM ngrams WHERE terms = ?) query = [sql|INSERT INTO node_stories(node_id, ngrams_id, version, ngrams_type_id, ngrams_repo_element)
INSERT INTO node_stories(node_id, version, ngrams_type_id, ngrams_id, ngrams_repo_element) VALUES (?, ?, ?, ?, ? :: jsonb)
SELECT s.sid, s.sversion, s.sngrams_type_id, s.sngrams_id, s.srepo |]
FROM s s JOIN nodes n ON s.sid = n.id
|]
deleteArchiveStateList :: PGS.Connection -> NodeId -> ArchiveStateList -> IO () deleteArchiveStateList :: PGS.Connection -> NodeId -> ArchiveStateList -> IO ()
deleteArchiveStateList c nodeId as = do deleteArchiveStateList c nodeId as = do
...@@ -531,19 +492,21 @@ deleteArchiveStateList c nodeId as = do ...@@ -531,19 +492,21 @@ deleteArchiveStateList c nodeId as = do
where where
query :: PGS.Query query :: PGS.Query
query = [sql| DELETE FROM node_stories query = [sql| DELETE FROM node_stories
WHERE node_id = ? AND ngrams_type_id = ? AND ngrams_id IN (SELECT id FROM ngrams WHERE terms = ?) |] WHERE node_id = ? AND ngrams_type_id = ?
AND ngrams_id IN (SELECT id FROM ngrams WHERE terms = ?)
|]
updateArchiveStateList :: PGS.Connection -> NodeId -> Version -> ArchiveStateList -> IO () updateArchiveStateList :: PGS.Connection -> NodeId -> Version -> ArchiveStateList -> IO ()
updateArchiveStateList c nodeId version as = do updateArchiveStateList c nodeId version as = do
let params = (\(nt, n, nre) -> (nre, version, nodeId, nt, n)) <$> as let params = (\(nt, n, nre) -> (nre, version, nodeId, nt, n)) <$> as
--q <- PGS.format c query params
--printDebug "[updateArchiveList] query" q
mapM_ (runPGSExecute c query) params mapM_ (runPGSExecute c query) params
where where
query :: PGS.Query query :: PGS.Query
query = [sql| UPDATE node_stories query = [sql| UPDATE node_stories
SET ngrams_repo_element = ?, version = ? SET ngrams_repo_element = ?, version = ?
WHERE node_id = ? AND ngrams_type_id = ? AND ngrams_id IN (SELECT id FROM ngrams WHERE terms = ?) |] WHERE node_id = ? AND ngrams_type_id = ?
AND ngrams_id IN (SELECT id FROM ngrams WHERE terms = ?)
|]
-- | This function updates the node story and archive for given node_id. -- | This function updates the node story and archive for given node_id.
updateNodeStory :: PGS.Connection -> NodeId -> ArchiveList -> ArchiveList -> IO () updateNodeStory :: PGS.Connection -> NodeId -> ArchiveList -> ArchiveList -> IO ()
...@@ -639,21 +602,18 @@ writeNodeStories c (NodeStory nls) = do ...@@ -639,21 +602,18 @@ writeNodeStories c (NodeStory nls) = do
mapM_ (\(nId, a) -> upsertNodeStories c nId a) $ Map.toList nls mapM_ (\(nId, a) -> upsertNodeStories c nId a) $ Map.toList nls
-- | Returns a `NodeListStory`, updating the given one for given `NodeId` -- | Returns a `NodeListStory`, updating the given one for given `NodeId`
nodeStoryInc :: PGS.Connection -> Maybe NodeListStory -> NodeId -> IO NodeListStory nodeStoryInc :: PGS.Connection -> NodeListStory -> NodeId -> IO NodeListStory
nodeStoryInc c Nothing nId = getNodeStory c nId nodeStoryInc c ns@(NodeStory nls) nId = do
nodeStoryInc c (Just ns@(NodeStory nls)) nId = do
case Map.lookup nId nls of case Map.lookup nId nls of
Nothing -> do Nothing -> getNodeStory c nId >>= pure . (ns <>)
(NodeStory nls') <- getNodeStory c nId
pure $ NodeStory $ Map.union nls nls'
Just _ -> pure ns Just _ -> pure ns
nodeStoryIncs :: PGS.Connection -> Maybe NodeListStory -> [NodeId] -> IO NodeListStory nodeStoryIncrementalRead :: PGS.Connection -> Maybe NodeListStory -> [NodeId] -> IO NodeListStory
nodeStoryIncs _ Nothing [] = pure $ NodeStory $ Map.empty nodeStoryIncrementalRead _ Nothing [] = pure $ NodeStory $ Map.empty
nodeStoryIncs c Nothing (ni:ns) = do nodeStoryIncrementalRead c Nothing (ni:ns) = do
m <- getNodeStory c ni m <- getNodeStory c ni
nodeStoryIncs c (Just m) ns nodeStoryIncrementalRead c (Just m) ns
nodeStoryIncs c (Just nls) ns = foldM (\m n -> nodeStoryInc c (Just m) n) nls ns nodeStoryIncrementalRead c (Just nls) ns = foldM (\m n -> nodeStoryInc c m n) nls ns
-- nodeStoryDec :: Pool PGS.Connection -> NodeListStory -> NodeId -> IO NodeListStory -- nodeStoryDec :: Pool PGS.Connection -> NodeListStory -> NodeId -> IO NodeListStory
-- nodeStoryDec pool ns@(NodeStory nls) ni = do -- nodeStoryDec pool ns@(NodeStory nls) ni = do
...@@ -667,29 +627,53 @@ nodeStoryIncs c (Just nls) ns = foldM (\m n -> nodeStoryInc c (Just m) n) nls ns ...@@ -667,29 +627,53 @@ nodeStoryIncs c (Just nls) ns = foldM (\m n -> nodeStoryInc c (Just m) n) nls ns
-- pure $ NodeStory ns' -- pure $ NodeStory ns'
------------------------------------ ------------------------------------
-- | NgramsRepoElement contains, in particular, `nre_list`,
-- `nre_parent` and `nre_children`. We want to make sure that all
-- children entries (i.e. ones that have `nre_parent`) have the same
-- `list` as their parent entry.
fixChildrenTermTypes :: NodeListStory -> NodeListStory
fixChildrenTermTypes (NodeStory nls) =
NodeStory $ Map.fromList [ (nId, a & a_state %~ fixChildrenInNgramsStatePatch) |
(nId, a) <- Map.toList nls ]
fixChildrenInNgramsStatePatch :: NgramsState' -> NgramsState'
fixChildrenInNgramsStatePatch ns = archiveStateFromList $ nsParents <> nsChildrenFixed
where
nls = archiveStateToList ns
nsParents = filter (\(_nt, _t, nre) -> isNothing $ nre ^. nre_parent) nls
parentNtMap = Map.fromList $ (\(_nt, t, nre) -> (t, nre ^. nre_list)) <$> nsParents
nsChildren = filter (\(_nt, _t, nre) -> isJust $ nre ^. nre_parent) nls
nsChildrenFixed = (\(nt, t, nre) ->
( nt
, t
, nre & nre_list %~
(\l -> parentNtMap ^. at (nre ^. nre_parent . _Just) . non l)
)
) <$> nsChildren
------------------------------------
fromDBNodeStoryEnv :: Pool PGS.Connection -> IO NodeStoryEnv fromDBNodeStoryEnv :: Pool PGS.Connection -> IO NodeStoryEnv
fromDBNodeStoryEnv pool = do fromDBNodeStoryEnv pool = do
tvar <- nodeStoryVar pool Nothing [] tvar <- nodeStoryVar pool Nothing []
let saver_immediate = do let saver_immediate = do
ns <- atomically $ readTVar tvar ns <- atomically $ do
ns' <- readTVar tvar
let ns'' = fixChildrenTermTypes ns'
writeTVar tvar ns''
pure ns''
withResource pool $ \c -> do withResource pool $ \c -> do
--printDebug "[mkNodeStorySaver] will call writeNodeStories, ns" ns --printDebug "[mkNodeStorySaver] will call writeNodeStories, ns" ns
writeNodeStories c ns writeNodeStories c ns
pure ()
let archive_saver_immediate ns@(NodeStory nls) = withResource pool $ \c -> do let archive_saver_immediate ns@(NodeStory nls) = withResource pool $ \c -> do
mapM_ (\(nId, a) -> do mapM_ (\(nId, a) -> do
insertNodeArchiveHistory c nId (a ^. a_version) $ reverse $ a ^. a_history insertNodeArchiveHistory c nId (a ^. a_version) $ reverse $ a ^. a_history
) $ Map.toList nls ) $ Map.toList nls
pure $ clearHistory ns pure $ clearHistory ns
-- saver <- mkNodeStorySaver saver_immediate
-- let saver = modifyMVar_ mvar $ \mv -> do
-- writeNodeStories pool mv
-- printDebug "[fromDBNodeStoryEnv] saver" mv
-- let mv' = clearHistory mv
-- printDebug "[fromDBNodeStoryEnv] saver, cleared" mv'
-- pure mv'
pure $ NodeStoryEnv { _nse_var = tvar pure $ NodeStoryEnv { _nse_var = tvar
, _nse_saver = saver_immediate
, _nse_saver_immediate = saver_immediate , _nse_saver_immediate = saver_immediate
, _nse_archive_saver_immediate = archive_saver_immediate , _nse_archive_saver_immediate = archive_saver_immediate
, _nse_getter = nodeStoryVar pool (Just tvar) , _nse_getter = nodeStoryVar pool (Just tvar)
...@@ -700,39 +684,15 @@ nodeStoryVar :: Pool PGS.Connection ...@@ -700,39 +684,15 @@ nodeStoryVar :: Pool PGS.Connection
-> [NodeId] -> [NodeId]
-> IO (TVar NodeListStory) -> IO (TVar NodeListStory)
nodeStoryVar pool Nothing nIds = do nodeStoryVar pool Nothing nIds = do
state' <- withResource pool $ \c -> nodeStoryIncs c Nothing nIds state' <- withResource pool $ \c -> nodeStoryIncrementalRead c Nothing nIds
atomically $ newTVar state' atomically $ newTVar state'
nodeStoryVar pool (Just tv) nIds = do nodeStoryVar pool (Just tv) nIds = do
nls <- atomically $ readTVar tv nls <- atomically $ readTVar tv
nls' <- withResource pool nls' <- withResource pool
$ \c -> nodeStoryIncs c (Just nls) nIds $ \c -> nodeStoryIncrementalRead c (Just nls) nIds
_ <- atomically $ writeTVar tv nls' _ <- atomically $ writeTVar tv nls'
pure tv pure tv
-- Debounce is useful since it could delay the saving to some later
-- time, asynchronously and we keep operating on memory only.
-- mkNodeStorySaver :: Pool PGS.Connection -> MVar NodeListStory -> IO (IO ())
-- mkNodeStorySaver pool mvns = do
-- mkNodeStorySaver :: IO () -> IO (IO ())
-- mkNodeStorySaver saver = mkDebounce settings
-- where
-- settings = defaultDebounceSettings
-- { debounceAction = saver
-- -- do
-- -- -- NOTE: Lock MVar first, then use resource pool.
-- -- -- Otherwise we could wait for MVar, while
-- -- -- blocking the pool connection.
-- -- modifyMVar_ mvns $ \ns -> do
-- -- withResource pool $ \c -> do
-- -- --printDebug "[mkNodeStorySaver] will call writeNodeStories, ns" ns
-- -- writeNodeStories c ns
-- -- pure $ clearHistory ns
-- --withMVar mvns (\ns -> printDebug "[mkNodeStorySaver] debounce nodestory" ns)
-- , debounceFreq = 1*minute
-- }
-- minute = 60*sec
-- sec = 10^(6 :: Int)
clearHistory :: NodeListStory -> NodeListStory clearHistory :: NodeListStory -> NodeListStory
clearHistory (NodeStory ns) = NodeStory $ ns & (traverse . a_history) .~ emptyHistory clearHistory (NodeStory ns) = NodeStory $ ns & (traverse . a_history) .~ emptyHistory
where where
...@@ -745,18 +705,6 @@ currentVersion listId = do ...@@ -745,18 +705,6 @@ currentVersion listId = do
pure $ nls ^. unNodeStory . at listId . _Just . a_version pure $ nls ^. unNodeStory . at listId . _Just . a_version
-- mkNodeStorySaver :: MVar NodeListStory -> Cmd err (Cmd err ())
-- mkNodeStorySaver mvns = mkDebounce settings
-- where
-- settings = defaultDebounceSettings
-- { debounceAction = withMVar mvns (\ns -> writeNodeStories ns)
-- , debounceFreq = 1 * minute
-- -- , debounceEdge = trailingEdge -- Trigger on the trailing edge
-- }
-- minute = 60 * second
-- second = 10^(6 :: Int)
----------------------------------------- -----------------------------------------
fixNodeStoryVersions :: (HasNodeStory env err m) => m () fixNodeStoryVersions :: (HasNodeStory env err m) => m ()
......
...@@ -69,6 +69,7 @@ tests = sequential $ aroundAll withTestDB $ describe "Database" $ do ...@@ -69,6 +69,7 @@ tests = sequential $ aroundAll withTestDB $ describe "Database" $ do
it "Can add query node story" queryNodeStoryTest it "Can add query node story" queryNodeStoryTest
it "Can add new terms to node story" insertNewTermsToNodeStoryTest it "Can add new terms to node story" insertNewTermsToNodeStoryTest
it "Can add new terms (with children) to node story" insertNewTermsWithChildrenToNodeStoryTest it "Can add new terms (with children) to node story" insertNewTermsWithChildrenToNodeStoryTest
it "Can add fix children terms to match parents" insertNodeStoryChildrenWithDifferentNgramsTypeThanParentTest
data ExpectedActual a = data ExpectedActual a =
Expected a Expected a
......
...@@ -13,13 +13,14 @@ Portability : POSIX ...@@ -13,13 +13,14 @@ Portability : POSIX
module Test.Database.Operations.NodeStory where module Test.Database.Operations.NodeStory where
import Control.Lens ((.~))
import Control.Monad.Reader import Control.Monad.Reader
import Data.Map.Strict qualified as Map import Data.Map.Strict qualified as Map
import Data.Set qualified as Set import Data.Set qualified as Set
import Database.PostgreSQL.Simple qualified as PSQL import Database.PostgreSQL.Simple qualified as PSQL
import Database.PostgreSQL.Simple.SqlQQ import Database.PostgreSQL.Simple.SqlQQ
import Gargantext.API.Ngrams (setListNgrams, saveNodeStoryImmediate) import Gargantext.API.Ngrams (setListNgrams, saveNodeStoryImmediate)
import Gargantext.API.Ngrams.Types (MSet(..), NgramsRepoElement(..), NgramsTerm(..)) import Gargantext.API.Ngrams.Types (MSet(..), NgramsRepoElement(..), NgramsTerm(..), nre_list)
import Gargantext.API.Ngrams.Tools (getNodeStoryVar) import Gargantext.API.Ngrams.Tools (getNodeStoryVar)
import Gargantext.Core.NodeStory hiding (runPGSQuery) import Gargantext.Core.NodeStory hiding (runPGSQuery)
import Gargantext.Core.Types.Individu import Gargantext.Core.Types.Individu
...@@ -78,9 +79,8 @@ queryNodeStoryTest env = do ...@@ -78,9 +79,8 @@ queryNodeStoryTest env = do
liftIO $ do liftIO $ do
ns <- atomically $ readTVar v ns <- atomically $ readTVar v
ns `shouldBe` (NodeStory $ Map.singleton listId $ Archive { _a_version = 0 ns `shouldBe` (NodeStory $ Map.singleton listId
, _a_state = Map.empty (initArchive :: ArchiveList))
, _a_history = [] })
insertNewTermsToNodeStoryTest :: TestEnv -> Assertion insertNewTermsToNodeStoryTest :: TestEnv -> Assertion
...@@ -110,9 +110,9 @@ insertNewTermsToNodeStoryTest env = do ...@@ -110,9 +110,9 @@ insertNewTermsToNodeStoryTest env = do
liftIO $ do liftIO $ do
ns <- atomically $ readTVar v ns <- atomically $ readTVar v
ns `shouldBe` (NodeStory $ Map.singleton listId $ Archive { _a_version = 0 ns `shouldBe` (NodeStory $ Map.singleton listId
, _a_state = Map.singleton NgramsTerms nls ((initArchive :: ArchiveList) & a_state .~
, _a_history = [] }) Map.singleton NgramsTerms nls))
-- check that the ngrams are in the DB as well -- check that the ngrams are in the DB as well
ngramsMap <- selectNgramsId [terms] ngramsMap <- selectNgramsId [terms]
-- saveNodeStory is called by `setListNgrams` -- saveNodeStory is called by `setListNgrams`
...@@ -159,7 +159,7 @@ insertNewTermsWithChildrenToNodeStoryTest env = do ...@@ -159,7 +159,7 @@ insertNewTermsWithChildrenToNodeStoryTest env = do
, _nre_children = MSet $ Map.singleton tChild () } , _nre_children = MSet $ Map.singleton tChild () }
let nreChild = NgramsRepoElement { _nre_size = 1 let nreChild = NgramsRepoElement { _nre_size = 1
, _nre_list = MapTerm , _nre_list = MapTerm
, _nre_root = Nothing , _nre_root = Just tParent
, _nre_parent = Just tParent , _nre_parent = Just tParent
, _nre_children = MSet Map.empty } , _nre_children = MSet Map.empty }
...@@ -168,16 +168,15 @@ insertNewTermsWithChildrenToNodeStoryTest env = do ...@@ -168,16 +168,15 @@ insertNewTermsWithChildrenToNodeStoryTest env = do
liftIO $ do liftIO $ do
ns <- atomically $ readTVar v ns <- atomically $ readTVar v
ns `shouldBe` (NodeStory $ Map.singleton listId $ Archive { _a_version = 0 ns `shouldBe` (NodeStory $ Map.singleton listId
, _a_state = Map.singleton NgramsTerms nls ((initArchive :: ArchiveList) & a_state .~
, _a_history = [] }) Map.singleton NgramsTerms nls))
-- `setListNgrams` calls saveNodeStory already so we should have -- `setListNgrams` calls saveNodeStory already so we should have
-- the terms in the DB by now -- the terms in the DB by now
ngramsMap <- selectNgramsId terms ngramsMap <- selectNgramsId terms
liftIO $ (snd <$> Map.toList ngramsMap) `shouldBe` terms liftIO $ (snd <$> Map.toList ngramsMap) `shouldBe` terms
saveNodeStoryImmediate
dbTerms <- runPGSQuery [sql| dbTerms <- runPGSQuery [sql|
SELECT terms SELECT terms
FROM ngrams FROM ngrams
...@@ -186,9 +185,6 @@ insertNewTermsWithChildrenToNodeStoryTest env = do ...@@ -186,9 +185,6 @@ insertNewTermsWithChildrenToNodeStoryTest env = do
|] (PSQL.Only listId) |] (PSQL.Only listId)
liftIO $ (Set.fromList $ (\(PSQL.Only t) -> t) <$> dbTerms) `shouldBe` (Set.fromList terms) liftIO $ (Set.fromList $ (\(PSQL.Only t) -> t) <$> dbTerms) `shouldBe` (Set.fromList terms)
ngramsMap2 <- selectNgramsId terms
liftIO $ (Set.fromList (snd <$> Map.toList ngramsMap2)) `shouldBe` (Set.fromList terms)
-- let (Just (tParentId, _)) = head $ filter ((==) (unNgramsTerm tParent) . snd) $ Map.toList ngramsMap2 -- let (Just (tParentId, _)) = head $ filter ((==) (unNgramsTerm tParent) . snd) $ Map.toList ngramsMap2
-- let (Just (tChildId, _)) = head $ filter ((==) (unNgramsTerm tChild) . snd) $ Map.toList ngramsMap2 -- let (Just (tChildId, _)) = head $ filter ((==) (unNgramsTerm tChild) . snd) $ Map.toList ngramsMap2
...@@ -197,3 +193,63 @@ insertNewTermsWithChildrenToNodeStoryTest env = do ...@@ -197,3 +193,63 @@ insertNewTermsWithChildrenToNodeStoryTest env = do
-- liftIO $ tParentId `shouldBe` tParentId' -- liftIO $ tParentId `shouldBe` tParentId'
insertNodeStoryChildrenWithDifferentNgramsTypeThanParentTest :: TestEnv -> Assertion
insertNodeStoryChildrenWithDifferentNgramsTypeThanParentTest env = do
flip runReaderT env $ runTestMonad $ do
-- NOTE(adn) We need to create user 'gargantua'(!!) in order
-- for 'addDocumentsToHyperCorpus' to work.
let user = UserName userMaster
parentId <- getRootId user
[corpus] <- getCorporaWithParentId parentId
let corpusId = _node_id corpus
userId <- getUserId user
listId <- getOrMkList corpusId userId
v <- getNodeStoryVar [listId]
let tParent = NgramsTerm "hello"
let tChild = NgramsTerm "world"
let terms = unNgramsTerm <$> [tParent, tChild]
let nreParent = NgramsRepoElement { _nre_size = 1
, _nre_list = MapTerm
, _nre_root = Nothing
, _nre_parent = Nothing
, _nre_children = MSet $ Map.singleton tChild () }
let nreChild = NgramsRepoElement { _nre_size = 1
, _nre_list = CandidateTerm
, _nre_root = Just tParent
, _nre_parent = Just tParent
, _nre_children = MSet Map.empty }
let nreChildFixedType = nreChild & nre_list .~ MapTerm
let nls = Map.fromList [(tParent, nreParent), (tChild, nreChild)]
let nlsWithChildFixed = Map.fromList [(tParent, nreParent), (tChild, nreChildFixedType)]
setListNgrams listId NgramsTerms nls
liftIO $ do
ns <- atomically $ readTVar v
ns `shouldBe` (NodeStory $ Map.singleton listId
((initArchive :: ArchiveList) & a_state .~
Map.singleton NgramsTerms nlsWithChildFixed))
ngramsMap <- selectNgramsId terms
liftIO $ (snd <$> Map.toList ngramsMap) `shouldBe` terms
dbTerms <- runPGSQuery [sql|
SELECT terms
FROM ngrams
JOIN node_stories ON ngrams.id = ngrams_id
WHERE node_id = ?
|] (PSQL.Only listId)
liftIO $ (Set.fromList $ (\(PSQL.Only t) -> t) <$> dbTerms) `shouldBe` (Set.fromList terms)
let (Just (tChildId, _)) = head $ filter ((==) (unNgramsTerm tChild) . snd) $ Map.toList ngramsMap
[PSQL.Only childType] <- runPGSQuery [sql|SELECT ngrams_repo_element->>'list'
FROM node_stories
WHERE ngrams_id = ?|] (PSQL.Only tChildId)
liftIO $ childType `shouldBe` ("MapTerm" :: Text)
...@@ -116,9 +116,6 @@ instance HasNodeStoryEnv TestEnv where ...@@ -116,9 +116,6 @@ instance HasNodeStoryEnv TestEnv where
instance HasNodeStoryVar TestEnv where instance HasNodeStoryVar TestEnv where
hasNodeStoryVar = hasNodeStory . nse_getter hasNodeStoryVar = hasNodeStory . nse_getter
instance HasNodeStorySaver TestEnv where
hasNodeStorySaver = hasNodeStory . nse_saver
instance HasNodeStoryImmediateSaver TestEnv where instance HasNodeStoryImmediateSaver TestEnv where
hasNodeStoryImmediateSaver = hasNodeStory . nse_saver_immediate hasNodeStoryImmediateSaver = hasNodeStory . nse_saver_immediate
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment