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
157
Issues
157
List
Board
Labels
Milestones
Merge Requests
9
Merge Requests
9
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
02e63fe4
Commit
02e63fe4
authored
Oct 10, 2024
by
Alexandre Delanoë
Browse files
Options
Browse Files
Download
Plain Diff
[FIX] conflicts
parents
6f91bebf
a81bb4ef
Pipeline
#6818
failed with stages
in 17 minutes and 47 seconds
Changes
37
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
37 changed files
with
1025 additions
and
201 deletions
+1025
-201
README.md
README.md
+65
-2
Import.hs
bin/gargantext-cli/CLI/Import.hs
+1
-1
Ini.hs
bin/gargantext-cli/CLI/Ini.hs
+14
-4
Types.hs
bin/gargantext-cli/CLI/Types.hs
+8
-0
Worker.hs
bin/gargantext-cli/CLI/Worker.hs
+79
-0
Main.hs
bin/gargantext-cli/Main.hs
+5
-1
update-project-dependencies
bin/update-project-dependencies
+2
-2
cabal.project
cabal.project
+14
-2
cabal.project.freeze
cabal.project.freeze
+17
-1
gargantext-settings.toml_toModify
gargantext-settings.toml_toModify
+22
-0
gargantext.cabal
gargantext.cabal
+12
-0
Auth.hs
src/Gargantext/API/Admin/Auth.hs
+8
-27
Types.hs
src/Gargantext/API/Admin/Auth/Types.hs
+4
-4
EnvTypes.hs
src/Gargantext/API/Admin/EnvTypes.hs
+61
-12
TOML.hs
src/Gargantext/API/Admin/Settings/TOML.hs
+55
-0
GraphQL.hs
src/Gargantext/API/GraphQL.hs
+2
-2
New.hs
src/Gargantext/API/Node/New.hs
+57
-27
Types.hs
src/Gargantext/API/Node/New/Types.hs
+13
-3
Routes.hs
src/Gargantext/API/Routes.hs
+16
-14
Config.hs
src/Gargantext/Core/Config.hs
+6
-0
Worker.hs
src/Gargantext/Core/Config/Worker.hs
+86
-0
Individu.hs
src/Gargantext/Core/Types/Individu.hs
+1
-0
Worker.hs
src/Gargantext/Core/Worker.hs
+115
-0
Broker.hs
src/Gargantext/Core/Worker/Broker.hs
+37
-0
Env.hs
src/Gargantext/Core/Worker/Env.hs
+2
-9
Jobs.hs
src/Gargantext/Core/Worker/Jobs.hs
+20
-24
Types.hs
src/Gargantext/Core/Worker/Jobs/Types.hs
+90
-0
Update.hs
src/Gargantext/Database/Query/Table/Node/Update.hs
+1
-1
Jobs.hs
src/Gargantext/Utils/Jobs.hs
+20
-39
Internal.hs
src/Gargantext/Utils/Jobs/Internal.hs
+12
-0
stack.yaml
stack.yaml
+18
-0
test_config.toml
test-data/test_config.toml
+12
-0
Worker.hs
test/Test/Core/Worker.hs
+29
-0
Instances.hs
test/Test/Instances.hs
+105
-3
Types.hs
test/Test/Parsers/Types.hs
+1
-22
Jobs.hs
test/Test/Utils/Jobs.hs
+12
-1
Main.hs
test/drivers/tasty/Main.hs
+3
-0
No files found.
README.md
View file @
02e63fe4
...
@@ -410,8 +410,6 @@ $ ALTER ROLE gargantua PASSWORD 'yourPasswordIn_gargantext-settings.toml'
...
@@ -410,8 +410,6 @@ $ ALTER ROLE gargantua PASSWORD 'yourPasswordIn_gargantext-settings.toml'
```
```
Maybe you need to change the port to 5433 for database connection in your gargantext.ini file.
Maybe you need to change the port to 5433 for database connection in your gargantext.ini file.
## `haskell-language-server`
## `haskell-language-server`
If you want to use
`haskell-language-server`
for GHC 9.4.7, install it
If you want to use
`haskell-language-server`
for GHC 9.4.7, install it
...
@@ -420,3 +418,68 @@ with `ghcup`:
...
@@ -420,3 +418,68 @@ with `ghcup`:
ghcup compile hls
--version
2.7.0.0
--ghc
9.4.7
ghcup compile hls
--version
2.7.0.0
--ghc
9.4.7
```
```
https://haskell-language-server.readthedocs.io/en/latest/installation.html
https://haskell-language-server.readthedocs.io/en/latest/installation.html
# Async workers
Async workers allow us to accept long-running jobs and execute them
asynchronously. Workers can be spawned on multiple machines, which
allows for scaling.
To run the worker, follow these steps:
-
start a PostgreSQL DB, usually the one with Gargantext DB is enough
-
`"simple"`
worker definition is in
`gargantext-settings.toml`
-
run worker:
`cabal v2-run gargantext-cli -- worker --name simple`
When running the worker for the first time (or sending a job), best
attempt is made to ensure the DB exists (if not, we will try to create
it) and the
`pgmq`
schema is initialized. This allows for hassle-free
maintenance and easier onboarding.
The project that we base our worker is
[
haskell-bee
](
https://gitlab.iscpif.fr/gargantext/haskell-bee/
)
. It's
a more generic framework for managing asynchronous workers, supporting
different brokers. Here, we decided to use
`pgmq`
because we already
have PostgreSQL deployed.
## Design
Thanks to the fact that we already use
`Servant.Jobs`
(which executes
the jobs in the gargantext-API process), we can migrate our jobs more
easily to a different backend.
All job definitions are in
`G.A.A.EnvTypes`
under
`GargJob`
datatype. However, because of a bit different design, the contsructors
for this datatype are empty, without their respective arguments.
Hence, I created
`G.C.W.J.Types`
with the
`Job`
datatype. Hopefully,
in the future, we can replace
`GargJob`
with this datatype.
If you want to add a new job, just add a new constructor to
`Job`
(with all the arguments this job needs), implement to/from JSON
serialization (so we can send and read that job via the broker) and
implement appropriate handler in
`G.C.Worker`
->
`performAction`
.
## No storage backend
When you compare
`haskell-bee`
with the
[
celery
project](https://docs.celeryq.dev/en/stable/), you can notice 2
things:
-
both have configurable brokers
-
`haskell-bee`
doesn't have a storage backend This is because, when
analyzing our tasks, we actually don't store any
**task**
results
anywhere. The progress can be reported immediately via notifications,
same for errors. And when a task is executed (e.g. add to corpus with
query), the garg db state is mutated.
One could discuss if such a
**task**
storage backend is needed: if you
want to debug some task, just run the worker and log its results. You
can inspect later the errors in the log. On the other hand, if we had
a production worker, which processes lots of tasks, it could be a pain
to store the results of all of them, as we mostly don't care about the
finished ones.
Also, the
`haskell-bee`
framework allows to add custom hooks to the
worker. In particular, search for
`onJobError`
/
`onJobTimeout`
in
`Worker.State`
. We could trigger some
`IO`
action on these hooks
(logging, sending mail, firing rockets).
bin/gargantext-cli/CLI/Import.hs
View file @
02e63fe4
...
@@ -33,7 +33,7 @@ import Gargantext.Database.Action.Flow.Types (FlowCmdM)
...
@@ -33,7 +33,7 @@ import Gargantext.Database.Action.Flow.Types (FlowCmdM)
import
Gargantext.Database.Admin.Types.Node
(
CorpusId
)
import
Gargantext.Database.Admin.Types.Node
(
CorpusId
)
import
Gargantext.Database.Query.Tree.Root
(
MkCorpusUser
(
MkCorpusUserNormalCorpusName
))
import
Gargantext.Database.Query.Tree.Root
(
MkCorpusUser
(
MkCorpusUserNormalCorpusName
))
import
Gargantext.Prelude
import
Gargantext.Prelude
import
Gargantext.Utils.Jobs.Monad
(
MonadJobStatus
,
JobHandle
)
import
Gargantext.Utils.Jobs.Monad
(
MonadJobStatus
(
..
)
)
import
Options.Applicative
import
Options.Applicative
import
Prelude
(
String
)
import
Prelude
(
String
)
import
qualified
Data.Text
as
T
import
qualified
Data.Text
as
T
...
...
bin/gargantext-cli/CLI/Ini.hs
View file @
02e63fe4
...
@@ -28,6 +28,7 @@ import Gargantext.Core.Config.Ini.Ini qualified as Ini
...
@@ -28,6 +28,7 @@ import Gargantext.Core.Config.Ini.Ini qualified as Ini
import
Gargantext.Core.Config.Ini.Mail
qualified
as
IniMail
import
Gargantext.Core.Config.Ini.Mail
qualified
as
IniMail
import
Gargantext.Core.Config.Ini.NLP
qualified
as
IniNLP
import
Gargantext.Core.Config.Ini.NLP
qualified
as
IniNLP
import
Gargantext.Core.Config.Types
qualified
as
CTypes
import
Gargantext.Core.Config.Types
qualified
as
CTypes
import
Gargantext.Core.Config.Worker
(
WorkerSettings
(
..
),
WorkerDefinition
(
..
))
import
Gargantext.Prelude
import
Gargantext.Prelude
import
Options.Applicative
import
Options.Applicative
import
Servant.Client.Core
(
parseBaseUrl
)
import
Servant.Client.Core
(
parseBaseUrl
)
...
@@ -35,7 +36,7 @@ import Toml qualified
...
@@ -35,7 +36,7 @@ import Toml qualified
iniCLI
::
IniArgs
->
IO
()
iniCLI
::
IniArgs
->
IO
()
iniCLI
iniArgs
=
do
iniCLI
iniArgs
@
(
IniArgs
{
dry_run
})
=
do
let
iniPath
=
fromMaybe
"gargantext.ini"
$
ini_path
iniArgs
let
iniPath
=
fromMaybe
"gargantext.ini"
$
ini_path
iniArgs
let
tomlPath
=
fromMaybe
"gargantext-settings.toml"
$
toml_path
iniArgs
let
tomlPath
=
fromMaybe
"gargantext-settings.toml"
$
toml_path
iniArgs
putStrLn
$
"Reading configuration from file "
<>
iniPath
<>
"..."
putStrLn
$
"Reading configuration from file "
<>
iniPath
<>
"..."
...
@@ -44,8 +45,11 @@ iniCLI iniArgs = do
...
@@ -44,8 +45,11 @@ iniCLI iniArgs = do
iniNLP
<-
IniNLP
.
readConfig
iniPath
iniNLP
<-
IniNLP
.
readConfig
iniPath
connInfo
<-
Ini
.
readDBConfig
iniPath
connInfo
<-
Ini
.
readDBConfig
iniPath
let
c
=
convertConfigs
ini
iniMail
iniNLP
connInfo
let
c
=
convertConfigs
ini
iniMail
iniNLP
connInfo
T
.
writeFile
tomlPath
(
show
(
Toml
.
encode
c
)
::
Text
)
if
dry_run
then
putStrLn
$
"Converted configuration into TOML and wrote it to file "
<>
tomlPath
putStrLn
(
show
(
Toml
.
encode
c
)
::
Text
)
else
do
T
.
writeFile
tomlPath
(
show
(
Toml
.
encode
c
)
::
Text
)
putStrLn
$
"Converted configuration into TOML and wrote it to file "
<>
tomlPath
iniCmd
::
HasCallStack
=>
Mod
CommandFields
CLI
iniCmd
::
HasCallStack
=>
Mod
CommandFields
CLI
iniCmd
=
command
"ini"
(
info
(
helper
<*>
fmap
CLISub
iniParser
)
iniCmd
=
command
"ini"
(
info
(
helper
<*>
fmap
CLISub
iniParser
)
...
@@ -54,7 +58,8 @@ iniCmd = command "ini" (info (helper <*> fmap CLISub iniParser)
...
@@ -54,7 +58,8 @@ iniCmd = command "ini" (info (helper <*> fmap CLISub iniParser)
iniParser
::
Parser
CLICmd
iniParser
::
Parser
CLICmd
iniParser
=
fmap
CCMD_ini
$
IniArgs
<$>
iniParser
=
fmap
CCMD_ini
$
IniArgs
<$>
(
optional
.
strOption
$
long
"ini-path"
<>
help
"Path to the input ini file"
)
<*>
(
optional
.
strOption
$
long
"ini-path"
<>
help
"Path to the input ini file"
)
<*>
(
optional
.
strOption
$
long
"toml-path"
<>
help
"Path to the output .toml file"
)
(
optional
.
strOption
$
long
"toml-path"
<>
help
"Path to the output .toml file"
)
<*>
(
flag
False
True
(
long
"dry-run"
<>
help
"If set, will only output generated .toml file to stdout"
))
convertConfigs
::
Ini
.
GargConfig
->
IniMail
.
MailConfig
->
IniNLP
.
NLPConfig
->
PGS
.
ConnectInfo
->
Config
.
GargConfig
convertConfigs
::
Ini
.
GargConfig
->
IniMail
.
MailConfig
->
IniNLP
.
NLPConfig
->
PGS
.
ConnectInfo
->
Config
.
GargConfig
convertConfigs
ini
@
(
Ini
.
GargConfig
{
..
})
iniMail
nlpConfig
connInfo
=
convertConfigs
ini
@
(
Ini
.
GargConfig
{
..
})
iniMail
nlpConfig
connInfo
=
...
@@ -78,6 +83,9 @@ convertConfigs ini@(Ini.GargConfig { .. }) iniMail nlpConfig connInfo =
...
@@ -78,6 +83,9 @@ convertConfigs ini@(Ini.GargConfig { .. }) iniMail nlpConfig connInfo =
,
_jc_js_id_timeout
=
_gc_js_id_timeout
}
,
_jc_js_id_timeout
=
_gc_js_id_timeout
}
,
_gc_apis
=
CTypes
.
APIsConfig
{
_ac_epo_api_url
=
_gc_epo_api_url
,
_gc_apis
=
CTypes
.
APIsConfig
{
_ac_epo_api_url
=
_gc_epo_api_url
,
_ac_scrapyd_url
}
,
_ac_scrapyd_url
}
,
_gc_worker
=
WorkerSettings
{
_wsDefinitions
=
[
wd
]
,
_wsDefaultVisibilityTimeout
=
1
,
_wsDatabase
=
connInfo
{
PGS
.
connectDatabase
=
"pgmq"
}
}
,
_gc_log_level
=
LevelDebug
,
_gc_log_level
=
LevelDebug
}
}
where
where
...
@@ -85,6 +93,8 @@ convertConfigs ini@(Ini.GargConfig { .. }) iniMail nlpConfig connInfo =
...
@@ -85,6 +93,8 @@ convertConfigs ini@(Ini.GargConfig { .. }) iniMail nlpConfig connInfo =
case
parseBaseUrl
"http://localhost:6800"
of
case
parseBaseUrl
"http://localhost:6800"
of
Nothing
->
panicTrace
"Cannot parse base url for scrapyd"
Nothing
->
panicTrace
"Cannot parse base url for scrapyd"
Just
b
->
b
Just
b
->
b
wd
=
WorkerDefinition
{
_wdName
=
"default"
,
_wdQueue
=
"default"
}
mkFrontendConfig
::
Ini
.
GargConfig
->
CTypes
.
FrontendConfig
mkFrontendConfig
::
Ini
.
GargConfig
->
CTypes
.
FrontendConfig
mkFrontendConfig
(
Ini
.
GargConfig
{
..
})
=
mkFrontendConfig
(
Ini
.
GargConfig
{
..
})
=
...
...
bin/gargantext-cli/CLI/Types.hs
View file @
02e63fe4
...
@@ -48,6 +48,7 @@ data ImportArgs = ImportArgs
...
@@ -48,6 +48,7 @@ data ImportArgs = ImportArgs
data
IniArgs
=
IniArgs
data
IniArgs
=
IniArgs
{
ini_path
::
!
(
Maybe
FilePath
)
{
ini_path
::
!
(
Maybe
FilePath
)
,
toml_path
::
!
(
Maybe
FilePath
)
,
toml_path
::
!
(
Maybe
FilePath
)
,
dry_run
::
!
Bool
}
deriving
(
Show
,
Eq
)
}
deriving
(
Show
,
Eq
)
data
InitArgs
=
InitArgs
data
InitArgs
=
InitArgs
...
@@ -79,6 +80,12 @@ data CLIRoutes
...
@@ -79,6 +80,12 @@ data CLIRoutes
|
CLIR_export
FilePath
|
CLIR_export
FilePath
deriving
(
Show
,
Eq
)
deriving
(
Show
,
Eq
)
data
WorkerArgs
=
WorkerArgs
{
worker_toml
::
!
SettingsFile
,
worker_name
::
!
Text
,
worker_run_single
::
!
Bool
}
deriving
(
Show
,
Eq
)
data
CLICmd
data
CLICmd
=
CCMD_clean_csv_corpus
=
CCMD_clean_csv_corpus
|
CCMD_filter_terms_and_cooc
!
CorpusFile
!
TermListFile
!
OutputFile
|
CCMD_filter_terms_and_cooc
!
CorpusFile
!
TermListFile
!
OutputFile
...
@@ -93,6 +100,7 @@ data CLICmd
...
@@ -93,6 +100,7 @@ data CLICmd
|
CCMD_upgrade
!
UpgradeArgs
|
CCMD_upgrade
!
UpgradeArgs
|
CCMD_golden_file_diff
!
GoldenFileDiffArgs
|
CCMD_golden_file_diff
!
GoldenFileDiffArgs
|
CCMD_routes
!
CLIRoutes
|
CCMD_routes
!
CLIRoutes
|
CCMD_worker
!
WorkerArgs
deriving
(
Show
,
Eq
)
deriving
(
Show
,
Eq
)
data
CLI
=
data
CLI
=
...
...
bin/gargantext-cli/CLI/Worker.hs
0 → 100644
View file @
02e63fe4
{-|
Module : Worker.hs
Description : Gargantext Job Worker
Copyright : (c) CNRS, 2017-Present
License : AGPL + CECILL v3
Maintainer : team@gargantext.org
Stability : experimental
Portability : POSIX
-}
module
CLI.Worker
where
import
CLI.Types
import
CLI.Parsers
import
Data.List
qualified
as
List
(
cycle
,
concat
,
take
)
import
Data.Text
qualified
as
T
import
Gargantext.Core.Config
(
hasConfig
,
_gc_worker
)
import
Gargantext.Core.Config.Types
(
SettingsFile
(
..
))
import
Gargantext.Core.Config.Worker
(
WorkerDefinition
(
..
),
WorkerSettings
(
..
),
findDefinitionByName
)
import
Gargantext.Core.Worker
(
withPGMQWorker
,
withPGMQWorkerSingle
)
import
Gargantext.Core.Worker.Env
(
withWorkerEnv
)
import
Gargantext.Core.Worker.Jobs
(
sendJob
)
import
Gargantext.Core.Worker.Jobs.Types
(
Job
(
Ping
))
import
Gargantext.Prelude
import
Options.Applicative
import
Prelude
qualified
-- TODO Command to spawn all workers at once
-- TODO Command to monitor queues
-- TODO Support for KillWorkerSafely on Ctrl-C (so that the job in progress is moved back into the queue)
workerCLI
::
WorkerArgs
->
IO
()
workerCLI
(
WorkerArgs
{
..
})
=
do
let
___
=
putStrLn
((
List
.
concat
$
List
.
take
72
$
List
.
cycle
[
"_"
])
::
Prelude
.
String
)
___
putStrLn
(
"GarganText worker"
::
Text
)
putStrLn
(
"worker_name: "
<>
worker_name
)
putStrLn
(
"worker toml: "
<>
_SettingsFile
worker_toml
)
___
withWorkerEnv
worker_toml
$
\
env
->
do
let
gc
=
env
^.
hasConfig
let
ws
=
_gc_worker
gc
case
findDefinitionByName
ws
worker_name
of
Nothing
->
do
let
workerNames
=
_wdName
<$>
(
_wsDefinitions
ws
)
let
availableWorkers
=
T
.
intercalate
", "
workerNames
putStrLn
(
"Worker definition not found! Available workers: "
<>
availableWorkers
)
Just
wd
->
do
putStrLn
(
"Starting worker '"
<>
worker_name
<>
"'"
)
putStrLn
(
"Worker settings: "
<>
show
ws
::
Text
)
if
worker_run_single
then
withPGMQWorkerSingle
env
wd
$
\
a
_state
->
do
wait
a
else
withPGMQWorker
env
wd
$
\
a
_state
->
do
runReaderT
(
sendJob
Ping
)
env
wait
a
workerCmd
::
HasCallStack
=>
Mod
CommandFields
CLI
workerCmd
=
command
"worker"
(
info
(
helper
<*>
fmap
CLISub
worker_p
)
(
progDesc
"Gargantext worker."
))
worker_p
::
Parser
CLICmd
worker_p
=
fmap
CCMD_worker
$
WorkerArgs
<$>
settings_p
<*>
strOption
(
long
"name"
<>
metavar
"STRING"
<>
help
"Worker name, as defined in the .toml file"
)
<*>
flag
False
True
(
long
"run-single"
<>
help
"Whether to loop or run a single job from queue"
)
bin/gargantext-cli/Main.hs
View file @
02e63fe4
...
@@ -33,6 +33,7 @@ import CLI.Phylo (phyloCLI, phyloCmd)
...
@@ -33,6 +33,7 @@ import CLI.Phylo (phyloCLI, phyloCmd)
import
CLI.Phylo.Profile
(
phyloProfileCLI
,
phyloProfileCmd
)
import
CLI.Phylo.Profile
(
phyloProfileCLI
,
phyloProfileCmd
)
import
CLI.Server.Routes
(
routesCLI
,
routesCmd
)
import
CLI.Server.Routes
(
routesCLI
,
routesCmd
)
import
CLI.Upgrade
(
upgradeCLI
,
upgradeCmd
)
import
CLI.Upgrade
(
upgradeCLI
,
upgradeCmd
)
import
CLI.Worker
(
workerCLI
,
workerCmd
)
runCLI
::
CLI
->
IO
()
runCLI
::
CLI
->
IO
()
runCLI
=
\
case
runCLI
=
\
case
...
@@ -62,6 +63,8 @@ runCLI = \case
...
@@ -62,6 +63,8 @@ runCLI = \case
->
fileDiffCLI
args
->
fileDiffCLI
args
CLISub
(
CCMD_routes
args
)
CLISub
(
CCMD_routes
args
)
->
routesCLI
args
->
routesCLI
args
CLISub
(
CCMD_worker
args
)
->
workerCLI
args
main
::
IO
()
main
::
IO
()
...
@@ -85,5 +88,6 @@ allOptions = subparser (
...
@@ -85,5 +88,6 @@ allOptions = subparser (
phyloProfileCmd
<>
phyloProfileCmd
<>
upgradeCmd
<>
upgradeCmd
<>
fileDiffCmd
<>
fileDiffCmd
<>
routesCmd
routesCmd
<>
workerCmd
)
)
bin/update-project-dependencies
View file @
02e63fe4
...
@@ -18,8 +18,8 @@ fi
...
@@ -18,8 +18,8 @@ fi
# with the `sha256sum` result calculated on the `cabal.project` and
# with the `sha256sum` result calculated on the `cabal.project` and
# `cabal.project.freeze`. This ensures the files stay deterministic so that CI
# `cabal.project.freeze`. This ensures the files stay deterministic so that CI
# cache can kick in.
# cache can kick in.
expected_cabal_project_hash
=
"
3afb11e01938b74ae8419caa160180d8f8628a67315a2d689c3a42a76463071e
"
expected_cabal_project_hash
=
"
eb28225cf0ebf07cc233223d3bbed085ea6ed19e05912c06ecda92a89f8132cb
"
expected_cabal_project_freeze_hash
=
"
de1726d350936da5f5e15140e3be29bb4f44757c5702defe995c2386f1b4a741
"
expected_cabal_project_freeze_hash
=
"
30dd1cf2cb2015351dd0576391d22b187443b1935c2be23599b821ad1ab95f23
"
cabal
--store-dir
=
$STORE_DIR
v2-build
--dry-run
cabal
--store-dir
=
$STORE_DIR
v2-build
--dry-run
...
...
cabal.project
View file @
02e63fe4
...
@@ -190,14 +190,24 @@ source-repository-package
...
@@ -190,14 +190,24 @@ source-repository-package
source
-
repository
-
package
source
-
repository
-
package
type
:
git
type
:
git
location
:
https
://
github
.
com
/
glguy
/
toml
-
parser
location
:
https
://
gitlab
.
iscpif
.
fr
/
gargantext
/
haskell
-
pgmq
tag
:
toml
-
parser
-
2.0.1.0
tag
:
0591
a643d8ba1776af4fac56c1e4ff5fc3e98bb3
source
-
repository
-
package
type
:
git
location
:
https
://
gitlab
.
iscpif
.
fr
/
gargantext
/
haskell
-
bee
tag
:
d783198e1b7ca8a61e5332965db468da3faef796
source
-
repository
-
package
source
-
repository
-
package
type
:
git
type
:
git
location
:
https
://
gitlab
.
iscpif
.
fr
/
gargantext
/
haskell
-
throttle
location
:
https
://
gitlab
.
iscpif
.
fr
/
gargantext
/
haskell
-
throttle
tag
:
02f5
ed9ee2d6cce45161addf945b88bc6adf9059
tag
:
02f5
ed9ee2d6cce45161addf945b88bc6adf9059
source
-
repository
-
package
type
:
git
location
:
https
://
github
.
com
/
glguy
/
toml
-
parser
tag
:
toml
-
parser
-
2.0.1.0
allow
-
newer
:
allow
-
newer
:
accelerate
-
arithmetic
:
accelerate
accelerate
-
arithmetic
:
accelerate
...
@@ -231,6 +241,8 @@ allow-newer:
...
@@ -231,6 +241,8 @@ allow-newer:
,
stemmer
:
base
,
stemmer
:
base
allow
-
older
:
aeson
:
hashable
allow
-
older
:
aeson
:
hashable
,
crawlerHAL
:
servant
-
client
,
crawlerHAL
:
servant
-
client
,
haskell
-
bee
:
postgresql
-
libpq
,
haskell
-
bee
:
stm
,
haskell
-
throttle
:
time
,
haskell
-
throttle
:
time
,
hsparql
:
rdf4h
,
hsparql
:
rdf4h
...
...
cabal.project.freeze
View file @
02e63fe4
active-repositories: hackage.haskell.org:merge
active-repositories: hackage.haskell.org:merge
constraints: any.Cabal ==3.8.1.0,
constraints: any.Boolean ==0.2.4,
any.Cabal ==3.8.1.0,
any.Cabal-syntax ==3.8.1.0,
any.Cabal-syntax ==3.8.1.0,
any.Glob ==0.10.2,
any.Glob ==0.10.2,
any.HTTP ==4000.4.1,
any.HTTP ==4000.4.1,
...
@@ -11,6 +12,7 @@ constraints: any.Cabal ==3.8.1.0,
...
@@ -11,6 +12,7 @@ constraints: any.Cabal ==3.8.1.0,
any.MissingH ==1.6.0.1,
any.MissingH ==1.6.0.1,
MissingH +network--ge-3_0_0,
MissingH +network--ge-3_0_0,
any.MonadRandom ==0.6,
any.MonadRandom ==0.6,
any.NumInstances ==1.4,
any.OneTuple ==0.4.2,
any.OneTuple ==0.4.2,
any.Only ==0.1,
any.Only ==0.1,
any.QuickCheck ==2.14.3,
any.QuickCheck ==2.14.3,
...
@@ -87,6 +89,7 @@ constraints: any.Cabal ==3.8.1.0,
...
@@ -87,6 +89,7 @@ constraints: any.Cabal ==3.8.1.0,
any.bytestring ==0.11.5.3,
any.bytestring ==0.11.5.3,
any.bytestring-builder ==0.10.8.2.0,
any.bytestring-builder ==0.10.8.2.0,
bytestring-builder +bytestring_has_builder,
bytestring-builder +bytestring_has_builder,
any.bytestring-lexing ==0.5.0.14,
any.bzlib-conduit ==0.3.0.3,
any.bzlib-conduit ==0.3.0.3,
any.c2hs ==0.28.8,
any.c2hs ==0.28.8,
c2hs +base3 -regression,
c2hs +base3 -regression,
...
@@ -180,6 +183,7 @@ constraints: any.Cabal ==3.8.1.0,
...
@@ -180,6 +183,7 @@ constraints: any.Cabal ==3.8.1.0,
entropy -donotgetentropy,
entropy -donotgetentropy,
any.epo-api-client ==0.1.0.0,
any.epo-api-client ==0.1.0.0,
any.erf ==2.0.0.0,
any.erf ==2.0.0.0,
any.errors ==2.3.0,
any.exceptions ==0.10.5,
any.exceptions ==0.10.5,
any.extra ==1.7.16,
any.extra ==1.7.16,
any.fail ==4.9.0.0,
any.fail ==4.9.0.0,
...
@@ -220,12 +224,16 @@ constraints: any.Cabal ==3.8.1.0,
...
@@ -220,12 +224,16 @@ constraints: any.Cabal ==3.8.1.0,
hashable +integer-gmp -random-initial-seed,
hashable +integer-gmp -random-initial-seed,
any.hashtables ==1.3.1,
any.hashtables ==1.3.1,
hashtables -bounds-checking -debug -detailed-profiling -portable -sse42 +unsafe-tricks,
hashtables -bounds-checking -debug -detailed-profiling -portable -sse42 +unsafe-tricks,
any.haskell-bee ==0.1.0.0,
any.haskell-igraph ==0.10.4,
any.haskell-igraph ==0.10.4,
any.haskell-lexer ==1.1.1,
any.haskell-lexer ==1.1.1,
any.haskell-pgmq ==0.1.0.0,
any.haskell-src-exts ==1.23.1,
any.haskell-src-exts ==1.23.1,
any.haskell-src-meta ==0.8.14,
any.haskell-src-meta ==0.8.14,
any.haskell-throttle ==0.1.0.0,
any.haskell-throttle ==0.1.0.0,
any.hedgehog ==1.5,
any.hedgehog ==1.5,
any.hedis ==0.15.2,
hedis -dev,
any.hgal ==2.0.0.3,
any.hgal ==2.0.0.3,
any.hlcm ==0.2.2,
any.hlcm ==0.2.2,
any.hmatrix ==0.20.2,
any.hmatrix ==0.20.2,
...
@@ -298,6 +306,8 @@ constraints: any.Cabal ==3.8.1.0,
...
@@ -298,6 +306,8 @@ constraints: any.Cabal ==3.8.1.0,
any.libyaml-clib ==0.2.5,
any.libyaml-clib ==0.2.5,
any.lifted-async ==0.10.2.5,
any.lifted-async ==0.10.2.5,
any.lifted-base ==0.2.3.12,
any.lifted-base ==0.2.3.12,
any.linear ==1.23,
linear -herbie +template-haskell,
any.list-t ==1.0.5.7,
any.list-t ==1.0.5.7,
any.llvm-hs ==12.0.0,
any.llvm-hs ==12.0.0,
llvm-hs -debug -llvm-with-rtti +shared-llvm,
llvm-hs -debug -llvm-with-rtti +shared-llvm,
...
@@ -341,6 +351,7 @@ constraints: any.Cabal ==3.8.1.0,
...
@@ -341,6 +351,7 @@ constraints: any.Cabal ==3.8.1.0,
any.mtl ==2.2.2,
any.mtl ==2.2.2,
any.mtl-compat ==0.2.2,
any.mtl-compat ==0.2.2,
mtl-compat -two-point-one -two-point-two,
mtl-compat -two-point-one -two-point-two,
any.multimap ==1.2.1,
any.mwc-random ==0.15.1.0,
any.mwc-random ==0.15.1.0,
mwc-random -benchpapi,
mwc-random -benchpapi,
any.nanomsg-haskell ==0.2.4,
any.nanomsg-haskell ==0.2.4,
...
@@ -351,6 +362,7 @@ constraints: any.Cabal ==3.8.1.0,
...
@@ -351,6 +362,7 @@ constraints: any.Cabal ==3.8.1.0,
any.network-control ==0.0.2,
any.network-control ==0.0.2,
any.network-info ==0.2.1,
any.network-info ==0.2.1,
any.network-uri ==2.6.4.2,
any.network-uri ==2.6.4.2,
any.newtype-generics ==0.6.2,
any.old-locale ==1.0.0.7,
any.old-locale ==1.0.0.7,
any.old-time ==1.1.0.4,
any.old-time ==1.1.0.4,
any.opaleye ==0.9.7.0,
any.opaleye ==0.9.7.0,
...
@@ -434,6 +446,7 @@ constraints: any.Cabal ==3.8.1.0,
...
@@ -434,6 +446,7 @@ constraints: any.Cabal ==3.8.1.0,
any.rts ==1.0.2,
any.rts ==1.0.2,
any.safe ==0.3.21,
any.safe ==0.3.21,
any.safe-exceptions ==0.1.7.4,
any.safe-exceptions ==0.1.7.4,
any.scanner ==0.3.1,
any.scientific ==0.3.7.0,
any.scientific ==0.3.7.0,
scientific -bytestring-builder -integer-simple,
scientific -bytestring-builder -integer-simple,
any.securemem ==0.1.10,
any.securemem ==0.1.10,
...
@@ -555,6 +568,8 @@ constraints: any.Cabal ==3.8.1.0,
...
@@ -555,6 +568,8 @@ constraints: any.Cabal ==3.8.1.0,
any.unicode-collation ==0.1.3.6,
any.unicode-collation ==0.1.3.6,
unicode-collation -doctests -executable,
unicode-collation -doctests -executable,
any.unique ==0.0.1,
any.unique ==0.0.1,
any.units ==2.4.1.5,
any.units-parser ==0.1.1.5,
any.unix ==2.7.3,
any.unix ==2.7.3,
any.unix-compat ==0.7.2,
any.unix-compat ==0.7.2,
any.unix-time ==0.4.15,
any.unix-time ==0.4.15,
...
@@ -578,6 +593,7 @@ constraints: any.Cabal ==3.8.1.0,
...
@@ -578,6 +593,7 @@ constraints: any.Cabal ==3.8.1.0,
any.vector-algorithms ==0.9.0.2,
any.vector-algorithms ==0.9.0.2,
vector-algorithms +bench +boundschecks -internalchecks -llvm +properties -unsafechecks,
vector-algorithms +bench +boundschecks -internalchecks -llvm +properties -unsafechecks,
any.vector-binary-instances ==0.2.5.2,
any.vector-binary-instances ==0.2.5.2,
any.vector-space ==0.16,
any.vector-th-unbox ==0.2.2,
any.vector-th-unbox ==0.2.2,
any.void ==0.7.3,
any.void ==0.7.3,
void -safe,
void -safe,
...
...
gargantext-settings.toml_toModify
View file @
02e63fe4
...
@@ -138,3 +138,25 @@ dispatcher = { bind = "tcp://*:5561", connect = "tcp://localhost:5561" }
...
@@ -138,3 +138,25 @@ dispatcher = { bind = "tcp://*:5561", connect = "tcp://localhost:5561" }
# - johnsnows:// (for https:// JohnSnow)
# - johnsnows:// (for https:// JohnSnow)
EN = "spacy://localhost:8000"
EN = "spacy://localhost:8000"
FR = "spacy://localhost:8001"
FR = "spacy://localhost:8001"
[worker]
# After this number of seconds, the job will be available again.
# You can set timeout for each job individually and this is the
# preferred method over using defaultVt.
default_visibility_timeout = 1
# if you leave the same credentials as in [database] section above,
# workers will try to set up the `gargantext_pgmq` database
# automatically
[worker.database]
host = "127.0.0.1"
port = 5432
name = "gargantext_pgmq"
user = "gargantua"
pass = PASSWORD_TO_CHANGE
[[worker.definitions]]
name = "default"
queue = "default"
gargantext.cabal
View file @
02e63fe4
...
@@ -172,6 +172,7 @@ library
...
@@ -172,6 +172,7 @@ library
Gargantext.Core.Config.NLP
Gargantext.Core.Config.NLP
Gargantext.Core.Config.Types
Gargantext.Core.Config.Types
Gargantext.Core.Config.Utils
Gargantext.Core.Config.Utils
Gargantext.Core.Config.Worker
Gargantext.Core.Mail.Types
Gargantext.Core.Mail.Types
Gargantext.Core.Methods.Similarities
Gargantext.Core.Methods.Similarities
Gargantext.Core.Methods.Similarities.Conditional
Gargantext.Core.Methods.Similarities.Conditional
...
@@ -239,6 +240,11 @@ library
...
@@ -239,6 +240,11 @@ library
Gargantext.Core.Viz.Phylo.PhyloTools
Gargantext.Core.Viz.Phylo.PhyloTools
Gargantext.Core.Viz.Phylo.SynchronicClustering
Gargantext.Core.Viz.Phylo.SynchronicClustering
Gargantext.Core.Viz.Types
Gargantext.Core.Viz.Types
Gargantext.Core.Worker
Gargantext.Core.Worker.Broker
Gargantext.Core.Worker.Env
Gargantext.Core.Worker.Jobs
Gargantext.Core.Worker.Jobs.Types
Gargantext.Database.Action.Flow
Gargantext.Database.Action.Flow
Gargantext.Database.Action.Flow.Types
Gargantext.Database.Action.Flow.Types
Gargantext.Database.Action.Metrics.TFICF
Gargantext.Database.Action.Metrics.TFICF
...
@@ -518,7 +524,9 @@ library
...
@@ -518,7 +524,9 @@ library
, gargantext-graph >=0.1.0.0
, gargantext-graph >=0.1.0.0
, gargantext-prelude
, gargantext-prelude
, graphviz ^>= 2999.20.1.0
, graphviz ^>= 2999.20.1.0
, haskell-bee
, haskell-igraph ^>= 0.10.4
, haskell-igraph ^>= 0.10.4
, haskell-pgmq >= 0.1.0.0 && < 0.2
, haskell-throttle
, haskell-throttle
, hlcm ^>= 0.2.2
, hlcm ^>= 0.2.2
, hsinfomap ^>= 0.1
, hsinfomap ^>= 0.1
...
@@ -585,6 +593,7 @@ library
...
@@ -585,6 +593,7 @@ library
, servant-swagger-ui-core >= 0.3.5
, servant-swagger-ui-core >= 0.3.5
, servant-websockets >= 2.0.0 && < 2.1
, servant-websockets >= 2.0.0 && < 2.1
, servant-xml-conduit ^>= 0.1.0.4
, servant-xml-conduit ^>= 0.1.0.4
, shelly >= 1.9 && < 2
, singletons ^>= 3.0.2
, singletons ^>= 3.0.2
, singletons-th >= 3.1 && < 3.2
, singletons-th >= 3.1 && < 3.2
, smtp-mail >= 0.3.0.0
, smtp-mail >= 0.3.0.0
...
@@ -643,6 +652,7 @@ executable gargantext-cli
...
@@ -643,6 +652,7 @@ executable gargantext-cli
CLI.Server.Routes
CLI.Server.Routes
CLI.Types
CLI.Types
CLI.Upgrade
CLI.Upgrade
CLI.Worker
Paths_gargantext
Paths_gargantext
hs-source-dirs:
hs-source-dirs:
bin/gargantext-cli
bin/gargantext-cli
...
@@ -658,6 +668,7 @@ executable gargantext-cli
...
@@ -658,6 +668,7 @@ executable gargantext-cli
, extra ^>= 1.7.9
, extra ^>= 1.7.9
, gargantext
, gargantext
, gargantext-prelude
, gargantext-prelude
, haskell-bee
, ini ^>= 0.4.1
, ini ^>= 0.4.1
, lens >= 5.2.2 && < 5.3
, lens >= 5.2.2 && < 5.3
, monad-logger ^>= 0.3.36
, monad-logger ^>= 0.3.36
...
@@ -810,6 +821,7 @@ test-suite garg-test-tasty
...
@@ -810,6 +821,7 @@ test-suite garg-test-tasty
Test.Core.Text.Examples
Test.Core.Text.Examples
Test.Core.Text.Flow
Test.Core.Text.Flow
Test.Core.Utils
Test.Core.Utils
Test.Core.Worker
Test.Database.Operations
Test.Database.Operations
Test.Database.Operations.DocumentSearch
Test.Database.Operations.DocumentSearch
Test.Database.Operations.NodeStory
Test.Database.Operations.NodeStory
...
...
src/Gargantext/API/Admin/Auth.hs
View file @
02e63fe4
...
@@ -40,11 +40,12 @@ module Gargantext.API.Admin.Auth
...
@@ -40,11 +40,12 @@ module Gargantext.API.Admin.Auth
,
withNamedAccess
,
withNamedAccess
,
ForgotPasswordAsyncParams
,
ForgotPasswordAsyncParams
,
forgotUserPassword
)
)
where
where
import
Control.Lens
(
view
,
(
#
))
import
Control.Lens
(
view
,
(
#
))
import
Data.Text
qualified
as
Text
import
Data.Text.Lazy.Encoding
qualified
as
LE
import
Data.Text.Lazy.Encoding
qualified
as
LE
import
Data.UUID
(
UUID
,
fromText
,
toText
)
import
Data.UUID
(
UUID
,
fromText
,
toText
)
import
Data.UUID.V4
(
nextRandom
)
import
Data.UUID.V4
(
nextRandom
)
...
@@ -58,7 +59,8 @@ import Gargantext.Core.Config (HasJWTSettings(..))
...
@@ -58,7 +59,8 @@ import Gargantext.Core.Config (HasJWTSettings(..))
import
Gargantext.Core.Mail
(
MailModel
(
..
),
mail
)
import
Gargantext.Core.Mail
(
MailModel
(
..
),
mail
)
import
Gargantext.Core.Mail.Types
(
mailSettings
)
import
Gargantext.Core.Mail.Types
(
mailSettings
)
import
Gargantext.Core.Types.Individu
(
User
(
..
),
Username
,
GargPassword
(
..
))
import
Gargantext.Core.Types.Individu
(
User
(
..
),
Username
,
GargPassword
(
..
))
import
Gargantext.Database.Action.Flow.Types
(
FlowCmdM
)
import
Gargantext.Core.Worker.Jobs
qualified
as
Jobs
import
Gargantext.Core.Worker.Jobs.Types
qualified
as
Jobs
import
Gargantext.Database.Action.User.New
(
guessUserName
)
import
Gargantext.Database.Action.User.New
(
guessUserName
)
import
Gargantext.Database.Admin.Types.Node
(
NodeId
(
..
))
import
Gargantext.Database.Admin.Types.Node
(
NodeId
(
..
))
import
Gargantext.Database.Admin.Types.Node
(
UserId
)
import
Gargantext.Database.Admin.Types.Node
(
UserId
)
...
@@ -70,7 +72,7 @@ import Gargantext.Database.Schema.Node (NodePoly(_node_id))
...
@@ -70,7 +72,7 @@ import Gargantext.Database.Schema.Node (NodePoly(_node_id))
import
Gargantext.Prelude
hiding
(
Handler
,
reverse
,
to
)
import
Gargantext.Prelude
hiding
(
Handler
,
reverse
,
to
)
import
Gargantext.Prelude.Crypto.Auth
qualified
as
Auth
import
Gargantext.Prelude.Crypto.Auth
qualified
as
Auth
import
Gargantext.Prelude.Crypto.Pass.User
(
gargPass
)
import
Gargantext.Prelude.Crypto.Pass.User
(
gargPass
)
import
Gargantext.Utils.Jobs
(
serveJobsAPI
,
MonadJobStatus
(
..
)
)
import
Gargantext.Utils.Jobs
(
serveJobsAPI
)
import
Servant
import
Servant
import
Servant.API.Generic
()
import
Servant.API.Generic
()
import
Servant.Auth.Server
import
Servant.Auth.Server
...
@@ -240,14 +242,7 @@ forgotPassword = Named.ForgotPasswordAPI
...
@@ -240,14 +242,7 @@ forgotPassword = Named.ForgotPasswordAPI
forgotPasswordPost
::
(
CmdCommon
env
)
forgotPasswordPost
::
(
CmdCommon
env
)
=>
ForgotPasswordRequest
->
Cmd'
env
err
ForgotPasswordResponse
=>
ForgotPasswordRequest
->
Cmd'
env
err
ForgotPasswordResponse
forgotPasswordPost
(
ForgotPasswordRequest
email
)
=
do
forgotPasswordPost
(
ForgotPasswordRequest
_email
)
=
do
us
<-
getUsersWithEmail
(
Text
.
toLower
email
)
case
us
of
[
u
]
->
forgotUserPassword
u
_
->
pure
()
-- NOTE Sending anything else here could leak information about
-- users' emails
pure
$
ForgotPasswordResponse
"ok"
pure
$
ForgotPasswordResponse
"ok"
forgotPasswordGet
::
(
CmdCommon
env
,
HasServerError
err
)
forgotPasswordGet
::
(
CmdCommon
env
,
HasServerError
err
)
...
@@ -327,19 +322,5 @@ generateForgotPasswordUUID = do
...
@@ -327,19 +322,5 @@ generateForgotPasswordUUID = do
-- malicious users emails of our users in the db
-- malicious users emails of our users in the db
forgotPasswordAsync
::
Named
.
ForgotPasswordAsyncAPI
(
AsServerT
(
GargM
Env
BackendInternalError
))
forgotPasswordAsync
::
Named
.
ForgotPasswordAsyncAPI
(
AsServerT
(
GargM
Env
BackendInternalError
))
forgotPasswordAsync
=
Named
.
ForgotPasswordAsyncAPI
$
AsyncJobs
$
forgotPasswordAsync
=
Named
.
ForgotPasswordAsyncAPI
$
AsyncJobs
$
serveJobsAPI
ForgotPasswordJob
$
\
jHandle
p
->
forgotPasswordAsync'
p
jHandle
serveJobsAPI
ForgotPasswordJob
$
\
_jHandle
p
->
do
Jobs
.
sendJob
$
Jobs
.
ForgotPasswordAsync
{
Jobs
.
_fpa_args
=
p
}
forgotPasswordAsync'
::
(
FlowCmdM
env
err
m
,
MonadJobStatus
m
)
=>
ForgotPasswordAsyncParams
->
JobHandle
m
->
m
()
forgotPasswordAsync'
(
ForgotPasswordAsyncParams
{
email
})
jobHandle
=
do
markStarted
2
jobHandle
markProgress
1
jobHandle
-- printDebug "[forgotPasswordAsync'] email" email
_
<-
forgotPasswordPost
$
ForgotPasswordRequest
{
_fpReq_email
=
email
}
markComplete
jobHandle
src/Gargantext/API/Admin/Auth/Types.hs
View file @
02e63fe4
...
@@ -118,23 +118,23 @@ type Email = Text
...
@@ -118,23 +118,23 @@ type Email = Text
type
Password
=
Text
type
Password
=
Text
data
ForgotPasswordRequest
=
ForgotPasswordRequest
{
_fpReq_email
::
Email
}
data
ForgotPasswordRequest
=
ForgotPasswordRequest
{
_fpReq_email
::
Email
}
deriving
(
Generic
)
deriving
(
Generic
)
instance
ToSchema
ForgotPasswordRequest
where
instance
ToSchema
ForgotPasswordRequest
where
declareNamedSchema
=
genericDeclareNamedSchema
(
unPrefixSwagger
"_fpReq_"
)
declareNamedSchema
=
genericDeclareNamedSchema
(
unPrefixSwagger
"_fpReq_"
)
data
ForgotPasswordResponse
=
ForgotPasswordResponse
{
_fpRes_status
::
Text
}
data
ForgotPasswordResponse
=
ForgotPasswordResponse
{
_fpRes_status
::
Text
}
deriving
(
Generic
)
deriving
(
Generic
)
instance
ToSchema
ForgotPasswordResponse
where
instance
ToSchema
ForgotPasswordResponse
where
declareNamedSchema
=
genericDeclareNamedSchema
(
unPrefixSwagger
"_fpRes_"
)
declareNamedSchema
=
genericDeclareNamedSchema
(
unPrefixSwagger
"_fpRes_"
)
data
ForgotPasswordGet
=
ForgotPasswordGet
{
_fpGet_password
::
Password
}
data
ForgotPasswordGet
=
ForgotPasswordGet
{
_fpGet_password
::
Password
}
deriving
(
Generic
)
deriving
(
Generic
)
instance
ToSchema
ForgotPasswordGet
where
instance
ToSchema
ForgotPasswordGet
where
declareNamedSchema
=
genericDeclareNamedSchema
(
unPrefixSwagger
"_fpGet_"
)
declareNamedSchema
=
genericDeclareNamedSchema
(
unPrefixSwagger
"_fpGet_"
)
newtype
ForgotPasswordAsyncParams
=
newtype
ForgotPasswordAsyncParams
=
ForgotPasswordAsyncParams
{
email
::
Text
}
ForgotPasswordAsyncParams
{
email
::
Text
}
deriving
(
Generic
,
Show
)
deriving
(
Generic
,
Show
,
Eq
)
instance
FromJSON
ForgotPasswordAsyncParams
where
instance
FromJSON
ForgotPasswordAsyncParams
where
parseJSON
=
genericParseJSON
defaultOptions
parseJSON
=
genericParseJSON
defaultOptions
instance
ToJSON
ForgotPasswordAsyncParams
where
instance
ToJSON
ForgotPasswordAsyncParams
where
...
...
src/Gargantext/API/Admin/EnvTypes.hs
View file @
02e63fe4
...
@@ -6,6 +6,7 @@
...
@@ -6,6 +6,7 @@
module
Gargantext.API.Admin.EnvTypes
(
module
Gargantext.API.Admin.EnvTypes
(
GargJob
(
..
)
GargJob
(
..
)
,
parseGargJob
,
Env
(
..
)
,
Env
(
..
)
,
Mode
(
..
)
,
Mode
(
..
)
,
modeToLoggingLevels
,
modeToLoggingLevels
...
@@ -28,9 +29,12 @@ module Gargantext.API.Admin.EnvTypes (
...
@@ -28,9 +29,12 @@ module Gargantext.API.Admin.EnvTypes (
,
ConcreteJobHandle
-- opaque
,
ConcreteJobHandle
-- opaque
)
where
)
where
import
Control.Lens
hiding
(
Level
,
(
:<
))
import
Control.Lens
hiding
(
Level
,
(
:<
)
,
(
.=
)
)
import
Control.Monad.Except
import
Control.Monad.Except
import
Control.Monad.Reader
import
Control.Monad.Reader
import
Data.Aeson
qualified
as
Aeson
import
Data.Aeson
((
.:
),
(
.=
),
object
,
withObject
)
import
Data.Aeson.Types
(
prependFailure
,
typeMismatch
)
import
Data.List
((
\\
))
import
Data.List
((
\\
))
import
Data.Pool
(
Pool
)
import
Data.Pool
(
Pool
)
import
Data.Sequence
(
ViewL
(
..
),
viewl
)
import
Data.Sequence
(
ViewL
(
..
),
viewl
)
...
@@ -99,24 +103,69 @@ instance HasLogger (GargM Env BackendInternalError) where
...
@@ -99,24 +103,69 @@ instance HasLogger (GargM Env BackendInternalError) where
data
GargJob
data
GargJob
=
TableNgramsJob
=
AddAnnuaireFormJob
|
ForgotPasswordJob
|
UpdateNgramsListJobJSON
|
UpdateNgramsListJobTSV
|
AddContactJob
|
AddContactJob
|
AddCorpusFileJob
|
AddCorpusFormJob
|
AddCorpusQueryJob
|
AddFileJob
|
AddFileJob
|
DocumentFromWriteNodeJob
|
DocumentFromWriteNodeJob
|
UpdateNodeJob
|
ForgotPasswordJob
|
UploadFrameCalcJob
|
UploadDocumentJob
|
NewNodeJob
|
NewNodeJob
|
AddCorpusQueryJob
|
AddCorpusFormJob
|
AddCorpusFileJob
|
AddAnnuaireFormJob
|
RecomputeGraphJob
|
RecomputeGraphJob
|
TableNgramsJob
|
UpdateNgramsListJobJSON
|
UpdateNgramsListJobTSV
|
UpdateNodeJob
|
UploadDocumentJob
|
UploadFrameCalcJob
deriving
(
Show
,
Eq
,
Ord
,
Enum
,
Bounded
)
deriving
(
Show
,
Eq
,
Ord
,
Enum
,
Bounded
)
parseGargJob
::
Text
->
Maybe
GargJob
parseGargJob
s
=
case
s
of
"addannuaireform"
->
Just
AddAnnuaireFormJob
"addcontact"
->
Just
AddContactJob
"addcorpusfile"
->
Just
AddCorpusFileJob
"addcorpusform"
->
Just
AddCorpusFormJob
"addcorpusquery"
->
Just
AddCorpusQueryJob
"addfile"
->
Just
AddFileJob
"documentfromwritenode"
->
Just
DocumentFromWriteNodeJob
"forgotpassword"
->
Just
ForgotPasswordJob
"newnode"
->
Just
NewNodeJob
"recomputegraph"
->
Just
RecomputeGraphJob
"tablengrams"
->
Just
TableNgramsJob
"updatedocument"
->
Just
UploadDocumentJob
"updateframecalc"
->
Just
UploadFrameCalcJob
"updatengramslistjson"
->
Just
UpdateNgramsListJobJSON
"updatengramslisttsv"
->
Just
UpdateNgramsListJobTSV
"updatenode"
->
Just
UpdateNodeJob
_
->
Nothing
instance
FromJSON
GargJob
where
parseJSON
=
withObject
"GargJob"
$
\
o
->
do
type_
<-
o
.:
"type"
case
parseGargJob
type_
of
Just
gj
->
return
gj
Nothing
->
prependFailure
"parsing garg job type failed, "
(
typeMismatch
"type"
$
Aeson
.
String
type_
)
instance
ToJSON
GargJob
where
toJSON
AddAnnuaireFormJob
=
object
[
(
"type"
.=
(
"addannuaireform"
::
Text
))]
toJSON
AddContactJob
=
object
[
(
"type"
.=
(
"addcontact"
::
Text
))]
toJSON
AddCorpusFileJob
=
object
[
(
"type"
.=
(
"addcorpusfile"
::
Text
))]
toJSON
AddCorpusFormJob
=
object
[
(
"type"
.=
(
"addcorpusform"
::
Text
))]
toJSON
AddCorpusQueryJob
=
object
[
(
"type"
.=
(
"addcorpusquery"
::
Text
))]
toJSON
AddFileJob
=
object
[
(
"type"
.=
(
"addfile"
::
Text
))]
toJSON
DocumentFromWriteNodeJob
=
object
[
(
"type"
.=
(
"documentfromwritenode"
::
Text
))]
toJSON
ForgotPasswordJob
=
object
[
(
"type"
.=
(
"forgotpassword"
::
Text
))]
toJSON
NewNodeJob
=
object
[
(
"type"
.=
(
"newnode"
::
Text
))]
toJSON
RecomputeGraphJob
=
object
[
(
"type"
.=
(
"recomputegraph"
::
Text
))]
toJSON
TableNgramsJob
=
object
[
(
"type"
.=
(
"tablengrams"
::
Text
))]
toJSON
UploadDocumentJob
=
object
[
(
"type"
.=
(
"updatedocument"
::
Text
))]
toJSON
UploadFrameCalcJob
=
object
[
(
"type"
.=
(
"updateframecalc"
::
Text
))]
toJSON
UpdateNgramsListJobJSON
=
object
[
(
"type"
.=
(
"updatengramslistjson"
::
Text
))]
toJSON
UpdateNgramsListJobTSV
=
object
[
(
"type"
.=
(
"updatengramslisttsv"
::
Text
))]
toJSON
UpdateNodeJob
=
object
[
(
"type"
.=
(
"updatenode"
::
Text
))]
-- Do /not/ treat the data types of this type as strict, because it's convenient
-- Do /not/ treat the data types of this type as strict, because it's convenient
-- to be able to partially initialise things like an 'Env' during tests, without
-- to be able to partially initialise things like an 'Env' during tests, without
-- having to specify /everything/. This means that when we /construct/ an 'Env',
-- having to specify /everything/. This means that when we /construct/ an 'Env',
...
...
src/Gargantext/API/Admin/Settings/TOML.hs
0 → 100644
View file @
02e63fe4
{-# LANGUAGE TemplateHaskell #-}
module
Gargantext.API.Admin.Settings.TOML
where
import
Control.Lens
hiding
((
.=
))
import
Data.Text
qualified
as
T
import
Gargantext.API.Admin.Settings.CORS
import
Gargantext.API.Admin.Settings.MicroServices
import
Gargantext.Core.Worker.TOML
import
Gargantext.Prelude
(
panicTrace
)
import
Gargantext.System.Logging
import
Prelude
import
Toml
import
Servant.Client.Core.BaseUrl
-- | Compatibility bridge until we fix #304 (move to Toml)
data
GargTomlSettings
=
GargTomlSettings
{
_gargCorsSettings
::
!
CORSSettings
,
_gargMicroServicesSettings
::
!
MicroServicesSettings
,
_gargWorkerSettings
::
!
WorkerSettings
}
makeLenses
''
G
argTomlSettings
settingsCodec
::
TomlCodec
GargTomlSettings
settingsCodec
=
GargTomlSettings
<$>
(
Toml
.
table
corsSettingsCodec
"cors"
.=
_gargCorsSettings
)
<*>
(
Toml
.
table
microServicesSettingsCodec
"microservices.proxy"
.=
_gargMicroServicesSettings
)
<*>
(
Toml
.
table
workerSettingsCodec
"worker"
.=
_gargWorkerSettings
)
-- | Extends the 'allowed-origins' in the CORSettings with the URLs embellished
-- with the proxy port.
addProxyToAllowedOrigins
::
GargTomlSettings
->
GargTomlSettings
addProxyToAllowedOrigins
stgs
=
stgs
&
over
gargCorsSettings
(
addProxies
$
stgs
^.
gargMicroServicesSettings
.
msProxyPort
)
where
addProxies
::
Int
->
CORSSettings
->
CORSSettings
addProxies
port
cors
=
let
origins
=
_corsAllowedOrigins
cors
mkUrl
(
CORSOrigin
bh
)
=
CORSOrigin
$
bh
{
baseUrlPort
=
port
}
in
cors
{
_corsAllowedOrigins
=
origins
<>
Prelude
.
map
mkUrl
origins
}
-- | Loads the 'CORSSettings' from the 'toml' file.
loadGargTomlSettings
::
FilePath
->
IO
GargTomlSettings
loadGargTomlSettings
tomlFile
=
do
tomlRes
<-
Toml
.
decodeFileEither
settingsCodec
tomlFile
case
tomlRes
of
Left
errs
->
do
withLogger
()
$
\
ioLogger
->
do
logMsg
ioLogger
ERROR
$
T
.
unpack
$
"Error, gargantext-settings.toml parsing failed: "
<>
Toml
.
prettyTomlDecodeErrors
errs
panicTrace
"Please fix the errors in your gargantext-settings.toml file."
Right
settings0
->
case
settings0
^.
gargCorsSettings
.
corsUseOriginsForHosts
of
True
->
pure
$
addProxyToAllowedOrigins
$
settings0
&
over
(
gargCorsSettings
.
corsAllowedHosts
)
(
\
_
->
(
settings0
^.
gargCorsSettings
.
corsAllowedOrigins
))
False
->
pure
$
addProxyToAllowedOrigins
settings0
src/Gargantext/API/GraphQL.hs
View file @
02e63fe4
...
@@ -13,10 +13,10 @@ Portability : POSIX
...
@@ -13,10 +13,10 @@ Portability : POSIX
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DuplicateRecordFields #-}
-- permit duplications for field names in multiple constructors
{-# LANGUAGE DuplicateRecordFields #-}
-- permit duplications for field names in multiple constructors
{-# LANGUAGE KindSignatures #-}
-- for use of Endpoint (name :: Symbol)
{-# LANGUAGE KindSignatures #-}
-- for use of Endpoint (name :: Symbol)
{-# LANGUAGE PartialTypeSignatures #-}
-- to automatically use suggested type hole signatures during compilation
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE PartialTypeSignatures #-}
-- to automatically use suggested type hole signatures during compilation
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeOperators #-}
module
Gargantext.API.GraphQL
where
module
Gargantext.API.GraphQL
where
...
...
src/Gargantext/API/Node/New.hs
View file @
02e63fe4
...
@@ -27,31 +27,33 @@ import Gargantext.API.Errors.Types
...
@@ -27,31 +27,33 @@ import Gargantext.API.Errors.Types
import
Gargantext.API.Node.New.Types
import
Gargantext.API.Node.New.Types
import
Gargantext.API.Prelude
import
Gargantext.API.Prelude
import
Gargantext.API.Routes.Named.Node
qualified
as
Named
import
Gargantext.API.Routes.Named.Node
qualified
as
Named
import
Gargantext.Core.Notifications.CentralExchange.Types
qualified
as
CE
import
Gargantext.Core.AsyncUpdates.CentralExchange.Types
qualified
as
CE
import
Gargantext.Database.Action.Flow.Types
import
Gargantext.Core.Mail.Types
(
HasMail
)
import
Gargantext.Core.NLP
(
HasNLPServer
)
import
Gargantext.Core.Worker.Jobs
qualified
as
Jobs
import
Gargantext.Core.Worker.Jobs.Types
qualified
as
Jobs
import
Gargantext.Database.Action.Node
import
Gargantext.Database.Action.Node
import
Gargantext.Database.Admin.Types.Node
import
Gargantext.Database.Admin.Types.Node
import
Gargantext.Database.Prelude
(
DBCmd
'
)
import
Gargantext.Database.Prelude
(
CmdM
,
DBCmd
'
)
import
Gargantext.Database.Query.Table.Node.Error
(
HasNodeError
(
..
))
import
Gargantext.Database.Query.Table.Node.Error
(
HasNodeError
(
..
))
import
Gargantext.Prelude
import
Gargantext.Prelude
import
Gargantext.Utils.Jobs
(
serveJobsAPI
,
MonadJobStatus
(
..
)
)
import
Gargantext.Utils.Jobs
(
serveJobsAPI
)
import
Servant.Server.Generic
(
AsServerT
)
import
Servant.Server.Generic
(
AsServerT
)
------------------------------------------------------------------------
------------------------------------------------------------------------
postNode
::
(
HasNodeError
err
,
CE
.
HasCentralExchangeNotification
env
)
-- postNode :: (CmdM env err m, HasNodeError err, HasSettings env)
postNode
::
(
HasMail
env
,
HasNodeError
err
,
HasNLPServer
env
,
CE
.
HasCentralExchangeNotification
env
)
=>
AuthenticatedUser
=>
AuthenticatedUser
-- ^ The logged-in user
-- ^ The logged-in user
->
NodeId
->
NodeId
->
PostNode
->
PostNode
-- -> m [NodeId]
->
DBCmd'
env
err
[
NodeId
]
->
DBCmd'
env
err
[
NodeId
]
postNode
authenticatedUser
pId
(
PostNode
nodeName
nt
)
=
do
postNode
authenticatedUser
nId
pn
=
do
let
userId
=
authenticatedUser
^.
auth_user_id
postNode'
authenticatedUser
nId
pn
nodeIds
<-
mkNodeWithParent
nt
(
Just
pId
)
userId
nodeName
-- mapM_ (CE.ce_notify . CE.UpdateTreeFirstLevel) nodeIds
CE
.
ce_notify
$
CE
.
UpdateTreeFirstLevel
pId
return
nodeIds
postNodeAsyncAPI
postNodeAsyncAPI
::
AuthenticatedUser
::
AuthenticatedUser
...
@@ -60,29 +62,57 @@ postNodeAsyncAPI
...
@@ -60,29 +62,57 @@ postNodeAsyncAPI
-- ^ The target node
-- ^ The target node
->
Named
.
PostNodeAsyncAPI
(
AsServerT
(
GargM
Env
BackendInternalError
))
->
Named
.
PostNodeAsyncAPI
(
AsServerT
(
GargM
Env
BackendInternalError
))
postNodeAsyncAPI
authenticatedUser
nId
=
Named
.
PostNodeAsyncAPI
$
AsyncJobs
$
postNodeAsyncAPI
authenticatedUser
nId
=
Named
.
PostNodeAsyncAPI
$
AsyncJobs
$
serveJobsAPI
NewNodeJob
$
\
jHandle
p
->
postNodeAsync
authenticatedUser
nId
p
jHandle
serveJobsAPI
NewNodeJob
$
\
_jHandle
p
->
do
Jobs
.
sendJob
$
Jobs
.
NewNodeAsync
{
Jobs
.
_nna_node_id
=
nId
,
Jobs
.
_nna_authenticatedUser
=
authenticatedUser
,
Jobs
.
_nna_postNode
=
p
}
-- postNodeAsync authenticatedUser nId p jHandle
------------------------------------------------------------------------
------------------------------------------------------------------------
postNodeAsync
::
(
FlowCmdM
env
err
m
,
MonadJobStatus
m
,
CE
.
HasCentralExchangeNotification
env
)
-- postNode' :: (CmdM env err m, HasSettings env, HasNodeError err)
-- => AuthenticatedUser
-- -- ^ The logged-in user
-- -> NodeId
-- -> PostNode
-- -> m [NodeId]
-- postNode' authenticatedUser pId (PostNode nodeName nt) = do
postNode'
::
(
CmdM
env
err
m
,
HasNodeError
err
,
HasMail
env
,
CE
.
HasCentralExchangeNotification
env
)
=>
AuthenticatedUser
=>
AuthenticatedUser
-- ^ The logged in user
-- ^ The logged in user
->
NodeId
->
NodeId
->
PostNode
->
PostNode
->
JobHandle
m
->
m
[
NodeId
]
->
m
()
postNode'
authenticatedUser
nId
(
PostNode
nodeName
tn
)
=
do
postNodeAsync
authenticatedUser
nId
(
PostNode
nodeName
tn
)
jobHandle
=
do
-- printDebug "postNodeAsync" nId
markStarted
3
jobHandle
markProgress
1
jobHandle
-- _ <- threadDelay 1000
markProgress
1
jobHandle
let
userId
=
authenticatedUser
^.
auth_user_id
let
userId
=
authenticatedUser
^.
auth_user_id
_
nodeIds
<-
mkNodeWithParent
tn
(
Just
nId
)
userId
nodeName
nodeIds
<-
mkNodeWithParent
tn
(
Just
nId
)
userId
nodeName
-- mapM_ (CE.ce_notify . CE.UpdateTreeFirstLevel) nodeIds
-- mapM_ (CE.ce_notify . CE.UpdateTreeFirstLevel) nodeIds
CE
.
ce_notify
$
CE
.
UpdateTreeFirstLevel
nId
CE
.
ce_notify
$
CE
.
UpdateTreeFirstLevel
nId
markComplete
jobHandle
return
nodeIds
-- postNodeAsync :: (FlowCmdM env err m, MonadJobStatus m, HasSettings env)
-- => AuthenticatedUser
-- -- ^ The logged in user
-- -> NodeId
-- -> PostNode
-- -> JobHandle m
-- -> m ()
-- postNodeAsync authenticatedUser nId (PostNode nodeName tn) jobHandle = do
-- -- printDebug "postNodeAsync" nId
-- markStarted 3 jobHandle
-- markProgress 1 jobHandle
-- -- _ <- threadDelay 1000
-- markProgress 1 jobHandle
-- let userId = authenticatedUser ^. auth_user_id
-- _ <- mkNodeWithParent tn (Just nId) userId nodeName
-- markComplete jobHandle
src/Gargantext/API/Node/New/Types.hs
View file @
02e63fe4
{-|
Module : Gargantext.API.Node.New.Types
Description :
Copyright : (c) CNRS, 2024-Present
License : AGPL + CECILL v3
Maintainer : team@gargantext.org
Stability : experimental
Portability : POSIX
-}
module
Gargantext.API.Node.New.Types
(
module
Gargantext.API.Node.New.Types
(
PostNode
(
..
)
PostNode
(
..
)
...
@@ -5,16 +15,16 @@ module Gargantext.API.Node.New.Types (
...
@@ -5,16 +15,16 @@ module Gargantext.API.Node.New.Types (
import
Data.Aeson
import
Data.Aeson
import
Data.Swagger
import
Data.Swagger
import
Data.Text
(
Text
)
import
GHC.Generics
import
GHC.Generics
import
Gargantext.Core.Types
(
NodeType
(
..
))
import
Gargantext.Core.Types
(
NodeType
(
..
))
import
Gargantext.Prelude
import
Test.QuickCheck
import
Test.QuickCheck
import
Web.FormUrlEncoded
import
Web.FormUrlEncoded
------------------------------------------------------------------------
------------------------------------------------------------------------
data
PostNode
=
PostNode
{
pn_name
::
Text
data
PostNode
=
PostNode
{
pn_name
::
Text
,
pn_typename
::
NodeType
}
,
pn_typename
::
NodeType
}
deriving
(
Generic
)
deriving
(
Generic
,
Eq
,
Show
)
------------------------------------------------------------------------
------------------------------------------------------------------------
-- TODO unPrefix "pn_" FromJSON, ToJSON, ToSchema, adapt frontend.
-- TODO unPrefix "pn_" FromJSON, ToJSON, ToSchema, adapt frontend.
instance
FromJSON
PostNode
instance
FromJSON
PostNode
...
...
src/Gargantext/API/Routes.hs
View file @
02e63fe4
...
@@ -10,31 +10,26 @@ Portability : POSIX
...
@@ -10,31 +10,26 @@ Portability : POSIX
-}
-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE UndecidableInstances #-}
module
Gargantext.API.Routes
module
Gargantext.API.Routes
where
where
import
Control.Lens
(
view
)
import
Data.Validity
import
Data.Validity
import
Gargantext.API.Admin.EnvTypes
(
Env
,
GargJob
(
..
))
import
Gargantext.API.Admin.EnvTypes
(
Env
,
GargJob
(
..
))
import
Gargantext.API.Admin.Orchestrator.Types
(
AsyncJobs
(
..
))
import
Gargantext.API.Admin.Orchestrator.Types
(
AsyncJobs
(
..
))
import
Gargantext.API.Errors.Types
import
Gargantext.API.Errors.Types
import
Gargantext.API.Node.Corpus.Annuaire
qualified
as
Annuaire
import
Gargantext.API.Node.Corpus.Annuaire
qualified
as
Annuaire
import
Gargantext.API.Node.Corpus.New
qualified
as
New
import
Gargantext.API.Prelude
import
Gargantext.API.Prelude
import
Gargantext.API.Routes.Named.Annuaire
qualified
as
Named
import
Gargantext.API.Routes.Named.Annuaire
qualified
as
Named
import
Gargantext.API.Routes.Named.Corpus
qualified
as
Named
import
Gargantext.API.Routes.Named.Corpus
qualified
as
Named
import
Gargantext.Core.Config
(
gc_jobs
,
HasConfig
(
..
))
import
Gargantext.Core.Config.Types
(
jc_max_docs_scrapers
)
import
Gargantext.Core.Types.Individu
(
User
(
..
))
import
Gargantext.Core.Types.Individu
(
User
(
..
))
import
Gargantext.Core.Worker.Jobs
qualified
as
Jobs
import
Gargantext.Core.Worker.Jobs.Types
qualified
as
Jobs
import
Gargantext.Prelude
import
Gargantext.Prelude
import
Gargantext.Utils.Jobs
(
serveJobsAPI
,
MonadJobStatus
(
..
)
)
import
Gargantext.Utils.Jobs
(
serveJobsAPI
)
import
Servant
import
Servant
import
Servant.Auth.Swagger
()
import
Servant.Auth.Swagger
()
import
Servant.Server.Generic
(
AsServerT
)
import
Servant.Server.Generic
(
AsServerT
)
...
@@ -53,9 +48,12 @@ waitAPI n = do
...
@@ -53,9 +48,12 @@ waitAPI n = do
addCorpusWithQuery
::
User
->
Named
.
AddWithQuery
(
AsServerT
(
GargM
Env
BackendInternalError
))
addCorpusWithQuery
::
User
->
Named
.
AddWithQuery
(
AsServerT
(
GargM
Env
BackendInternalError
))
addCorpusWithQuery
user
=
Named
.
AddWithQuery
$
\
cid
->
AsyncJobs
$
addCorpusWithQuery
user
=
Named
.
AddWithQuery
$
\
cid
->
AsyncJobs
$
serveJobsAPI
AddCorpusQueryJob
$
\
jHandle
q
->
do
serveJobsAPI
AddCorpusQueryJob
$
\
_jHandle
q
->
do
limit
<-
view
$
hasConfig
.
gc_jobs
.
jc_max_docs_scrapers
-- limit <- view $ hasConfig . gc_jobs . jc_max_docs_scrapers
New
.
addToCorpusWithQuery
user
cid
q
(
Just
$
fromIntegral
limit
)
jHandle
-- New.addToCorpusWithQuery user cid q (Just $ fromIntegral limit) jHandle
Jobs
.
sendJob
$
Jobs
.
AddCorpusWithQuery
{
Jobs
.
_acq_args
=
q
,
Jobs
.
_acq_user
=
user
,
Jobs
.
_acq_cid
=
cid
}
{- let log' x = do
{- let log' x = do
printDebug "addToCorpusWithQuery" x
printDebug "addToCorpusWithQuery" x
liftBase $ log x
liftBase $ log x
...
@@ -63,11 +61,15 @@ addCorpusWithQuery user = Named.AddWithQuery $ \cid -> AsyncJobs $
...
@@ -63,11 +61,15 @@ addCorpusWithQuery user = Named.AddWithQuery $ \cid -> AsyncJobs $
addCorpusWithForm
::
User
->
Named
.
AddWithForm
(
AsServerT
(
GargM
Env
BackendInternalError
))
addCorpusWithForm
::
User
->
Named
.
AddWithForm
(
AsServerT
(
GargM
Env
BackendInternalError
))
addCorpusWithForm
user
=
Named
.
AddWithForm
$
\
cid
->
AsyncJobs
$
addCorpusWithForm
user
=
Named
.
AddWithForm
$
\
cid
->
AsyncJobs
$
serveJobsAPI
AddCorpusFormJob
$
\
jHandle
i
->
do
serveJobsAPI
AddCorpusFormJob
$
\
_
jHandle
i
->
do
-- /NOTE(adinapoli)/ Track the initial steps outside 'addToCorpusWithForm', because it's
-- /NOTE(adinapoli)/ Track the initial steps outside 'addToCorpusWithForm', because it's
-- called in a few places, and the job status might be different between invocations.
-- called in a few places, and the job status might be different between invocations.
markStarted
3
jHandle
-- markStarted 3 jHandle
New
.
addToCorpusWithForm
user
cid
i
jHandle
-- New.addToCorpusWithForm user cid i jHandle
Jobs
.
sendJob
$
Jobs
.
AddCorpusFormAsync
{
Jobs
.
_acf_args
=
i
,
Jobs
.
_acf_user
=
user
,
Jobs
.
_acf_cid
=
cid
}
--addCorpusWithFile :: User -> ServerT Named.AddWithFile (GargM Env BackendInternalError)
--addCorpusWithFile :: User -> ServerT Named.AddWithFile (GargM Env BackendInternalError)
--addCorpusWithFile user cid =
--addCorpusWithFile user cid =
...
...
src/Gargantext/Core/Config.hs
View file @
02e63fe4
...
@@ -28,6 +28,7 @@ module Gargantext.Core.Config (
...
@@ -28,6 +28,7 @@ module Gargantext.Core.Config (
,
gc_jobs
,
gc_jobs
,
gc_secrets
,
gc_secrets
,
gc_apis
,
gc_apis
,
gc_worker
,
gc_log_level
,
gc_log_level
,
mkProxyUrl
,
mkProxyUrl
...
@@ -42,6 +43,7 @@ import Data.Text as T
...
@@ -42,6 +43,7 @@ import Data.Text as T
import
Database.PostgreSQL.Simple
qualified
as
PSQL
import
Database.PostgreSQL.Simple
qualified
as
PSQL
import
Gargantext.Core.Config.Mail
(
MailConfig
)
import
Gargantext.Core.Config.Mail
(
MailConfig
)
import
Gargantext.Core.Config.NLP
(
NLPConfig
)
import
Gargantext.Core.Config.NLP
(
NLPConfig
)
import
Gargantext.Core.Config.Worker
(
WorkerSettings
)
import
Gargantext.Core.Config.Types
import
Gargantext.Core.Config.Types
import
Gargantext.Prelude
import
Gargantext.Prelude
import
Servant.Auth.Server
(
JWTSettings
)
import
Servant.Auth.Server
(
JWTSettings
)
...
@@ -65,6 +67,7 @@ data GargConfig = GargConfig { _gc_datafilepath :: ~FilePath
...
@@ -65,6 +67,7 @@ data GargConfig = GargConfig { _gc_datafilepath :: ~FilePath
,
_gc_jobs
::
~
JobsConfig
,
_gc_jobs
::
~
JobsConfig
,
_gc_secrets
::
~
SecretsConfig
,
_gc_secrets
::
~
SecretsConfig
,
_gc_apis
::
~
APIsConfig
,
_gc_apis
::
~
APIsConfig
,
_gc_worker
::
~
WorkerSettings
,
_gc_log_level
::
~
LogLevel
,
_gc_log_level
::
~
LogLevel
}
}
deriving
(
Generic
,
Show
)
deriving
(
Generic
,
Show
)
...
@@ -83,6 +86,7 @@ instance FromValue GargConfig where
...
@@ -83,6 +86,7 @@ instance FromValue GargConfig where
_gc_jobs
<-
reqKey
"jobs"
_gc_jobs
<-
reqKey
"jobs"
_gc_apis
<-
reqKey
"apis"
_gc_apis
<-
reqKey
"apis"
_gc_notifications_config
<-
reqKey
"notifications"
_gc_notifications_config
<-
reqKey
"notifications"
_gc_worker
<-
reqKey
"worker"
let
_gc_log_level
=
LevelDebug
let
_gc_log_level
=
LevelDebug
return
$
GargConfig
{
_gc_datafilepath
return
$
GargConfig
{
_gc_datafilepath
,
_gc_jobs
,
_gc_jobs
...
@@ -94,6 +98,7 @@ instance FromValue GargConfig where
...
@@ -94,6 +98,7 @@ instance FromValue GargConfig where
,
_gc_notifications_config
,
_gc_notifications_config
,
_gc_frames
,
_gc_frames
,
_gc_secrets
,
_gc_secrets
,
_gc_worker
,
_gc_log_level
}
,
_gc_log_level
}
instance
ToValue
GargConfig
where
instance
ToValue
GargConfig
where
toValue
=
defaultTableToValue
toValue
=
defaultTableToValue
...
@@ -109,6 +114,7 @@ instance ToTable GargConfig where
...
@@ -109,6 +114,7 @@ instance ToTable GargConfig where
,
"mail"
.=
_gc_mail_config
,
"mail"
.=
_gc_mail_config
,
"notifications"
.=
_gc_notifications_config
,
"notifications"
.=
_gc_notifications_config
,
"nlp"
.=
_gc_nlp_config
,
"nlp"
.=
_gc_nlp_config
,
"worker"
.=
_gc_worker
]
]
...
...
src/Gargantext/Core/Config/Worker.hs
0 → 100644
View file @
02e63fe4
{-|
Module : Gargantext.Core.Config.Worker
Description : Worker TOML file config
Copyright : (c) CNRS, 2024
License : AGPL + CECILL v3
Maintainer : team@gargantext.org
Stability : experimental
Portability : POSIX
Although Async.Worker.Broker supports various Broker types, in
Gargantext we will only use PGMQ. This makes for easier config,
simpler design. Also, the DevOps stuff is simpler (providing multiple
brokers at the same time could lead to complexities in analyzing
what's going on).
If need arises, we could switch to a different broker by rewriting its
initialization. At the same time, sending and executing jobs should be
broker-agnostic.
-}
module
Gargantext.Core.Config.Worker
where
import
Async.Worker.Broker.Types
qualified
as
Broker
import
Database.PGMQ.Types
qualified
as
PGMQ
import
Database.PostgreSQL.Simple
qualified
as
PGS
import
Gargantext.Core.Config.Types
(
unTOMLConnectInfo
,
TOMLConnectInfo
(
..
))
import
Gargantext.Prelude
import
Toml.Schema
type
WorkerName
=
Text
data
WorkerSettings
=
WorkerSettings
{
_wsDatabase
::
!
PGS
.
ConnectInfo
-- After this number of seconds, the job will be available again.
-- You can set timeout for each job individually and this is the
-- preferred method over using defaultVt.
,
_wsDefaultVisibilityTimeout
::
PGMQ
.
VisibilityTimeout
,
_wsDefinitions
::
!
[
WorkerDefinition
]
}
deriving
(
Show
,
Eq
)
instance
FromValue
WorkerSettings
where
fromValue
=
parseTableFromValue
$
do
dbConfig
<-
reqKey
"database"
_wsDefinitions
<-
reqKey
"definitions"
_wsDefaultVisibilityTimeout
<-
reqKey
"default_visibility_timeout"
return
$
WorkerSettings
{
_wsDatabase
=
unTOMLConnectInfo
dbConfig
,
_wsDefinitions
,
_wsDefaultVisibilityTimeout
}
instance
ToValue
WorkerSettings
where
toValue
=
defaultTableToValue
instance
ToTable
WorkerSettings
where
toTable
(
WorkerSettings
{
..
})
=
table
[
"database"
.=
TOMLConnectInfo
_wsDatabase
,
"default_visibility_timeout"
.=
_wsDefaultVisibilityTimeout
,
"definitions"
.=
_wsDefinitions
]
data
WorkerDefinition
=
WorkerDefinition
{
_wdName
::
!
WorkerName
,
_wdQueue
::
!
Broker
.
Queue
}
deriving
(
Show
,
Eq
)
instance
FromValue
WorkerDefinition
where
fromValue
=
parseTableFromValue
$
do
_wdName
<-
reqKey
"name"
queue
<-
reqKey
"queue"
return
$
WorkerDefinition
{
_wdQueue
=
Broker
.
Queue
queue
,
..
}
instance
ToValue
WorkerDefinition
where
toValue
=
defaultTableToValue
instance
ToTable
WorkerDefinition
where
toTable
(
WorkerDefinition
{
..
})
=
table
[
"name"
.=
_wdName
,
"queue"
.=
Broker
.
_Queue
_wdQueue
]
findDefinitionByName
::
WorkerSettings
->
WorkerName
->
Maybe
WorkerDefinition
findDefinitionByName
(
WorkerSettings
{
_wsDefinitions
})
workerName
=
head
$
filter
(
\
wd
->
_wdName
wd
==
workerName
)
_wsDefinitions
-- wdToRedisBrokerInitParams :: WorkerDefinition -> Maybe BRedis.RedisBrokerInitParams
-- wdToRedisBrokerInitParams wd = BRedis.RedisBrokerInitParams <$> (wdToRedisConnectInfo wd)
src/Gargantext/Core/Types/Individu.hs
View file @
02e63fe4
...
@@ -31,6 +31,7 @@ import Prelude qualified
...
@@ -31,6 +31,7 @@ import Prelude qualified
data
User
=
UserDBId
UserId
|
UserName
Text
|
RootId
NodeId
data
User
=
UserDBId
UserId
|
UserName
Text
|
RootId
NodeId
deriving
(
Show
,
Eq
,
Generic
)
deriving
(
Show
,
Eq
,
Generic
)
instance
FromJSON
User
instance
ToJSON
User
instance
ToJSON
User
renderUser
::
User
->
T
.
Text
renderUser
::
User
->
T
.
Text
...
...
src/Gargantext/Core/Worker.hs
0 → 100644
View file @
02e63fe4
{-|
Module : Gargantext.Core.Worker
Description : Asynchronous worker logic
Copyright : (c) CNRS, 2024
License : AGPL + CECILL v3
Maintainer : team@gargantext.org
Stability : experimental
Portability : POSIX
-}
{-# LANGUAGE UndecidableInstances #-}
{-# OPTIONS_GHC -Wno-orphans #-}
-- orphan HasNodeError IOException
module
Gargantext.Core.Worker
where
import
Async.Worker.Broker.PGMQ
(
PGMQBroker
)
import
Async.Worker.Broker.Types
(
BrokerMessage
,
toA
,
getMessage
)
import
Async.Worker
qualified
as
Worker
import
Async.Worker.Types
qualified
as
Worker
import
Async.Worker.Types
(
HasWorkerBroker
)
import
Data.Text
qualified
as
T
import
Gargantext.API.Admin.Auth
(
forgotUserPassword
)
import
Gargantext.API.Admin.Auth.Types
(
ForgotPasswordAsyncParams
(
..
))
import
Gargantext.API.Node.Corpus.New
(
addToCorpusWithForm
,
addToCorpusWithQuery
)
import
Gargantext.API.Node.New
(
postNode'
)
import
Gargantext.Core.Config
(
hasConfig
,
gc_jobs
)
import
Gargantext.Core.Config.Types
(
jc_max_docs_scrapers
)
import
Gargantext.Core.Config.Worker
(
WorkerDefinition
(
..
))
import
Gargantext.Core.Worker.Broker
(
initBrokerWithDBCreate
)
import
Gargantext.Core.Worker.Env
import
Gargantext.Core.Worker.Jobs.Types
(
Job
(
..
))
import
Gargantext.Database.Query.Table.User
(
getUsersWithEmail
)
import
Gargantext.Prelude
import
Gargantext.Utils.Jobs.Monad
(
MonadJobStatus
(
noJobHandle
)
)
-- | Spawn a worker with PGMQ broker
-- TODO:
-- - reduce size of DB pool
-- - progress report via notifications
-- - I think there is no point to save job result, as usually there is none (we have side-effects only)
-- - replace Servant.Job to use workers instead of garg API threads
withPGMQWorker
::
(
HasWorkerBroker
PGMQBroker
Job
)
=>
WorkerEnv
->
WorkerDefinition
->
(
Async
()
->
Worker
.
State
PGMQBroker
Job
->
IO
()
)
->
IO
()
withPGMQWorker
env
(
WorkerDefinition
{
..
})
cb
=
do
let
gargConfig
=
env
^.
hasConfig
broker
<-
initBrokerWithDBCreate
gargConfig
let
state'
=
Worker
.
State
{
broker
,
queueName
=
_wdQueue
,
name
=
T
.
unpack
_wdName
,
performAction
=
performAction
env
,
onMessageReceived
=
Nothing
,
onJobFinish
=
Nothing
,
onJobTimeout
=
Nothing
,
onJobError
=
Nothing
}
withAsync
(
Worker
.
run
state'
)
(
\
a
->
cb
a
state'
)
withPGMQWorkerSingle
::
(
HasWorkerBroker
PGMQBroker
Job
)
=>
WorkerEnv
->
WorkerDefinition
->
(
Async
()
->
Worker
.
State
PGMQBroker
Job
->
IO
()
)
->
IO
()
withPGMQWorkerSingle
env
(
WorkerDefinition
{
..
})
cb
=
do
let
gargConfig
=
env
^.
hasConfig
broker
<-
initBrokerWithDBCreate
gargConfig
let
state'
=
Worker
.
State
{
broker
,
queueName
=
_wdQueue
,
name
=
T
.
unpack
_wdName
,
performAction
=
performAction
env
,
onMessageReceived
=
Nothing
,
onJobFinish
=
Nothing
,
onJobTimeout
=
Nothing
,
onJobError
=
Nothing
}
withAsync
(
Worker
.
runSingle
state'
)
(
\
a
->
cb
a
state'
)
-- | How the worker should process jobs
performAction
::
(
HasWorkerBroker
b
Job
)
=>
WorkerEnv
->
Worker
.
State
b
Job
->
BrokerMessage
b
(
Worker
.
Job
Job
)
->
IO
()
performAction
env
_state
bm
=
do
let
job'
=
toA
$
getMessage
bm
case
Worker
.
job
job'
of
Ping
->
putStrLn
(
"ping"
::
Text
)
AddCorpusFormAsync
{
..
}
->
runWorkerMonad
env
$
do
liftBase
$
putStrLn
(
"add corpus form"
::
Text
)
addToCorpusWithForm
_acf_user
_acf_cid
_acf_args
(
noJobHandle
(
Proxy
::
Proxy
WorkerMonad
))
AddCorpusWithQuery
{
..
}
->
runWorkerMonad
env
$
do
liftBase
$
putStrLn
(
"add corpus with query"
::
Text
)
let
limit
=
Just
$
fromIntegral
$
env
^.
hasConfig
.
gc_jobs
.
jc_max_docs_scrapers
addToCorpusWithQuery
_acq_user
_acq_cid
_acq_args
limit
(
noJobHandle
(
Proxy
::
Proxy
WorkerMonad
))
ForgotPasswordAsync
{
_fpa_args
=
ForgotPasswordAsyncParams
{
email
}
}
->
runWorkerMonad
env
$
do
liftBase
$
putStrLn
(
"forgot password: "
<>
email
)
us
<-
getUsersWithEmail
(
T
.
toLower
email
)
case
us
of
[
u
]
->
forgotUserPassword
u
_
->
pure
()
NewNodeAsync
{
..
}
->
runWorkerMonad
env
$
do
liftBase
$
putStrLn
(
"new node async "
::
Text
)
void
$
postNode'
_nna_authenticatedUser
_nna_node_id
_nna_postNode
return
()
GargJob
{
_gj_garg_job
}
->
putStrLn
(
"Garg job: "
<>
show
_gj_garg_job
<>
" (handling of this job is still not implemented!)"
::
Text
)
src/Gargantext/Core/Worker/Broker.hs
0 → 100644
View file @
02e63fe4
{-# LANGUAGE TupleSections #-}
module
Gargantext.Core.Worker.Broker
(
initBrokerWithDBCreate
)
where
import
Async.Worker.Broker.PGMQ
(
PGMQBroker
,
BrokerInitParams
(
PGMQBrokerInitParams
))
import
Async.Worker.Broker.Types
(
Broker
,
initBroker
)
import
Async.Worker.Types
qualified
as
WorkerT
import
Data.Text
qualified
as
T
import
Data.Text.Encoding
qualified
as
TE
import
Database.PostgreSQL.Simple
qualified
as
PSQL
import
Gargantext.Core.Config
(
GargConfig
(
..
),
gc_worker
)
import
Gargantext.Core.Config.Worker
(
WorkerSettings
(
..
))
import
Gargantext.Core.Worker.Jobs.Types
(
Job
(
..
))
import
Gargantext.Prelude
import
Shelly
qualified
as
SH
-- | Create DB if not exists, then run 'initBroker' (which, in
-- particular, creates the pgmq extension, if needed)
initBrokerWithDBCreate
::
(
WorkerT
.
HasWorkerBroker
PGMQBroker
Job
)
=>
GargConfig
->
IO
(
Broker
PGMQBroker
(
WorkerT
.
Job
Job
))
initBrokerWithDBCreate
gc
@
(
GargConfig
{
_gc_database_config
})
=
do
-- By using gargantext db credentials, we create pgmq db (if needed)
let
WorkerSettings
{
..
}
=
gc
^.
gc_worker
let
psqlDB
=
TE
.
decodeUtf8
$
PSQL
.
postgreSQLConnectionString
_gc_database_config
-- For the \gexec trick, see:
-- https://stackoverflow.com/questions/18389124/simulate-create-database-if-not-exists-for-postgresql
(
_res
,
_ec
)
<-
SH
.
shelly
$
SH
.
silently
$
SH
.
escaping
False
$
do
let
sql
=
"
\"
SELECT 'CREATE DATABASE "
<>
(
T
.
pack
$
PSQL
.
connectDatabase
_wsDatabase
)
<>
"' WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = '"
<>
(
T
.
pack
$
PSQL
.
connectDatabase
_wsDatabase
)
<>
"')
\\
gexec
\"
"
result
<-
SH
.
run
"echo"
[
sql
,
"|"
,
"psql"
,
"-d"
,
"
\"
"
<>
psqlDB
<>
"
\"
"
]
(
result
,)
<$>
SH
.
lastExitCode
initBroker
$
PGMQBrokerInitParams
_wsDatabase
_wsDefaultVisibilityTimeout
src/Gargantext/Core/Worker/Env.hs
View file @
02e63fe4
...
@@ -24,8 +24,7 @@ import Data.Text qualified as T
...
@@ -24,8 +24,7 @@ import Data.Text qualified as T
import
Database.PostgreSQL.Simple
(
Connection
)
import
Database.PostgreSQL.Simple
(
Connection
)
import
Gargantext.API.Admin.EnvTypes
(
ConcreteJobHandle
,
GargJob
,
Mode
(
Dev
),
modeToLoggingLevels
)
import
Gargantext.API.Admin.EnvTypes
(
ConcreteJobHandle
,
GargJob
,
Mode
(
Dev
),
modeToLoggingLevels
)
import
Gargantext.API.Admin.Orchestrator.Types
(
JobLog
,
noJobLog
)
import
Gargantext.API.Admin.Orchestrator.Types
(
JobLog
,
noJobLog
)
import
Gargantext.API.Admin.Settings
(
devSettings
,
newPool
)
import
Gargantext.API.Admin.Settings
(
newPool
)
import
Gargantext.API.Admin.Types
(
HasSettings
(
..
),
Settings
(
..
))
import
Gargantext.API.Prelude
(
GargM
)
import
Gargantext.API.Prelude
(
GargM
)
import
Gargantext.Core.Notifications.CentralExchange
qualified
as
CE
import
Gargantext.Core.Notifications.CentralExchange
qualified
as
CE
import
Gargantext.Core.Notifications.CentralExchange.Types
qualified
as
CET
import
Gargantext.Core.Notifications.CentralExchange.Types
qualified
as
CET
...
@@ -49,8 +48,7 @@ import System.Log.FastLogger qualified as FL
...
@@ -49,8 +48,7 @@ import System.Log.FastLogger qualified as FL
data
WorkerEnv
=
WorkerEnv
data
WorkerEnv
=
WorkerEnv
{
_w_env_settings
::
!
Settings
{
_w_env_config
::
!
GargConfig
,
_w_env_config
::
!
GargConfig
,
_w_env_logger
::
!
(
Logger
(
GargM
WorkerEnv
IOException
))
,
_w_env_logger
::
!
(
Logger
(
GargM
WorkerEnv
IOException
))
,
_w_env_pool
::
!
(
Pool
Connection
)
,
_w_env_pool
::
!
(
Pool
Connection
)
,
_w_env_nodeStory
::
!
NodeStoryEnv
,
_w_env_nodeStory
::
!
NodeStoryEnv
...
@@ -70,12 +68,10 @@ withWorkerEnv settingsFile k = withLoggerHoisted Dev $ \logger -> do
...
@@ -70,12 +68,10 @@ withWorkerEnv settingsFile k = withLoggerHoisted Dev $ \logger -> do
--nodeStory_env <- fromDBNodeStoryEnv (_gc_repofilepath cfg)
--nodeStory_env <- fromDBNodeStoryEnv (_gc_repofilepath cfg)
pool
<-
newPool
$
_gc_database_config
cfg
pool
<-
newPool
$
_gc_database_config
cfg
nodeStory_env
<-
fromDBNodeStoryEnv
pool
nodeStory_env
<-
fromDBNodeStoryEnv
pool
let
setts
=
devSettings
pure
$
WorkerEnv
pure
$
WorkerEnv
{
_w_env_pool
=
pool
{
_w_env_pool
=
pool
,
_w_env_logger
=
logger
,
_w_env_logger
=
logger
,
_w_env_nodeStory
=
nodeStory_env
,
_w_env_nodeStory
=
nodeStory_env
,
_w_env_settings
=
setts
,
_w_env_config
=
cfg
,
_w_env_config
=
cfg
,
_w_env_mail
=
_gc_mail_config
cfg
,
_w_env_mail
=
_gc_mail_config
cfg
,
_w_env_nlp
=
nlpServerMap
$
_gc_nlp_config
cfg
,
_w_env_nlp
=
nlpServerMap
$
_gc_nlp_config
cfg
...
@@ -84,9 +80,6 @@ withWorkerEnv settingsFile k = withLoggerHoisted Dev $ \logger -> do
...
@@ -84,9 +80,6 @@ withWorkerEnv settingsFile k = withLoggerHoisted Dev $ \logger -> do
instance
HasConfig
WorkerEnv
where
instance
HasConfig
WorkerEnv
where
hasConfig
=
to
_w_env_config
hasConfig
=
to
_w_env_config
instance
HasSettings
WorkerEnv
where
settings
=
to
_w_env_settings
instance
HasLogger
(
GargM
WorkerEnv
IOException
)
where
instance
HasLogger
(
GargM
WorkerEnv
IOException
)
where
data
instance
Logger
(
GargM
WorkerEnv
IOException
)
=
data
instance
Logger
(
GargM
WorkerEnv
IOException
)
=
GargWorkerLogger
{
GargWorkerLogger
{
...
...
src/Gargantext/Core/Worker/Jobs.hs
View file @
02e63fe4
...
@@ -13,43 +13,39 @@ Portability : POSIX
...
@@ -13,43 +13,39 @@ Portability : POSIX
module
Gargantext.Core.Worker.Jobs
where
module
Gargantext.Core.Worker.Jobs
where
import
Async.Worker.Broker.Redis
(
RedisBroker
,
BrokerInitParams
(
RedisBrokerInitParams
))
import
Async.Worker.Broker.PGMQ
(
PGMQBroker
)
import
Async.Worker.Broker.Types
(
Broker
,
initBroker
)
import
Async.Worker
qualified
as
Worker
import
Async.Worker
qualified
as
Worker
import
Async.Worker.Types
qualified
as
Worker
import
Async.Worker.Types
(
HasWorkerBroker
)
import
Async.Worker.Types
(
HasWorkerBroker
)
import
Control.Lens
(
view
)
import
Control.Lens
(
view
)
import
Database.Redis
qualified
as
Redi
s
import
Gargantext.API.Admin.EnvTypes
qualified
as
EnvType
s
import
Gargantext.Core.Config
(
gc_worker
,
HasConfig
(
..
))
import
Gargantext.Core.Config
(
gc_worker
,
HasConfig
(
..
))
import
Gargantext.Core.Config.Worker
(
WorkerSettings
(
..
),
WorkerDefinition
(
..
),
wdToRedisConnectInfo
)
import
Gargantext.Core.Config.Worker
(
WorkerSettings
(
..
),
WorkerDefinition
(
..
))
import
Gargantext.Core.Worker.Broker
(
initBrokerWithDBCreate
)
import
Gargantext.Core.Worker.Jobs.Types
(
Job
(
..
))
import
Gargantext.Core.Worker.Jobs.Types
(
Job
(
..
))
import
Gargantext.Database.Prelude
(
Cmd
'
)
import
Gargantext.Database.Prelude
(
Cmd
'
)
import
Gargantext.Prelude
import
Gargantext.Prelude
initializeRedisBroker
::
(
HasWorkerBroker
RedisBroker
Job
)
sendJob
::
(
HasWorkerBroker
PGMQBroker
Job
,
HasConfig
env
)
=>
Redis
.
ConnectInfo
->
IO
(
Broker
RedisBroker
(
Worker
.
Job
Job
))
initializeRedisBroker
connInfo
=
do
let
initParams
=
RedisBrokerInitParams
connInfo
initBroker
initParams
sendJob
::
(
HasWorkerBroker
RedisBroker
Job
,
HasConfig
env
)
=>
Job
=>
Job
->
Cmd'
env
err
()
->
Cmd'
env
err
()
sendJob
job
=
do
sendJob
job
=
do
ws
<-
view
$
hasConfig
.
gc_worker
gcConfig
<-
view
$
hasConfig
let
WorkerSettings
{
_wsDefinitions
}
=
gcConfig
^.
gc_worker
-- TODO Try to guess which worker should get this job
-- TODO Try to guess which worker should get this job
-- let mWd = findDefinitionByName ws workerName
-- let mWd = findDefinitionByName ws workerName
let
mWd
=
head
$
_wsDefinitions
w
s
let
mWd
=
head
_wsDefinition
s
case
mWd
of
case
mWd
of
Nothing
->
panicTrace
$
"worker definition not found
"
Nothing
->
panicTrace
"No worker definitions available
"
Just
wd
->
liftBase
$
do
Just
wd
->
liftBase
$
do
case
wdToRedisConnectInfo
wd
of
b
<-
initBrokerWithDBCreate
gcConfig
Nothing
->
panicTrace
$
"worker definition: could not create redis conn info"
let
queueName
=
_wdQueue
wd
Just
connInfo
->
do
void
$
Worker
.
sendJob'
$
Worker
.
mkDefaultSendJob'
b
queueName
job
b
<-
initializeRedisBroker
connInfo
let
queueName
=
_wdQueue
wd
void
$
Worker
.
sendJob'
$
Worker
.
mkDefaultSendJob'
b
queueName
job
-- | This is just a list of what's implemented and what not.
-- After we migrate to async workers, this should be removed
-- (see G.C.Worker -> performAction on what's implemented already)
handledJobs
::
[
EnvTypes
.
GargJob
]
handledJobs
=
[
EnvTypes
.
AddCorpusQueryJob
,
EnvTypes
.
ForgotPasswordJob
]
src/Gargantext/Core/Worker/Jobs/Types.hs
0 → 100644
View file @
02e63fe4
{-|
Module : Gargantext.Core.Worker.Jobs.Types
Description : Worker job definitions
Copyright : (c) CNRS, 2024-Present
License : AGPL + CECILL v3
Maintainer : team@gargantext.org
Stability : experimental
Portability : POSIX
-}
module
Gargantext.Core.Worker.Jobs.Types
where
import
Data.Aeson
((
.:
),
(
.=
),
object
,
withObject
)
import
Data.Aeson.Types
(
prependFailure
,
typeMismatch
)
import
Gargantext.API.Admin.Auth.Types
(
AuthenticatedUser
,
ForgotPasswordAsyncParams
)
import
Gargantext.API.Admin.EnvTypes
(
GargJob
)
import
Gargantext.API.Node.New.Types
(
PostNode
(
..
)
)
import
Gargantext.API.Node.Types
(
NewWithForm
,
WithQuery
)
import
Gargantext.Core.Types.Individu
(
User
)
import
Gargantext.Database.Admin.Types.Node
(
CorpusId
,
NodeId
)
import
Gargantext.Prelude
data
Job
=
Ping
|
AddCorpusFormAsync
{
_acf_args
::
NewWithForm
,
_acf_user
::
User
,
_acf_cid
::
CorpusId
}
|
AddCorpusWithQuery
{
_acq_args
::
WithQuery
,
_acq_user
::
User
,
_acq_cid
::
CorpusId
}
|
ForgotPasswordAsync
{
_fpa_args
::
ForgotPasswordAsyncParams
}
|
NewNodeAsync
{
_nna_node_id
::
NodeId
,
_nna_authenticatedUser
::
AuthenticatedUser
,
_nna_postNode
::
PostNode
}
|
GargJob
{
_gj_garg_job
::
GargJob
}
deriving
(
Show
,
Eq
)
instance
FromJSON
Job
where
parseJSON
=
withObject
"Job"
$
\
o
->
do
type_
<-
o
.:
"type"
case
type_
of
"Ping"
->
return
Ping
"AddCorpusFormAsync"
->
do
_acf_args
<-
o
.:
"args"
_acf_user
<-
o
.:
"user"
_acf_cid
<-
o
.:
"cid"
return
$
AddCorpusFormAsync
{
..
}
"AddCorpusWithQuery"
->
do
_acq_args
<-
o
.:
"args"
_acq_user
<-
o
.:
"user"
_acq_cid
<-
o
.:
"cid"
return
$
AddCorpusWithQuery
{
..
}
"ForgotPasswordAsync"
->
do
_fpa_args
<-
o
.:
"args"
return
$
ForgotPasswordAsync
{
_fpa_args
}
"NewNodeAsync"
->
do
_nna_node_id
<-
o
.:
"node_id"
_nna_authenticatedUser
<-
o
.:
"authenticated_user"
_nna_postNode
<-
o
.:
"post_node"
return
$
NewNodeAsync
{
..
}
"GargJob"
->
do
_gj_garg_job
<-
o
.:
"garg_job"
return
$
GargJob
{
_gj_garg_job
}
s
->
prependFailure
"parsing job type failed, "
(
typeMismatch
"type"
s
)
instance
ToJSON
Job
where
toJSON
Ping
=
object
[
(
"type"
.=
(
"Ping"
::
Text
))
]
toJSON
(
AddCorpusFormAsync
{
..
})
=
object
[
(
"type"
.=
(
"AddCorpusFormJob"
::
Text
))
,
(
"args"
.=
_acf_args
)
,
(
"user"
.=
_acf_user
)
,
(
"cid"
.=
_acf_cid
)
]
toJSON
(
AddCorpusWithQuery
{
..
})
=
object
[
(
"type"
.=
(
"AddCorpusWithQuery"
::
Text
))
,
(
"args"
.=
_acq_args
)
,
(
"user"
.=
_acq_user
)
,
(
"cid"
.=
_acq_cid
)
]
toJSON
(
ForgotPasswordAsync
{
..
})
=
object
[
(
"type"
.=
(
"ForgotPasswordAsync"
::
Text
))
,
(
"args"
.=
_fpa_args
)
]
toJSON
(
NewNodeAsync
{
..
})
=
object
[
(
"type"
.=
(
"NewNodeAsync"
::
Text
))
,
(
"node_id"
.=
_nna_node_id
)
,
(
"authenticated_user"
.=
_nna_authenticatedUser
)
,
(
"post_node"
.=
_nna_postNode
)
]
toJSON
(
GargJob
{
..
})
=
object
[
(
"type"
.=
(
"GargJob"
::
Text
))
,
(
"garg_job"
.=
_gj_garg_job
)
]
src/Gargantext/Database/Query/Table/Node/Update.hs
View file @
02e63fe4
...
@@ -14,7 +14,7 @@ module Gargantext.Database.Query.Table.Node.Update (Update(..), update)
...
@@ -14,7 +14,7 @@ module Gargantext.Database.Query.Table.Node.Update (Update(..), update)
import
Data.Text
qualified
as
DT
import
Data.Text
qualified
as
DT
import
Database.PostgreSQL.Simple
(
Only
(
Only
)
)
import
Database.PostgreSQL.Simple
(
Only
(
Only
)
)
import
Gargantext.Core.
Notification
s.CentralExchange.Types
qualified
as
CE
import
Gargantext.Core.
AsyncUpdate
s.CentralExchange.Types
qualified
as
CE
import
Gargantext.Core.Types
(
Name
)
import
Gargantext.Core.Types
(
Name
)
import
Gargantext.Database.Admin.Types.Node
(
NodeId
,
ParentId
)
import
Gargantext.Database.Admin.Types.Node
(
NodeId
,
ParentId
)
import
Gargantext.Database.Query.Table.Node
(
getParentId
)
import
Gargantext.Database.Query.Table.Node
(
getParentId
)
...
...
src/Gargantext/Utils/Jobs.hs
View file @
02e63fe4
...
@@ -22,22 +22,20 @@ module Gargantext.Utils.Jobs (
...
@@ -22,22 +22,20 @@ module Gargantext.Utils.Jobs (
,
markFailedNoErr
,
markFailedNoErr
)
where
)
where
import
Control.Monad.Except
(
runExceptT
)
import
Data.Text
qualified
as
T
import
Control.Monad.Reader
(
MonadReader
(
ask
),
ReaderT
(
runReaderT
)
)
import
Gargantext.API.Admin.EnvTypes
(
mkJobHandle
,
parseGargJob
,
Env
,
GargJob
(
..
)
)
import
Data.Aeson
(
ToJSON
)
import
Prelude
import
System.Directory
(
doesFileExist
)
import
Text.Read
(
readMaybe
)
import
qualified
Data.Text
as
T
import
Gargantext.API.Admin.EnvTypes
(
mkJobHandle
,
Env
,
GargJob
(
..
)
)
import
Gargantext.API.Errors.Types
(
BackendInternalError
(
InternalJobError
)
)
import
Gargantext.API.Errors.Types
(
BackendInternalError
(
InternalJobError
)
)
import
Gargantext.API.Prelude
(
GargM
)
import
Gargantext.API.Prelude
(
GargM
)
import
qualified
Gargantext.Utils.Jobs.Internal
as
Internal
import
Gargantext.Core.Worker.Jobs
qualified
as
Jobs
import
Gargantext.Utils.Jobs.Monad
(
JobError
,
MonadJobStatus
(
..
),
markFailureNoErr
,
markFailedNoErr
)
import
Gargantext.Core.Worker.Jobs.Types
qualified
as
Jobs
import
Gargantext.Prelude
import
Gargantext.System.Logging
import
Gargantext.System.Logging
import
Gargantext.Utils.Jobs.Internal
qualified
as
Internal
import
Gargantext.Utils.Jobs.Monad
(
JobError
,
MonadJobStatus
(
..
),
markFailureNoErr
,
markFailedNoErr
)
-- import Prelude
import
Servant.Job.Async
qualified
as
SJ
import
System.Directory
(
doesFileExist
)
import
qualified
Servant.Job.Async
as
SJ
jobErrorToGargError
jobErrorToGargError
::
JobError
->
BackendInternalError
::
JobError
->
BackendInternalError
...
@@ -61,38 +59,21 @@ serveJobsAPI
...
@@ -61,38 +59,21 @@ serveJobsAPI
serveJobsAPI
jobType
f
=
Internal
.
serveJobsAPI
mkJobHandle
ask
jobType
jobErrorToGargError
$
\
env
jHandle
i
->
do
serveJobsAPI
jobType
f
=
Internal
.
serveJobsAPI
mkJobHandle
ask
jobType
jobErrorToGargError
$
\
env
jHandle
i
->
do
runExceptT
$
flip
runReaderT
env
$
do
runExceptT
$
flip
runReaderT
env
$
do
$
(
logLocM
)
INFO
(
T
.
pack
$
"Running job of type: "
++
show
jobType
)
$
(
logLocM
)
INFO
(
T
.
pack
$
"Running job of type: "
++
show
jobType
)
unless
(
jobType
`
elem
`
Jobs
.
handledJobs
)
$
Jobs
.
sendJob
$
Jobs
.
GargJob
{
Jobs
.
_gj_garg_job
=
jobType
}
f
jHandle
i
f
jHandle
i
getLatestJobStatus
jHandle
getLatestJobStatus
jHandle
parseGargJob
::
String
->
Maybe
GargJob
parsePrios
::
[
Text
]
->
IO
[(
GargJob
,
Int
)]
parseGargJob
s
=
case
s
of
"tablengrams"
->
Just
TableNgramsJob
"forgotpassword"
->
Just
ForgotPasswordJob
"updatengramslistjson"
->
Just
UpdateNgramsListJobJSON
"updatengramslisttsv"
->
Just
UpdateNgramsListJobTSV
"addcontact"
->
Just
AddContactJob
"addfile"
->
Just
AddFileJob
"documentfromwritenode"
->
Just
DocumentFromWriteNodeJob
"updatenode"
->
Just
UpdateNodeJob
"updateframecalc"
->
Just
UploadFrameCalcJob
"updatedocument"
->
Just
UploadDocumentJob
"newnode"
->
Just
NewNodeJob
"addcorpusquery"
->
Just
AddCorpusQueryJob
"addcorpusform"
->
Just
AddCorpusFormJob
"addcorpusfile"
->
Just
AddCorpusFileJob
"addannuaireform"
->
Just
AddAnnuaireFormJob
"recomputegraph"
->
Just
RecomputeGraphJob
_
->
Nothing
parsePrios
::
[
String
]
->
IO
[(
GargJob
,
Int
)]
parsePrios
[]
=
pure
[]
parsePrios
[]
=
pure
[]
parsePrios
(
x
:
xs
)
=
(
:
)
<$>
go
x
<*>
parsePrios
xs
parsePrios
(
x
:
xs
)
=
(
:
)
<$>
go
(
T
.
unpack
x
)
<*>
parsePrios
xs
where
go
s
=
case
break
(
==
'='
)
s
of
where
(
[]
,
_
)
->
error
"parsePrios: empty jobname?"
go
s
=
case
break
(
==
'='
)
s
of
(
[]
,
_
)
->
errorTrace
"parsePrios: empty jobname?"
(
prop
,
valS
)
(
prop
,
valS
)
|
Just
val
<-
readMaybe
(
tail
valS
)
|
Just
val
<-
readMaybe
(
T
.
tail
$
T
.
pack
valS
)
,
Just
j
<-
parseGargJob
prop
->
pure
(
j
,
val
)
,
Just
j
<-
parseGargJob
(
T
.
pack
prop
)
->
pure
(
j
,
val
)
|
otherwise
->
error
$
|
otherwise
->
error
Trace
$
"parsePrios: invalid input. "
++
show
(
prop
,
valS
)
"parsePrios: invalid input. "
++
show
(
prop
,
valS
)
readPrios
::
Logger
IO
->
FilePath
->
IO
[(
GargJob
,
Int
)]
readPrios
::
Logger
IO
->
FilePath
->
IO
[(
GargJob
,
Int
)]
...
...
src/Gargantext/Utils/Jobs/Internal.hs
View file @
02e63fe4
{-|
Module : Gargantext.Utils.Jobs.Internal
Description : Servant Jobs
Copyright : (c) CNRS, 2024-Present
License : AGPL + CECILL v3
Maintainer : team@gargantext.org
Stability : experimental
Portability : POSIX
-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE ViewPatterns #-}
{-# LANGUAGE ViewPatterns #-}
module
Gargantext.Utils.Jobs.Internal
(
module
Gargantext.Utils.Jobs.Internal
(
serveJobsAPI
serveJobsAPI
-- * Internals for testing
-- * Internals for testing
...
...
stack.yaml
View file @
02e63fe4
...
@@ -17,6 +17,7 @@
...
@@ -17,6 +17,7 @@
-
"
binary-orphans-1.0.5"
-
"
binary-orphans-1.0.5"
-
"
blaze-html-0.9.2.0"
-
"
blaze-html-0.9.2.0"
-
"
boring-0.2.2"
-
"
boring-0.2.2"
-
"
bytestring-lexing-0.5.0.14"
-
"
bzlib-conduit-0.3.0.3"
-
"
bzlib-conduit-0.3.0.3"
-
"
cabal-doctest-1.0.10"
-
"
cabal-doctest-1.0.10"
-
"
cassava-0.5.3.2"
-
"
cassava-0.5.3.2"
...
@@ -62,6 +63,7 @@
...
@@ -62,6 +63,7 @@
-
"
language-c-0.9.3"
-
"
language-c-0.9.3"
-
"
libyaml-0.1.4"
-
"
libyaml-0.1.4"
-
"
libyaml-clib-0.2.5"
-
"
libyaml-clib-0.2.5"
-
"
linear-1.23"
-
"
logict-0.8.1.0"
-
"
logict-0.8.1.0"
-
"
lzma-0.0.1.1"
-
"
lzma-0.0.1.1"
-
"
math-functions-0.3.4.4"
-
"
math-functions-0.3.4.4"
...
@@ -127,6 +129,7 @@
...
@@ -127,6 +129,7 @@
-
"
type-equality-1.0.1"
-
"
type-equality-1.0.1"
-
"
typed-process-0.2.12.0"
-
"
typed-process-0.2.12.0"
-
"
unicode-collation-0.1.3.6"
-
"
unicode-collation-0.1.3.6"
-
"
units-2.4.1.5"
-
"
unix-compat-0.7.2"
-
"
unix-compat-0.7.2"
-
"
unix-time-0.4.15"
-
"
unix-time-0.4.15"
-
"
unordered-containers-0.2.20"
-
"
unordered-containers-0.2.20"
...
@@ -257,6 +260,10 @@
...
@@ -257,6 +260,10 @@
git
:
"
https://gitlab.iscpif.fr/gargantext/gargantext-graph.git"
git
:
"
https://gitlab.iscpif.fr/gargantext/gargantext-graph.git"
subdirs
:
subdirs
:
-
.
-
.
-
commit
:
58ab07e0110281f94ecc8840b8cd0c0a9081b672
git
:
"
https://gitlab.iscpif.fr/gargantext/haskell-bee"
subdirs
:
-
.
-
commit
:
bb15d828d5ef36eeaa84cccb00598b585048c88e
-
commit
:
bb15d828d5ef36eeaa84cccb00598b585048c88e
git
:
"
https://gitlab.iscpif.fr/gargantext/haskell-gargantext-prelude"
git
:
"
https://gitlab.iscpif.fr/gargantext/haskell-gargantext-prelude"
subdirs
:
subdirs
:
...
@@ -269,6 +276,10 @@
...
@@ -269,6 +276,10 @@
git
:
"
https://gitlab.iscpif.fr/gargantext/haskell-infomap.git"
git
:
"
https://gitlab.iscpif.fr/gargantext/haskell-infomap.git"
subdirs
:
subdirs
:
-
.
-
.
-
commit
:
0591a643d8ba1776af4fac56c1e4ff5fc3e98bb3
git
:
"
https://gitlab.iscpif.fr/gargantext/haskell-pgmq"
subdirs
:
-
.
-
commit
:
02f5ed9ee2d6cce45161addf945b88bc6adf9059
-
commit
:
02f5ed9ee2d6cce45161addf945b88bc6adf9059
git
:
"
https://gitlab.iscpif.fr/gargantext/haskell-throttle"
git
:
"
https://gitlab.iscpif.fr/gargantext/haskell-throttle"
subdirs
:
subdirs
:
...
@@ -301,6 +312,8 @@ flags:
...
@@ -301,6 +312,8 @@ flags:
"
warp-tests"
:
false
"
warp-tests"
:
false
JuicyPixels
:
JuicyPixels
:
mmap
:
false
mmap
:
false
MemoTrie
:
examples
:
false
MissingH
:
MissingH
:
"
network--ge-3_0_0"
:
true
"
network--ge-3_0_0"
:
true
QuickCheck
:
QuickCheck
:
...
@@ -436,6 +449,8 @@ flags:
...
@@ -436,6 +449,8 @@ flags:
portable
:
false
portable
:
false
sse42
:
false
sse42
:
false
"
unsafe-tricks"
:
true
"
unsafe-tricks"
:
true
hedis
:
dev
:
false
hmatrix
:
hmatrix
:
"
disable-default-paths"
:
false
"
disable-default-paths"
:
false
"
no-random_r"
:
false
"
no-random_r"
:
false
...
@@ -487,6 +502,9 @@ flags:
...
@@ -487,6 +502,9 @@ flags:
libyaml
:
libyaml
:
"
no-unicode"
:
false
"
no-unicode"
:
false
"
system-libyaml"
:
false
"
system-libyaml"
:
false
linear
:
herbie
:
false
"
template-haskell"
:
true
"
llvm-hs"
:
"
llvm-hs"
:
debug
:
false
debug
:
false
"
llvm-with-rtti"
:
false
"
llvm-with-rtti"
:
false
...
...
test-data/test_config.toml
View file @
02e63fe4
...
@@ -72,3 +72,15 @@ dispatcher = { bind = "tcp://*:15561", connect = "tcp://localhost:15561" }
...
@@ -72,3 +72,15 @@ dispatcher = { bind = "tcp://*:15561", connect = "tcp://localhost:15561" }
EN
=
"corenlp://localhost:9000"
EN
=
"corenlp://localhost:9000"
FR
=
"spacy://localhost:8001"
FR
=
"spacy://localhost:8001"
All
=
"corenlp://localhost:9000"
All
=
"corenlp://localhost:9000"
[worker]
[worker.database]
host
=
"127.0.0.1"
port
=
5432
name
=
"pgmq_test"
user
=
"gargantua"
pass
=
"gargantua_test"
[[worker.definitions]]
name
=
"default"
queue
=
"default"
test/Test/Core/Worker.hs
0 → 100644
View file @
02e63fe4
{-|
Module : Test.Core.Worker
Description :
Copyright : (c) CNRS, 2024-Present
License : AGPL + CECILL v3
Maintainer : team@gargantext.org
Stability : experimental
Portability : POSIX
-}
module
Test.Core.Worker
where
import
Data.Aeson
qualified
as
Aeson
import
Gargantext.Core.Methods.Similarities.Conditional
import
Gargantext.Core.Worker.Jobs.Types
(
Job
(
..
))
import
Gargantext.Prelude
import
Test.Instances
()
import
Test.Tasty
import
Test.Tasty.HUnit
import
Test.Tasty.QuickCheck
hiding
(
Positive
,
Negative
)
tests
::
TestTree
tests
=
testGroup
"worker unit tests"
[
testProperty
"Worker Job to/from JSON serialization is correct"
$
\
job
->
Aeson
.
decode
(
Aeson
.
encode
(
job
::
Job
))
==
Just
job
]
test/Test/Instances.hs
View file @
02e63fe4
...
@@ -22,21 +22,105 @@ import Data.Patch.Class (Replace(Keep), replace)
...
@@ -22,21 +22,105 @@ import Data.Patch.Class (Replace(Keep), replace)
import
Data.Text
qualified
as
T
import
Data.Text
qualified
as
T
import
Data.Validity
(
Validation
(
..
),
ValidationChain
(
..
),
prettyValidation
)
import
Data.Validity
(
Validation
(
..
),
ValidationChain
(
..
),
prettyValidation
)
import
EPO.API.Client.Types
qualified
as
EPO
import
EPO.API.Client.Types
qualified
as
EPO
import
Gargantext.API.Admin.Auth.Types
(
AuthenticatedUser
(
..
),
ForgotPasswordAsyncParams
(
..
))
import
Gargantext.API.Admin.EnvTypes
as
EnvTypes
import
Gargantext.API.Errors.Types
qualified
as
Errors
import
Gargantext.API.Errors.Types
qualified
as
Errors
import
Gargantext.API.Ngrams.Types
qualified
as
Ngrams
import
Gargantext.API.Ngrams.Types
qualified
as
Ngrams
import
Gargantext.API.Node.Corpus.New
(
ApiInfo
(
..
))
import
Gargantext.API.Node.Corpus.New
(
ApiInfo
(
..
))
import
Gargantext.API.Node.Types
(
RenameNode
(
..
),
WithQuery
(
..
))
import
Gargantext.API.Node.Corpus.New
qualified
as
New
import
Gargantext.Core.Notifications.CentralExchange.Types
qualified
as
CET
import
Gargantext.API.Node.Types
(
NewWithForm
(
..
),
RenameNode
(
..
),
WithQuery
(
..
))
import
Gargantext.Core.Notifications.Dispatcher.Types
qualified
as
DET
import
Gargantext.Core.AsyncUpdates.CentralExchange.Types
qualified
as
CET
import
Gargantext.Core.AsyncUpdates.Dispatcher.Types
qualified
as
DET
import
Gargantext.Core.NodeStory.Types
qualified
as
NS
import
Gargantext.Core.NodeStory.Types
qualified
as
NS
import
Gargantext.Core.Text.Ngrams
(
NgramsType
(
..
))
import
Gargantext.Core.Text.Ngrams
(
NgramsType
(
..
))
import
Gargantext.Core.Types.Individu
qualified
as
Individu
import
Gargantext.Core.Types.Main
(
ListType
(
CandidateTerm
,
StopTerm
,
MapTerm
))
import
Gargantext.Core.Types.Main
(
ListType
(
CandidateTerm
,
StopTerm
,
MapTerm
))
import
Gargantext.Core.Worker.Jobs.Types
(
Job
(
..
))
import
Gargantext.Database.Admin.Types.Node
(
UserId
(
UnsafeMkUserId
))
import
Gargantext.Database.Admin.Types.Node
(
UserId
(
UnsafeMkUserId
))
import
Gargantext.Database.Admin.Types.Hyperdata
qualified
as
Hyperdata
import
Gargantext.Database.Admin.Types.Hyperdata
qualified
as
Hyperdata
import
Gargantext.Prelude
hiding
(
replace
,
Location
)
import
Gargantext.Prelude
hiding
(
replace
,
Location
)
import
Servant.Job.Core
qualified
as
SJ
import
Servant.Job.Core
qualified
as
SJ
import
Servant.Job.Types
qualified
as
SJ
import
Servant.Job.Types
qualified
as
SJ
import
Test.QuickCheck
import
Test.QuickCheck
import
Test.Tasty.QuickCheck
hiding
(
Positive
,
Negative
)
import
Text.Parsec.Error
(
ParseError
,
Message
(
..
),
newErrorMessage
)
import
Text.Parsec.Pos
instance
Arbitrary
AuthenticatedUser
where
arbitrary
=
AuthenticatedUser
<$>
arbitrary
-- _auth_node_id
<*>
arbitrary
-- _auth_user_id
instance
Arbitrary
EnvTypes
.
GargJob
where
arbitrary
=
do
oneof
[
pure
AddAnnuaireFormJob
,
pure
AddContactJob
,
pure
AddCorpusFileJob
,
pure
AddCorpusFormJob
,
pure
AddCorpusQueryJob
,
pure
AddFileJob
,
pure
DocumentFromWriteNodeJob
,
pure
ForgotPasswordJob
,
pure
NewNodeJob
,
pure
RecomputeGraphJob
,
pure
TableNgramsJob
,
pure
UpdateNgramsListJobJSON
,
pure
UpdateNgramsListJobTSV
,
pure
UpdateNodeJob
,
pure
UploadDocumentJob
,
pure
UploadFrameCalcJob
]
instance
Arbitrary
Job
where
arbitrary
=
oneof
[
pure
Ping
,
addCorpusFormAsyncGen
,
forgotPasswordAsyncGen
,
newNodeAsyncGen
,
gargJobGen
]
where
forgotPasswordAsyncGen
=
do
email
<-
arbitrary
return
$
ForgotPasswordAsync
(
ForgotPasswordAsyncParams
{
email
})
addCorpusFormAsyncGen
=
do
_acf_args
<-
arbitrary
_acf_user
<-
arbitrary
_acf_cid
<-
arbitrary
return
$
AddCorpusFormAsync
{
..
}
newNodeAsyncGen
=
do
_nna_node_id
<-
arbitrary
_nna_authenticatedUser
<-
arbitrary
_nna_postNode
<-
arbitrary
return
$
NewNodeAsync
{
..
}
gargJobGen
=
do
_gj_garg_job
<-
arbitrary
return
$
GargJob
{
_gj_garg_job
}
instance
Arbitrary
Message
where
arbitrary
=
do
msgContent
<-
arbitrary
oneof
$
return
<$>
[
SysUnExpect
msgContent
,
UnExpect
msgContent
,
Expect
msgContent
,
Message
msgContent
]
instance
Arbitrary
SourcePos
where
arbitrary
=
do
sn
<-
arbitrary
l
<-
arbitrary
c
<-
arbitrary
return
$
newPos
sn
l
c
instance
Arbitrary
ParseError
where
arbitrary
=
do
sp
<-
arbitrary
msg
<-
arbitrary
return
$
newErrorMessage
msg
sp
...
@@ -53,6 +137,16 @@ alphanum :: [Char]
...
@@ -53,6 +137,16 @@ alphanum :: [Char]
alphanum
=
smallLetter
<>
largeLetter
<>
digit
alphanum
=
smallLetter
<>
largeLetter
<>
digit
instance
Arbitrary
Individu
.
User
where
arbitrary
=
do
userId
<-
arbitrary
userName
<-
arbitrary
nodeId
<-
arbitrary
oneof
[
pure
$
Individu
.
UserDBId
userId
,
pure
$
Individu
.
UserName
userName
,
pure
$
Individu
.
RootId
nodeId
]
instance
Arbitrary
EPO
.
AuthKey
where
instance
Arbitrary
EPO
.
AuthKey
where
arbitrary
=
do
arbitrary
=
do
user
<-
arbitrary
user
<-
arbitrary
...
@@ -104,6 +198,14 @@ instance Arbitrary Hyperdata.HyperdataPublic where
...
@@ -104,6 +198,14 @@ instance Arbitrary Hyperdata.HyperdataPublic where
instance
Arbitrary
a
=>
Arbitrary
(
SJ
.
JobOutput
a
)
where
instance
Arbitrary
a
=>
Arbitrary
(
SJ
.
JobOutput
a
)
where
arbitrary
=
SJ
.
JobOutput
<$>
arbitrary
arbitrary
=
SJ
.
JobOutput
<$>
arbitrary
instance
Arbitrary
NewWithForm
where
arbitrary
=
NewWithForm
<$>
arbitrary
-- _wf_filetype
<*>
arbitrary
-- _wf_fileformat
<*>
arbitrary
-- _wf_data
<*>
arbitrary
-- _wf_lang
<*>
arbitrary
-- _wf_name
<*>
arbitrary
-- _wf_selection
instance
Arbitrary
RenameNode
where
instance
Arbitrary
RenameNode
where
arbitrary
=
elements
[
RenameNode
"test"
]
arbitrary
=
elements
[
RenameNode
"test"
]
...
...
test/Test/Parsers/Types.hs
View file @
02e63fe4
...
@@ -19,6 +19,7 @@ module Test.Parsers.Types where
...
@@ -19,6 +19,7 @@ module Test.Parsers.Types where
import
Gargantext.Prelude
import
Gargantext.Prelude
import
Test.Instances
()
import
Test.QuickCheck
import
Test.QuickCheck
import
Test.QuickCheck.Instances
()
import
Test.QuickCheck.Instances
()
...
@@ -43,25 +44,3 @@ looseZonedTimePrecision (ZonedTime lt tz) = ZonedTime (looseLocalTimePrecision l
...
@@ -43,25 +44,3 @@ looseZonedTimePrecision (ZonedTime lt tz) = ZonedTime (looseLocalTimePrecision l
loosePrecisionEitherPEZT
::
Either
ParseError
ZonedTime
->
Either
ParseError
ZonedTime
loosePrecisionEitherPEZT
::
Either
ParseError
ZonedTime
->
Either
ParseError
ZonedTime
loosePrecisionEitherPEZT
(
Right
zt
)
=
Right
$
looseZonedTimePrecision
zt
loosePrecisionEitherPEZT
(
Right
zt
)
=
Right
$
looseZonedTimePrecision
zt
loosePrecisionEitherPEZT
pe
=
pe
loosePrecisionEitherPEZT
pe
=
pe
instance
Arbitrary
Message
where
arbitrary
=
do
msgContent
<-
arbitrary
oneof
$
return
<$>
[
SysUnExpect
msgContent
,
UnExpect
msgContent
,
Expect
msgContent
,
Message
msgContent
]
instance
Arbitrary
SourcePos
where
arbitrary
=
do
sn
<-
arbitrary
l
<-
arbitrary
c
<-
arbitrary
return
$
newPos
sn
l
c
instance
Arbitrary
ParseError
where
arbitrary
=
do
sp
<-
arbitrary
msg
<-
arbitrary
return
$
newErrorMessage
msg
sp
test/Test/Utils/Jobs.hs
View file @
02e63fe4
...
@@ -12,12 +12,13 @@ Portability : POSIX
...
@@ -12,12 +12,13 @@ Portability : POSIX
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeFamilies #-}
module
Test.Utils.Jobs
(
test
)
where
module
Test.Utils.Jobs
(
test
,
qcTests
)
where
import
Control.Concurrent
import
Control.Concurrent
import
Control.Concurrent.Async
import
Control.Concurrent.Async
import
Control.Concurrent.Async
qualified
as
Async
import
Control.Concurrent.Async
qualified
as
Async
import
Control.Concurrent.STM
import
Control.Concurrent.STM
import
Data.Aeson
qualified
as
Aeson
import
Data.Sequence
((
|>
),
fromList
)
import
Data.Sequence
((
|>
),
fromList
)
import
Data.Time
import
Data.Time
import
Debug.RecoverRTTI
(
anythingToString
)
import
Debug.RecoverRTTI
(
anythingToString
)
...
@@ -43,6 +44,9 @@ import System.IO.Unsafe
...
@@ -43,6 +44,9 @@ import System.IO.Unsafe
import
System.Timeout
(
timeout
)
import
System.Timeout
(
timeout
)
import
Test.Hspec
import
Test.Hspec
import
Test.Hspec.Expectations.Contrib
(
annotate
)
import
Test.Hspec.Expectations.Contrib
(
annotate
)
import
Test.Instances
()
-- arbitrary instances
import
Test.Tasty
(
TestTree
,
testGroup
)
import
Test.Tasty.QuickCheck
hiding
(
Positive
,
Negative
)
import
Test.Utils
(
waitUntil
)
import
Test.Utils
(
waitUntil
)
...
@@ -485,3 +489,10 @@ test = do
...
@@ -485,3 +489,10 @@ test = do
testFetchJobStatusNoContention
testFetchJobStatusNoContention
it
"marking stuff behaves as expected"
$
it
"marking stuff behaves as expected"
$
testMarkProgress
testMarkProgress
qcTests
::
TestTree
qcTests
=
testGroup
"jobs qc tests"
[
testProperty
"GargJob to/from JSON serialization is correct"
$
\
job
->
Aeson
.
decode
(
Aeson
.
encode
(
job
::
EnvTypes
.
GargJob
))
==
Just
job
]
test/drivers/tasty/Main.hs
View file @
02e63fe4
...
@@ -15,6 +15,7 @@ import Gargantext.Prelude
...
@@ -15,6 +15,7 @@ import Gargantext.Prelude
import
qualified
Test.Core.Text.Corpus.Query
as
CorpusQuery
import
qualified
Test.Core.Text.Corpus.Query
as
CorpusQuery
import
qualified
Test.Core.Text.Corpus.TSV
as
TSVParser
import
qualified
Test.Core.Text.Corpus.TSV
as
TSVParser
import
qualified
Test.Core.Utils
as
Utils
import
qualified
Test.Core.Utils
as
Utils
import
qualified
Test.Core.Worker
as
Worker
import
qualified
Test.Graph.Clustering
as
Graph
import
qualified
Test.Graph.Clustering
as
Graph
import
qualified
Test.Ngrams.NLP
as
NLP
import
qualified
Test.Ngrams.NLP
as
NLP
import
qualified
Test.Ngrams.Query
as
NgramsQuery
import
qualified
Test.Ngrams.Query
as
NgramsQuery
...
@@ -57,6 +58,8 @@ main = do
...
@@ -57,6 +58,8 @@ main = do
,
similaritySpec
,
similaritySpec
,
Phylo
.
tests
,
Phylo
.
tests
,
testGroup
"Stemming"
[
Lancaster
.
tests
]
,
testGroup
"Stemming"
[
Lancaster
.
tests
]
,
Worker
.
tests
,
Jobs
.
qcTests
,
asyncUpdatesSpec
,
asyncUpdatesSpec
,
Notifications
.
qcTests
,
Notifications
.
qcTests
]
]
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