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
149
Issues
149
List
Board
Labels
Milestones
Merge Requests
5
Merge Requests
5
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
58d9fcb0
Commit
58d9fcb0
authored
Dec 16, 2024
by
Alfredo Di Napoli
1
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Proper error handling for remote import and export handlers
parent
23a06d28
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
40 additions
and
19 deletions
+40
-19
Types.hs
src/Gargantext/API/Errors/Types.hs
+8
-0
Prelude.hs
src/Gargantext/API/Prelude.hs
+4
-1
Client.hs
src/Gargantext/API/Routes/Client.hs
+1
-1
Remote.hs
src/Gargantext/API/Routes/Named/Remote.hs
+3
-2
Remote.hs
src/Gargantext/API/Server/Named/Remote.hs
+24
-15
No files found.
src/Gargantext/API/Errors/Types.hs
View file @
58d9fcb0
...
...
@@ -35,6 +35,7 @@ module Gargantext.API.Errors.Types (
,
GraphQLError
(
..
)
,
ToFrontendErrorData
(
..
)
,
AccessPolicyErrorReason
(
..
)
,
HasBackendInternalError
(
..
)
-- * Constructing frontend errors
,
mkFrontendErrNoDiagnostic
...
...
@@ -67,6 +68,7 @@ import Gargantext.Prelude hiding (Location, WithStacktrace)
import
Gargantext.Utils.Dict
(
Dict
(
..
))
import
Gargantext.Utils.Jobs.Monad
qualified
as
Jobs
import
Servant
(
ServerError
)
import
Control.Lens.Prism
(
prism'
)
-- | A 'WithStacktrace' carries an error alongside its
-- 'CallStack', to be able to print the correct source location
...
...
@@ -121,6 +123,12 @@ data BackendInternalError
makePrisms
''
B
ackendInternalError
class
HasBackendInternalError
e
where
_BackendInternalError
::
Prism'
e
BackendInternalError
instance
HasBackendInternalError
BackendInternalError
where
_BackendInternalError
=
prism'
identity
Just
instance
ToJSON
BackendInternalError
where
toJSON
(
InternalJobError
s
)
=
object
[
(
"status"
,
toJSON
(
"IsFailure"
::
Text
))
...
...
src/Gargantext/API/Prelude.hs
View file @
58d9fcb0
...
...
@@ -17,11 +17,12 @@ module Gargantext.API.Prelude
,
HasServerError
(
..
)
,
serverError
)
where
import
Control.Exception.Safe
qualified
as
Safe
import
Control.Lens
((
#
))
import
Control.Monad.Random
(
MonadRandom
)
import
Gargantext.API.Admin.Auth.Types
(
AuthenticationError
)
import
Gargantext.API.Errors.Class
(
HasAuthenticationError
,
_AuthenticationError
)
import
Gargantext.API.Errors.Types
(
HasServerError
(
..
),
serverError
)
import
Gargantext.API.Errors.Types
(
HasServerError
(
..
),
serverError
,
HasBackendInternalError
)
import
Gargantext.Core.Notifications.CentralExchange.Types
(
HasCentralExchangeNotification
)
import
Gargantext.Core.Config
(
HasConfig
,
HasManager
)
import
Gargantext.Core.Mail.Types
(
HasMail
)
...
...
@@ -54,6 +55,7 @@ type ErrC err =
,
HasValidationError
err
,
HasTreeError
err
,
HasServerError
err
,
HasBackendInternalError
err
,
HasAuthenticationError
err
-- , ToJSON err -- TODO this is arguable
,
Exception
err
...
...
@@ -63,6 +65,7 @@ type GargServerC env err m =
(
HasNodeStory
env
err
m
,
HasMail
env
,
MonadRandom
m
,
Safe
.
MonadCatch
m
,
EnvC
env
,
ErrC
err
,
ToJSON
err
...
...
src/Gargantext/API/Routes/Client.hs
View file @
58d9fcb0
...
...
@@ -38,7 +38,7 @@ clientRoutes = genericClient
remoteImportClient
::
Auth
.
Token
->
C
.
ConduitT
()
Named
.
RemoteBinaryData
IO
()
->
ClientM
(
C
.
ConduitT
()
Named
.
RemoteBinaryData
IO
()
)
->
ClientM
()
remoteImportClient
(
S
.
Token
.
TE
.
encodeUtf8
->
token
)
c
=
clientRoutes
&
apiWithCustomErrorScheme
&
(
$
GES_new
)
...
...
src/Gargantext/API/Routes/Named/Remote.hs
View file @
58d9fcb0
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE DerivingStrategies #-}
module
Gargantext.API.Routes.Named.Remote
(
-- * Routes types
RemoteAPI
(
..
)
...
...
@@ -8,6 +9,7 @@ module Gargantext.API.Routes.Named.Remote (
,
RemoteBinaryData
(
..
)
)
where
import
Conduit
qualified
as
C
import
Data.Aeson
as
JSON
import
Data.ByteString.Lazy
qualified
as
BL
import
Data.ByteString
qualified
as
BS
...
...
@@ -20,7 +22,6 @@ import Prelude
import
Servant.API
import
Servant.Client.Core.BaseUrl
import
Test.QuickCheck
import
qualified
Conduit
as
C
data
RemoteAPI
mode
=
RemoteAPI
...
...
@@ -77,5 +78,5 @@ instance ToSchema RemoteBinaryData where
data
RemoteAPI'
mode
=
RemoteAPI'
{
remoteExportEp
::
mode
:-
"export"
:>
ReqBody
'[
J
SON
]
RemoteExportRequest
:>
Post
'[
J
SON
]
()
,
remoteImportEp
::
mode
:-
"import"
:>
StreamBody
NoFraming
OctetStream
(
C
.
ConduitT
()
RemoteBinaryData
IO
()
)
:>
StreamPost
NoFraming
OctetStream
(
C
.
ConduitT
()
RemoteBinaryData
IO
()
)
:>
Post
'[
J
SON
]
(
)
}
deriving
Generic
src/Gargantext/API/Server/Named/Remote.hs
View file @
58d9fcb0
...
...
@@ -2,6 +2,7 @@
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
module
Gargantext.API.Server.Named.Remote
(
remoteAPI
...
...
@@ -9,16 +10,21 @@ module Gargantext.API.Server.Named.Remote (
import
Codec.Serialise
import
Conduit
import
Control.Lens
(
view
)
import
Control.Exception.Safe
qualified
as
Safe
import
Control.Exception
(
toException
)
import
Control.Lens
(
view
,
(
#
))
import
Control.Monad.Except
(
throwError
)
import
Data.ByteString.Builder
qualified
as
B
import
Data.ByteString.Char8
qualified
as
C8
import
Data.ByteString.Lazy
qualified
as
BL
import
Data.Conduit.Combinators
qualified
as
C
import
Data.Conduit.List
qualified
as
CL
import
Gargantext.API.Errors.Types
import
Gargantext.API.Prelude
(
IsGargServer
)
import
Gargantext.API.Routes.Client
(
remoteImportClient
)
import
Gargantext.API.Routes.Named.Remote
qualified
as
Named
import
Gargantext.Core.Config
import
Gargantext.Database.Prelude
(
IsDBCmd
)
import
Prelude
import
Servant.Client.Streaming
(
mkClientEnv
,
withClientM
,
ClientError
)
import
Servant.Server.Generic
(
AsServerT
)
...
...
@@ -27,19 +33,21 @@ remoteAPI :: (MonadIO m, IsGargServer env err m) => Named.RemoteAPI (AsServerT m
remoteAPI
=
Named
.
RemoteAPI
$
Named
.
RemoteAPI'
{
remoteExportEp
=
remoteExportHandler
,
remoteImportEp
=
pure
,
remoteImportEp
=
remoteImportHandler
}
type
ExpectedPayload
=
C8
.
ByteString
-- FIXME(adn)
remoteImportHandler
::
(
MonadIO
m
,
Serialise
a
)
=>
ConduitT
()
Named
.
RemoteBinaryData
IO
()
->
m
a
remoteImportHandler
c
=
liftIO
$
do
chunks
<-
sourceToList
$
c
.|
C
.
map
(
B
.
byteString
.
Named
.
getRemoteBinaryData
)
case
deserialiseOrFail
(
B
.
toLazyByteString
$
mconcat
chunks
)
of
Left
err
->
liftIO
$
error
$
"Deserialization error: "
++
show
err
Right
value
->
pure
value
remoteImportHandler
::
(
HasBackendInternalError
err
,
IsDBCmd
env
err
m
,
MonadIO
m
)
=>
ConduitT
()
Named
.
RemoteBinaryData
IO
()
->
m
()
remoteImportHandler
c
=
do
chunks
<-
liftIO
$
sourceToList
$
c
.|
C
.
map
(
B
.
byteString
.
Named
.
getRemoteBinaryData
)
case
deserialiseOrFail
@
ExpectedPayload
(
B
.
toLazyByteString
$
mconcat
chunks
)
of
Left
err
->
throwError
$
_BackendInternalError
#
InternalUnexpectedError
(
toException
$
userError
$
"Deserialization error: "
++
show
err
)
Right
value
->
liftIO
$
putStrLn
$
show
$
value
remoteExportHandler
::
(
MonadIO
m
remoteExportHandler
::
(
MonadIO
m
,
Safe
.
MonadCatch
m
,
IsGargServer
err
env
m
)
=>
Named
.
RemoteExportRequest
...
...
@@ -48,13 +56,14 @@ remoteExportHandler Named.RemoteExportRequest{..} = do
mgr
<-
view
gargHttpManager
-- FIXME(adn) eventually we want to be sending nodes here.
let
node
=
C8
.
pack
"hello world"
result
<-
liftIO
$
withClientM
(
remoteImportClient
_rer_instance_auth
(
streamEncoder
node
))
(
mkClientEnv
mgr
_rer_instance_url
)
streamDecode
liftIO
$
putStrLn
(
show
(
result
::
ExpectedPayload
))
liftIO
(
withClientM
(
remoteImportClient
_rer_instance_auth
(
streamEncoder
node
))
(
mkClientEnv
mgr
_rer_instance_url
)
streamDecode
)
`
Safe
.
catch
`
\
(
e
::
BackendInternalError
)
->
throwError
$
_BackendInternalError
#
e
streamEncoder
::
Serialise
a
=>
a
->
ConduitT
()
Named
.
RemoteBinaryData
IO
()
streamEncoder
::
(
MonadIO
m
,
Serialise
a
)
=>
a
->
ConduitT
()
Named
.
RemoteBinaryData
m
()
streamEncoder
=
CL
.
sourceList
.
map
Named
.
RemoteBinaryData
.
BL
.
toChunks
.
serialise
streamDecode
::
Either
ClientError
(
ConduitT
()
Named
.
RemoteBinaryData
IO
()
)
->
IO
ExpectedPayload
-- | Returns a conduit which can be used to decode
streamDecode
::
Either
ClientError
()
->
IO
()
streamDecode
=
\
case
Left
err
->
error
$
show
err
-- FIXME(adn) How to deal with the error properly?
Right
c
->
remoteImportHandler
c
Left
err
->
Safe
.
throwIO
$
InternalUnexpectedError
(
toException
$
userError
$
show
err
)
Right
_
->
pure
()
Przemyslaw Kaminski
@cgenie
mentioned in commit
942e663f
·
Jan 29, 2025
mentioned in commit
942e663f
mentioned in commit 942e663f539b287b4cc0469fe2bcf735813b4ff2
Toggle commit list
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