Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
haskell-gargantext
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
195
Issues
195
List
Board
Labels
Milestones
Merge Requests
12
Merge Requests
12
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
gargantext
haskell-gargantext
Commits
1b2ff615
Commit
1b2ff615
authored
Jul 07, 2022
by
Przemyslaw Kaminski
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[nodeStories] node stories in db work now
parent
d7ca3aee
Pipeline
#3009
failed with stage
in 53 minutes and 55 seconds
Changes
9
Pipelines
1
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
459 additions
and
376 deletions
+459
-376
gargantext.cabal
gargantext.cabal
+1
-1
Settings.hs
src/Gargantext/API/Admin/Settings.hs
+3
-2
Dev.hs
src/Gargantext/API/Dev.hs
+4
-3
Ngrams.hs
src/Gargantext/API/Ngrams.hs
+4
-2
Tools.hs
src/Gargantext/API/Ngrams/Tools.hs
+19
-1
NodeStory.hs
src/Gargantext/Core/NodeStory.hs
+217
-182
NodeStoryFile.hs
src/Gargantext/Core/NodeStoryFile.hs
+210
-0
LegacyMain.hs
src/Gargantext/Core/Viz/Phylo/Legacy/LegacyMain.hs
+1
-0
NodeStory.hs
src/Gargantext/Database/NodeStory.hs
+0
-185
No files found.
gargantext.cabal
View file @
1b2ff615
...
...
@@ -161,6 +161,7 @@ library
Gargantext.Core.Methods.Graph.BAC.Proxemy
Gargantext.Core.Methods.Graph.MaxClique
Gargantext.Core.Methods.Matrix.Accelerate.Utils
Gargantext.Core.NodeStoryFile
Gargantext.Core.Statistics
Gargantext.Core.Text.Convert
Gargantext.Core.Text.Corpus.API.Arxiv
...
...
@@ -269,7 +270,6 @@ library
Gargantext.Database.Admin.Types.Hyperdata.User
Gargantext.Database.Admin.Types.Metrics
Gargantext.Database.GargDB
Gargantext.Database.NodeStory
Gargantext.Database.Query
Gargantext.Database.Query.Facet
Gargantext.Database.Query.Filter
...
...
src/Gargantext/API/Admin/Settings.hs
View file @
1b2ff615
...
...
@@ -27,7 +27,7 @@ import Data.Maybe (fromMaybe)
import
Data.Pool
(
Pool
,
createPool
)
import
Database.PostgreSQL.Simple
(
Connection
,
connect
,
close
,
ConnectInfo
)
import
Gargantext.Core.NodeStory
import
Gargantext.Prelude.Config
(
GargConfig
(
..
),
{-gc_repofilepath,-}
readConfig
)
import
Gargantext.Prelude.Config
(
{-GargConfig(..),-}
{-gc_repofilepath,-}
readConfig
)
import
Network.HTTP.Client.TLS
(
newTlsManager
)
import
Servant.Auth.Server
(
defaultJWTSettings
,
CookieSettings
(
..
),
XsrfCookieSettings
(
..
),
defaultCookieSettings
,
defaultXsrfCookieSettings
,
readKey
,
writeKey
)
import
Servant.Client
(
parseBaseUrl
)
...
...
@@ -180,7 +180,8 @@ newEnv port file = do
self_url_env
<-
parseBaseUrl
$
"http://0.0.0.0:"
<>
show
port
dbParam
<-
databaseParameters
file
pool
<-
newPool
dbParam
nodeStory_env
<-
readNodeStoryEnv
(
_gc_repofilepath
config_env
)
--nodeStory_env <- readNodeStoryEnv (_gc_repofilepath config_env)
nodeStory_env
<-
readNodeStoryEnv
pool
scrapers_env
<-
newJobEnv
defaultSettings
manager_env
logger
<-
newStderrLoggerSet
defaultBufSize
config_mail
<-
Mail
.
readConfig
file
...
...
src/Gargantext/API/Dev.hs
View file @
1b2ff615
...
...
@@ -22,7 +22,7 @@ import Gargantext.API.Prelude
import
Gargantext.Core.NodeStory
import
Gargantext.Database.Prelude
import
Gargantext.Prelude
import
Gargantext.Prelude.Config
(
GargConfig
(
..
),
readConfig
)
import
Gargantext.Prelude.Config
(
readConfig
)
import
qualified
Gargantext.Prelude.Mail
as
Mail
import
Servant
import
System.IO
(
FilePath
)
...
...
@@ -38,8 +38,9 @@ withDevEnv iniPath k = do
newDevEnv
=
do
cfg
<-
readConfig
iniPath
dbParam
<-
databaseParameters
iniPath
nodeStory_env
<-
readNodeStoryEnv
(
_gc_repofilepath
cfg
)
--
nodeStory_env <- readNodeStoryEnv (_gc_repofilepath cfg)
pool
<-
newPool
dbParam
nodeStory_env
<-
readNodeStoryEnv
pool
setts
<-
devSettings
devJwkFile
mail
<-
Mail
.
readConfig
iniPath
pure
$
DevEnv
...
...
@@ -61,7 +62,7 @@ runCmdReplServantErr = runCmdRepl
-- the command.
-- This function is constrained to the DevEnv rather than
-- using HasConnectionPool and HasRepoVar.
runCmdDev
::
(
Show
err
)
=>
DevEnv
->
Cmd''
DevEnv
err
a
->
IO
a
runCmdDev
::
Show
err
=>
DevEnv
->
Cmd''
DevEnv
err
a
->
IO
a
runCmdDev
env
f
=
(
either
(
fail
.
show
)
pure
=<<
runCmd
env
f
)
`
finally
`
...
...
src/Gargantext/API/Ngrams.hs
View file @
1b2ff615
...
...
@@ -106,7 +106,7 @@ import Gargantext.Database.Action.Flow.Types
import
Gargantext.Database.Action.Metrics.NgramsByContext
(
getOccByNgramsOnlyFast'
)
import
Gargantext.Database.Admin.Config
(
userMaster
)
import
Gargantext.Database.Admin.Types.Node
(
NodeType
(
..
))
import
Gargantext.Database.Prelude
(
HasConnectionPool
,
HasConfig
)
import
Gargantext.Database.Prelude
(
HasConnectionPool
(
..
)
,
HasConfig
)
import
Gargantext.Database.Query.Table.Ngrams
hiding
(
NgramsType
(
..
),
ngramsType
,
ngrams_terms
)
import
Gargantext.Database.Query.Table.Node
(
getNode
)
import
Gargantext.Database.Query.Table.Node.Error
(
HasNodeError
)
...
...
@@ -261,7 +261,9 @@ setListNgrams listId ngramsType ns = do
currentVersion
::
HasNodeStory
env
err
m
=>
ListId
->
m
Version
currentVersion
listId
=
do
nls
<-
getRepo
[
listId
]
--nls <- getRepo [listId]
pool
<-
view
connPool
nls
<-
liftBase
$
getNodeStory
pool
listId
pure
$
nls
^.
unNodeStory
.
at
listId
.
_Just
.
a_version
...
...
src/Gargantext/API/Ngrams/Tools.hs
View file @
1b2ff615
...
...
@@ -22,7 +22,8 @@ import Data.Hashable (Hashable)
import
Data.Set
(
Set
)
import
Data.Validity
import
Gargantext.API.Ngrams.Types
import
Gargantext.Core.Types
(
ListType
(
..
),
NodeId
,
ListId
)
import
Gargantext.Core.Types
(
ListType
(
..
),
NodeId
,
NodeType
(
..
),
ListId
)
import
Gargantext.Database.Prelude
(
CmdM
,
HasConnectionPool
(
..
))
import
Gargantext.Database.Schema.Ngrams
(
NgramsType
)
import
Gargantext.Prelude
import
qualified
Data.HashMap.Strict
as
HM
...
...
@@ -30,6 +31,7 @@ import qualified Data.Map.Strict as Map
import
qualified
Data.Set
as
Set
import
Gargantext.Core.NodeStory
mergeNgramsElement
::
NgramsRepoElement
->
NgramsRepoElement
->
NgramsRepoElement
mergeNgramsElement
_neOld
neNew
=
neNew
...
...
@@ -193,3 +195,19 @@ getCoocByNgrams' f (Diagonal diag) m =
where
ks
=
HM
.
keys
m
------------------------------------------
migrateFromDirToDb
::
(
CmdM
env
err
m
,
HasNodeStory
env
err
m
)
=>
m
()
migrateFromDirToDb
=
do
pool
<-
view
connPool
listIds
<-
liftBase
$
getNodesIdWithType
pool
NodeList
(
NodeStory
nls
)
<-
getRepo
listIds
_
<-
mapM
(
\
(
nId
,
a
)
->
do
n
<-
liftBase
$
nodeExists
pool
nId
case
n
of
False
->
pure
0
True
->
liftBase
$
upsertNodeArchive
pool
nId
a
)
$
Map
.
toList
nls
--
_
<-
nodeStoryIncs
(
Just
$
NodeStory
nls
)
listIds
pure
()
src/Gargantext/Core/NodeStory.hs
View file @
1b2ff615
This diff is collapsed.
Click to expand it.
src/Gargantext/Core/NodeStoryFile.hs
0 → 100644
View file @
1b2ff615
{- NOTE This is legacy code. It keeps node stories in a directory
repo. We now have migrated to the DB. However this code is needed to
make the migration (see Gargantext.API.Ngrams.Tools) -}
module
Gargantext.Core.NodeStoryFile
where
import
Control.Lens
(
view
)
import
Control.Monad
(
foldM
)
import
Codec.Serialise
(
serialise
,
deserialise
)
import
Codec.Serialise.Class
import
Control.Concurrent
(
MVar
(),
modifyMVar_
,
newMVar
,
readMVar
,
withMVar
)
import
Control.Debounce
(
mkDebounce
,
defaultDebounceSettings
,
debounceFreq
,
debounceAction
)
import
Gargantext.Core.NodeStory
import
Gargantext.Core.Types
(
ListId
,
NodeId
(
..
))
import
Gargantext.Prelude
import
System.Directory
(
renameFile
,
createDirectoryIfMissing
,
doesFileExist
,
removeFile
)
import
System.IO
(
FilePath
,
hClose
)
import
System.IO.Temp
(
withTempFile
)
import
qualified
Data.ByteString.Lazy
as
DBL
import
qualified
Data.List
as
List
import
qualified
Data.Map.Strict
as
Map
import
qualified
Gargantext.Database.Query.Table.Ngrams
as
TableNgrams
getRepo
::
HasNodeStory
env
err
m
=>
[
ListId
]
->
m
NodeListStory
getRepo
listIds
=
do
f
<-
getNodeListStory
v
<-
liftBase
$
f
listIds
v'
<-
liftBase
$
readMVar
v
pure
$
v'
getNodeListStory
::
HasNodeStory
env
err
m
=>
m
([
NodeId
]
->
IO
(
MVar
NodeListStory
))
getNodeListStory
=
do
env
<-
view
hasNodeStory
pure
$
view
nse_getter
env
readNodeStoryEnv
::
NodeStoryDir
->
IO
NodeStoryEnv
readNodeStoryEnv
nsd
=
do
mvar
<-
nodeStoryVar
nsd
Nothing
[]
saver
<-
mkNodeStorySaver
nsd
mvar
pure
$
NodeStoryEnv
{
_nse_var
=
mvar
,
_nse_saver
=
saver
,
_nse_getter
=
nodeStoryVar
nsd
(
Just
mvar
)
}
------------------------------------------------------------------------
mkNodeStorySaver
::
NodeStoryDir
->
MVar
NodeListStory
->
IO
(
IO
()
)
mkNodeStorySaver
nsd
mvns
=
mkDebounce
settings
where
settings
=
defaultDebounceSettings
{
debounceAction
=
withMVar
mvns
(
writeNodeStories
nsd
)
,
debounceFreq
=
1
*
minute
-- , debounceEdge = trailingEdge -- Trigger on the trailing edge
}
minute
=
60
*
second
second
=
10
^
(
6
::
Int
)
nodeStoryVar
::
NodeStoryDir
->
Maybe
(
MVar
NodeListStory
)
->
[
NodeId
]
->
IO
(
MVar
NodeListStory
)
nodeStoryVar
nsd
Nothing
ni
=
nodeStoryIncs
nsd
Nothing
ni
>>=
newMVar
nodeStoryVar
nsd
(
Just
mv
)
ni
=
do
_
<-
modifyMVar_
mv
$
\
mv'
->
(
nodeStoryIncs
nsd
(
Just
mv'
)
ni
)
pure
mv
nodeStoryInc
::
NodeStoryDir
->
Maybe
NodeListStory
->
NodeId
->
IO
NodeListStory
nodeStoryInc
nsd
(
Just
ns
@
(
NodeStory
nls
))
ni
=
do
case
Map
.
lookup
ni
nls
of
Nothing
->
do
(
NodeStory
nls'
)
<-
nodeStoryRead
nsd
ni
pure
$
NodeStory
$
Map
.
union
nls
nls'
Just
_
->
pure
ns
nodeStoryInc
nsd
Nothing
ni
=
nodeStoryRead
nsd
ni
nodeStoryIncs
::
NodeStoryDir
->
Maybe
NodeListStory
->
[
NodeId
]
->
IO
NodeListStory
nodeStoryIncs
_
Nothing
[]
=
pure
$
NodeStory
$
Map
.
empty
nodeStoryIncs
nsd
(
Just
nls
)
ns
=
foldM
(
\
m
n
->
nodeStoryInc
nsd
(
Just
m
)
n
)
nls
ns
nodeStoryIncs
nsd
Nothing
(
ni
:
ns
)
=
do
m
<-
nodeStoryRead
nsd
ni
nodeStoryIncs
nsd
(
Just
m
)
ns
nodeStoryDec
::
NodeStoryDir
->
NodeListStory
->
NodeId
->
IO
NodeListStory
nodeStoryDec
nsd
ns
@
(
NodeStory
nls
)
ni
=
do
case
Map
.
lookup
ni
nls
of
Nothing
->
do
-- we make sure the corresponding file repo is really removed
_
<-
nodeStoryRemove
nsd
ni
pure
ns
Just
_
->
do
let
ns'
=
Map
.
filterWithKey
(
\
k
_v
->
k
/=
ni
)
nls
_
<-
nodeStoryRemove
nsd
ni
pure
$
NodeStory
ns'
-- | TODO lock
nodeStoryRead
::
NodeStoryDir
->
NodeId
->
IO
NodeListStory
nodeStoryRead
nsd
ni
=
do
_repoDir
<-
createDirectoryIfMissing
True
nsd
let
nsp
=
nodeStoryPath
nsd
ni
exists
<-
doesFileExist
nsp
if
exists
then
deserialise
<$>
DBL
.
readFile
nsp
else
pure
(
initNodeStory
ni
)
nodeStoryRemove
::
NodeStoryDir
->
NodeId
->
IO
()
nodeStoryRemove
nsd
ni
=
do
let
nsp
=
nodeStoryPath
nsd
ni
exists
<-
doesFileExist
nsp
if
exists
then
removeFile
nsp
else
pure
()
nodeStoryRead_test
::
NodeStoryDir
->
NodeId
->
IO
(
Maybe
[
TableNgrams
.
NgramsType
])
nodeStoryRead_test
nsd
ni
=
nodeStoryRead
nsd
ni
>>=
\
n
->
pure
$
fmap
Map
.
keys
$
fmap
_a_state
$
Map
.
lookup
ni
$
_unNodeStory
n
------------------------------------------------------------------------
type
NodeStoryDir
=
FilePath
writeNodeStories
::
NodeStoryDir
->
NodeListStory
->
IO
()
writeNodeStories
fp
nls
=
do
_done
<-
mapM
(
writeNodeStory
fp
)
$
splitByNode
nls
-- printDebug "[writeNodeStories]" done
pure
()
writeNodeStory
::
NodeStoryDir
->
(
NodeId
,
NodeListStory
)
->
IO
()
writeNodeStory
rdfp
(
n
,
ns
)
=
saverAction'
rdfp
n
ns
splitByNode
::
NodeListStory
->
[(
NodeId
,
NodeListStory
)]
splitByNode
(
NodeStory
m
)
=
List
.
map
(
\
(
n
,
a
)
->
(
n
,
NodeStory
$
Map
.
singleton
n
a
))
$
Map
.
toList
m
saverAction'
::
Serialise
a
=>
NodeStoryDir
->
NodeId
->
a
->
IO
()
saverAction'
repoDir
nId
a
=
do
withTempFile
repoDir
((
cs
$
show
nId
)
<>
"-tmp-repo.cbor"
)
$
\
fp
h
->
do
-- printDebug "[repoSaverAction]" fp
DBL
.
hPut
h
$
serialise
a
hClose
h
renameFile
fp
(
nodeStoryPath
repoDir
nId
)
nodeStoryPath
::
NodeStoryDir
->
NodeId
->
FilePath
nodeStoryPath
repoDir
nId
=
repoDir
<>
"/"
<>
filename
where
filename
=
"repo"
<>
"-"
<>
(
cs
$
show
nId
)
<>
".cbor"
------------------------------------------------------------------------
-- TODO : repo Migration TODO TESTS
{-
repoMigration :: NodeStoryDir -> NgramsRepo -> IO ()
repoMigration fp r = writeNodeStories fp (repoToNodeListStory r)
repoToNodeListStory :: NgramsRepo -> NodeListStory
repoToNodeListStory (Repo _v s h) = NodeStory $ Map.fromList ns
where
s' = ngramsState_migration s
h' = ngramsStatePatch_migration h
ns = List.map (\(n,ns')
-> (n, let hs = fromMaybe [] (Map.lookup n h') in
Archive { _a_version = List.length hs
, _a_state = ns'
, _a_history = hs }
)
) $ Map.toList s'
ngramsState_migration :: NgramsState
-> Map NodeId NgramsState'
ngramsState_migration ns =
Map.fromListWith (Map.union) $
List.concat $
map (\(nt, nTable)
-> map (\(nid, table)
-> (nid, Map.singleton nt table)
) $ Map.toList nTable
) $ Map.toList ns
ngramsStatePatch_migration :: [NgramsStatePatch]
-> Map NodeId [NgramsStatePatch']
ngramsStatePatch_migration np' = Map.fromListWith (<>)
$ List.concat
$ map toPatch np'
where
toPatch :: NgramsStatePatch -> [(NodeId, [NgramsStatePatch'])]
toPatch p =
List.concat $
map (\(nt, nTable)
-> map (\(nid, table)
-> (nid, [fst $ Patch.singleton nt table])
) $ Patch.toList nTable
) $ Patch.toList p
-}
src/Gargantext/Core/Viz/Phylo/Legacy/LegacyMain.hs
View file @
1b2ff615
...
...
@@ -9,6 +9,7 @@ Portability : POSIX
-}
{-# LANGUAGE MonoLocalBinds #-}
{-# LANGUAGE ViewPatterns #-}
module
Gargantext.Core.Viz.Phylo.Legacy.LegacyMain
...
...
src/Gargantext/Database/NodeStory.hs
deleted
100644 → 0
View file @
d7ca3aee
{-# LANGUAGE Arrows #-}
{-# LANGUAGE TemplateHaskell #-}
module
Gargantext.Database.NodeStory
where
import
Control.Arrow
(
returnA
)
import
Control.Concurrent.MVar.Lifted
(
MVar
(),
withMVar
,
newMVar
,
modifyMVar_
)
--import Control.Debounce (mkDebounce, defaultDebounceSettings, debounceFreq, debounceAction)
import
Control.Monad
(
foldM
)
import
qualified
Data.Map.Strict
as
Map
import
Data.Profunctor.Product.TH
(
makeAdaptorAndInstance
)
import
Gargantext.API.Ngrams.Tools
(
getRepo
)
import
Gargantext.Core
(
HasDBid
)
import
Gargantext.Core.Mail.Types
(
HasMail
)
import
Gargantext.Core.NodeStory
(
Archive
(
..
),
NodeStory
(
..
),
NodeListStory
,
NgramsState
'
,
NgramsStatePatch
'
)
import
qualified
Gargantext.Core.NodeStory
as
NS
import
Gargantext.Core.Types
(
NodeId
(
..
),
NodeType
(
..
))
import
Gargantext.Database.Prelude
(
CmdM
,
mkCmd
,
runOpaQuery
)
import
Gargantext.Database.Query.Table.Node
(
getNodesIdWithType
,
nodeExists
)
import
Gargantext.Database.Query.Table.Node.Error
(
HasNodeError
)
import
Gargantext.Prelude
import
Opaleye
hiding
(
FromField
)
import
Opaleye.Internal.Table
(
Table
(
..
))
data
NodeStoryPoly
a
b
=
NodeStoryDB
{
node_id
::
a
,
archive
::
b
}
deriving
(
Eq
)
type
ArchiveQ
=
Archive
NgramsState'
NgramsStatePatch'
type
NodeListStoryQ
=
NodeStoryPoly
Int
ArchiveQ
type
NodeStoryWrite
=
NodeStoryPoly
(
Column
SqlInt4
)
(
Column
SqlJsonb
)
type
NodeStoryRead
=
NodeStoryPoly
(
Column
SqlInt4
)
(
Column
SqlJsonb
)
$
(
makeAdaptorAndInstance
"pNodeStory"
''
N
odeStoryPoly
)
nodeStoryTable
::
Table
NodeStoryRead
NodeStoryWrite
nodeStoryTable
=
Table
"node_stories"
(
pNodeStory
NodeStoryDB
{
node_id
=
tableField
"node_id"
,
archive
=
tableField
"archive"
}
)
nodeStorySelect
::
Select
NodeStoryRead
nodeStorySelect
=
selectTable
nodeStoryTable
getNodeStory
::
CmdM
env
err
m
=>
NodeId
->
m
NodeListStory
getNodeStory
(
NodeId
nodeId
)
=
do
res
<-
runOpaQuery
query
pure
$
NodeStory
$
Map
.
fromListWith
(
<>
)
$
(
\
(
NodeStoryDB
nId
a
)
->
(
nId
,
a
))
<$>
res
where
query
::
Select
NodeStoryRead
query
=
proc
()
->
do
row
@
(
NodeStoryDB
node_id
_
)
<-
nodeStorySelect
-<
()
restrict
-<
node_id
.==
sqlInt4
nodeId
returnA
-<
row
insertNodeArchive
::
CmdM
env
err
m
=>
NodeId
->
ArchiveQ
->
m
Int64
insertNodeArchive
(
NodeId
nId
)
a
=
mkCmd
$
\
c
->
runInsert
c
insert
where
insert
=
Insert
{
iTable
=
nodeStoryTable
,
iRows
=
[
NodeStoryDB
{
node_id
=
sqlInt4
nId
,
archive
=
sqlValueJSONB
a
}]
,
iReturning
=
rCount
,
iOnConflict
=
Nothing
}
updateNodeArchive
::
CmdM
env
err
m
=>
NodeId
->
ArchiveQ
->
m
Int64
updateNodeArchive
(
NodeId
nId
)
a
=
mkCmd
$
\
c
->
runUpdate
c
update
where
update
=
Update
{
uTable
=
nodeStoryTable
,
uUpdateWith
=
updateEasy
(
\
(
NodeStoryDB
{
..
})
->
NodeStoryDB
{
archive
=
sqlValueJSONB
a
,
..
})
,
uWhere
=
(
\
row
->
node_id
row
.==
sqlInt4
nId
)
,
uReturning
=
rCount
}
nodeStoryRemove
::
CmdM
env
err
m
=>
NodeId
->
m
Int64
nodeStoryRemove
(
NodeId
nId
)
=
mkCmd
$
\
c
->
runDelete
c
delete
where
delete
=
Delete
{
dTable
=
nodeStoryTable
,
dWhere
=
(
\
row
->
node_id
row
.==
sqlInt4
nId
)
,
dReturning
=
rCount
}
upsertNodeArchive
::
CmdM
env
err
m
=>
NodeId
->
ArchiveQ
->
m
Int64
upsertNodeArchive
nId
a
=
do
(
NodeStory
m
)
<-
getNodeStory
nId
case
Map
.
lookup
nId
m
of
Nothing
->
insertNodeArchive
nId
a
Just
_
->
updateNodeArchive
nId
a
writeNodeStories
::
CmdM
env
err
m
=>
NodeListStory
->
m
()
writeNodeStories
(
NodeStory
nls
)
=
do
_
<-
mapM
(
\
(
nId
,
a
)
->
upsertNodeArchive
nId
a
)
$
Map
.
toList
nls
pure
()
-- | Returns a `NodeListStory`, updating the given one for given `NodeId`
nodeStoryInc
::
CmdM
env
err
m
=>
Maybe
NodeListStory
->
NodeId
->
m
NodeListStory
nodeStoryInc
Nothing
nId
=
getNodeStory
nId
nodeStoryInc
(
Just
ns
@
(
NodeStory
nls
))
nId
=
do
case
Map
.
lookup
nId
nls
of
Nothing
->
do
(
NodeStory
nls'
)
<-
getNodeStory
nId
pure
$
NodeStory
$
Map
.
union
nls
nls'
Just
_
->
pure
ns
nodeStoryIncs
::
CmdM
env
err
m
=>
Maybe
NodeListStory
->
[
NodeId
]
->
m
NodeListStory
nodeStoryIncs
Nothing
[]
=
pure
$
NodeStory
$
Map
.
empty
nodeStoryIncs
(
Just
nls
)
ns
=
foldM
(
\
m
n
->
nodeStoryInc
(
Just
m
)
n
)
nls
ns
nodeStoryIncs
Nothing
(
ni
:
ns
)
=
do
m
<-
getNodeStory
ni
nodeStoryIncs
(
Just
m
)
ns
nodeStoryDec
::
CmdM
env
err
m
=>
NodeListStory
->
NodeId
->
m
NodeListStory
nodeStoryDec
ns
@
(
NodeStory
nls
)
ni
=
do
case
Map
.
lookup
ni
nls
of
Nothing
->
do
_
<-
nodeStoryRemove
ni
pure
ns
Just
_
->
do
let
ns'
=
Map
.
filterWithKey
(
\
k
_v
->
k
/=
ni
)
nls
_
<-
nodeStoryRemove
ni
pure
$
NodeStory
ns'
migrateFromDir
::
(
HasMail
env
,
HasNodeError
err
,
NS
.
HasNodeStory
env
err
m
,
HasDBid
NodeType
)
=>
m
()
migrateFromDir
=
do
listIds
<-
getNodesIdWithType
NodeList
(
NodeStory
nls
)
<-
getRepo
listIds
_
<-
mapM
(
\
(
nId
,
a
)
->
do
n
<-
nodeExists
nId
case
n
of
False
->
pure
0
True
->
upsertNodeArchive
nId
a
)
$
Map
.
toList
nls
--
_
<-
nodeStoryIncs
(
Just
$
NodeStory
nls
)
listIds
pure
()
------------------------------------
data
NodeStoryEnv
env
err
m
=
NodeStoryEnv
{
_nse_var
::
!
(
MVar
NodeListStory
)
,
_nse_saver
::
!
(
m
()
)
,
_nse_getter
::
[
NodeId
]
->
m
(
MVar
NodeListStory
)
--, _nse_cleaner :: !(IO ()) -- every 12 hours: cleans the repos of unused NodeStories
-- , _nse_lock :: !FileLock -- TODO (it depends on the option: if with database or file only)
}
--deriving (Generic)
nodeStoryEnv
::
CmdM
env
err
m
=>
m
(
NodeStoryEnv
env
err
m
)
nodeStoryEnv
=
do
mvar
<-
nodeStoryVar
Nothing
[]
--saver <- mkNodeStorySaver mvar
let
saver
=
mkNodeStorySaver
mvar
-- let saver = modifyMVar_ mvar $ \mv' -> do
-- writeNodeStories mv'
-- return mv'
pure
$
NodeStoryEnv
{
_nse_var
=
mvar
,
_nse_saver
=
saver
,
_nse_getter
=
nodeStoryVar
(
Just
mvar
)
}
nodeStoryVar
::
CmdM
env
err
m
=>
Maybe
(
MVar
NodeListStory
)
->
[
NodeId
]
->
m
(
MVar
NodeListStory
)
nodeStoryVar
Nothing
nIds
=
do
state
<-
nodeStoryIncs
Nothing
nIds
newMVar
state
nodeStoryVar
(
Just
mv
)
nIds
=
do
_
<-
modifyMVar_
mv
$
\
nsl
->
(
nodeStoryIncs
(
Just
nsl
)
nIds
)
pure
mv
-- TODO No debounce since this is IO stuff.
-- debounce is useful since it could delay the saving to some later
-- time, asynchronously and we keep operating on memory only.
mkNodeStorySaver
::
CmdM
env
err
m
=>
MVar
NodeListStory
->
m
()
mkNodeStorySaver
mvns
=
withMVar
mvns
writeNodeStories
-- 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)
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment