Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
5c601fe
Use HTTP instead of WebSocket for Ogmios
marcusbfs Feb 5, 2025
14a6d9d
Remove mempool methods from `QueryM.Ogmios`
marcusbfs Feb 5, 2025
12896f5
Fix warning
marcusbfs Feb 5, 2025
219f497
Use HTTP version of `evaluateTx`
marcusbfs Feb 5, 2025
141a59b
Extract Ogmios types into separate module
marcusbfs Feb 5, 2025
83b2c49
Clean and simplify Ogmios related code
marcusbfs Feb 5, 2025
5f963f1
Move mempool related types to `Ogmios.Mempool`
marcusbfs Feb 5, 2025
5c2d73f
Fix IPV6 parser
marcusbfs Feb 5, 2025
2c0c04d
Move `DecodeOgmios` to `Ogmios.Types`
marcusbfs Feb 5, 2025
af6d6f5
Rename `Ogmios.Queries` to `Ogmios.QueryEnv`
marcusbfs Feb 5, 2025
fb55251
Remove `uniqueId` and `ServerConfig` dependencies from Ogmios.Mempool
marcusbfs Feb 5, 2025
ea54320
Extract common configuration out of `Ogmios.Mempool`
marcusbfs Feb 5, 2025
2dcaa81
Remove unused exports
marcusbfs Feb 6, 2025
2d2196f
Omit "id" field for Ogmios HTTP request/response
marcusbfs Feb 7, 2025
2c8db1f
Simplify error handling
marcusbfs Feb 7, 2025
796868f
Reuse `aesonObject`
marcusbfs Feb 7, 2025
9a214a8
Simplify error handling
marcusbfs Feb 10, 2025
f8fea7c
Add `HttpUtils`
marcusbfs Feb 10, 2025
adba5b1
Clean duplicated code
marcusbfs Feb 10, 2025
febc66a
Remove websocket runtime from `QueryEnv`
marcusbfs Feb 13, 2025
06a5955
Refactor mempool code structure
marcusbfs Feb 13, 2025
99b98a0
Remove `resendPendingSubmitRequests` in websocket internals
marcusbfs Feb 13, 2025
946c443
Remove internal CTL helper functions from mempool
marcusbfs Feb 14, 2025
2718d8a
Remove unused code
marcusbfs Feb 14, 2025
303e7f4
Refactor `OgmiosDecodeError`
marcusbfs Feb 18, 2025
ace529e
Improve HTTP handler readability
marcusbfs Feb 18, 2025
d8ba070
Update changelog
marcusbfs Feb 18, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 10 additions & 19 deletions src/Internal/QueryM.purs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import Control.Monad.Rec.Class (class MonadRec)
import Control.Parallel (class Parallel, parallel, sequential)
import Control.Plus (class Plus)
import Ctl.Internal.Helpers (logWithLevel)
import Ctl.Internal.QueryM.HttpUtils (handleAffjaxResponseGeneric)
import Ctl.Internal.QueryM.Ogmios.QueryEnv (QueryRuntime)
import Ctl.Internal.ServerConfig (ServerConfig)
import Data.Bifunctor (lmap)
Expand Down Expand Up @@ -128,27 +129,17 @@ instance Parallel (QueryMT ParAff) (QueryMT Aff) where
sequential :: QueryMT ParAff ~> QueryMT Aff
sequential = wrap <<< sequential <<< unwrap

--------------------------------------------------------------------------------
-- Affjax
--------------------------------------------------------------------------------

-- Checks response status code and returns `ClientError` in case of failure,
-- otherwise attempts to decode the result.
--
-- This function solves the problem described there:
-- https://github.com/eviefp/purescript-affjax-errors
handleAffjaxResponse
:: forall (result :: Type)
. DecodeAeson result
=> Either Affjax.Error (Affjax.Response String)
-> Either ClientError result
handleAffjaxResponse (Left affjaxError) =
Left (ClientHttpError affjaxError)
handleAffjaxResponse
(Right { status: Affjax.StatusCode.StatusCode statusCode, body })
| statusCode < 200 || statusCode > 299 =
Left $ ClientHttpResponseError (wrap statusCode) $ ServiceOtherError body
| otherwise =
body # lmap (ClientDecodeJsonError body)
<<< (decodeAeson <=< parseJsonStringToAeson)

handleAffjaxResponse =
handleAffjaxResponseGeneric
ClientHttpError
( \statusCode body -> ClientHttpResponseError (wrap statusCode)
(ServiceOtherError body)
)
ClientDecodeJsonError
(decodeAeson <=< parseJsonStringToAeson)
pure
54 changes: 54 additions & 0 deletions src/Internal/QueryM/HttpUtils.purs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
-- | This module defines utilities for working with HTTP requests
module Ctl.Internal.QueryM.HttpUtils
( handleAffjaxResponseGeneric
) where

import Prelude

import Aeson (JsonDecodeError)
import Affjax (Error, Response) as Affjax
import Affjax.StatusCode as Affjax.StatusCode
import Data.Bifunctor (lmap)
import Data.Either (Either(Left, Right))

--------------------------------------------------------------------------------
-- Affjax
--------------------------------------------------------------------------------

-- Checks response status code and returns `ClientError` in case of failure,
-- otherwise attempts to decode the result.
--
-- This function solves the problem described there:
-- https://github.com/eviefp/purescript-affjax-errors

handleAffjaxResponseGeneric
:: forall err intermediate result
. (Affjax.Error -> err)
-- ^ Convert an Affjax error into custom error
-> (Int -> String -> err)
-- ^ Convert a non-2xx status code into custom error
-> (String -> JsonDecodeError -> err)
-- ^ Wrap aeson-parse/decode errors
-> (String -> Either JsonDecodeError intermediate)
-- ^ Parse the response body
-> (intermediate -> Either err result)
-- ^ Function from `intermediate` to `result`
-> Either Affjax.Error (Affjax.Response String)
-- ^ Argument
-> Either err result
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function could accept a record for better readability. Also, it might not need to be so generic, especially if we can reuse the same error type.

handleAffjaxResponseGeneric
mkHttpError
mkHttpResponseError
mkDecodeError
decodeAeson
mkResult =
case _ of
Left affjaxError ->
Left (mkHttpError affjaxError)
Right { status: Affjax.StatusCode.StatusCode statusCode, body }
| statusCode < 200 || statusCode > 299 ->
Left (mkHttpResponseError statusCode body)
| otherwise -> do
intermediate <- lmap (mkDecodeError body) do
decodeAeson body
mkResult intermediate
28 changes: 14 additions & 14 deletions src/Internal/QueryM/Ogmios.purs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import Affjax.ResponseFormat (string) as Affjax.ResponseFormat
import Affjax.StatusCode (StatusCode(StatusCode))
import Affjax.StatusCode as Affjax.StatusCode
import Cardano.Provider.Error
( ClientError(ClientHttpError, ClientHttpResponseError)
( ClientError(ClientHttpError, ClientHttpResponseError, ClientDecodeJsonError)
, ServiceError(ServiceOtherError)
)
import Cardano.Provider.TxEvaluation as Provider
Expand All @@ -33,13 +33,14 @@ import Control.Monad.Error.Class (class MonadThrow, throwError)
import Control.Monad.Reader.Class (asks)
import Ctl.Internal.Affjax (request) as Affjax
import Ctl.Internal.QueryM (QueryM)
import Ctl.Internal.QueryM.HttpUtils (handleAffjaxResponseGeneric)
import Ctl.Internal.QueryM.Ogmios.Types
( class DecodeOgmios
, AdditionalUtxoSet
, ChainTipQR(CtChainPoint, CtChainOrigin)
, CurrentEpoch
, DelegationsAndRewardsR
, OgmiosDecodeError(ResultDecodingError, ClientErrorResponse)
, OgmiosDecodeError(ClientErrorResponse)
, OgmiosEraSummaries
, OgmiosProtocolParameters
, OgmiosSystemStart
Expand Down Expand Up @@ -137,7 +138,7 @@ ogmiosQueryNoParams
. DecodeOgmios a
=> String
-> QueryM (Either OgmiosDecodeError a)
ogmiosQueryNoParams method = do ogmiosQueryParams method {}
ogmiosQueryNoParams = flip ogmiosQueryParams {}

ogmiosQueryParams
:: forall a p
Expand Down Expand Up @@ -201,17 +202,16 @@ handleAffjaxOgmiosResponse
. DecodeOgmios result
=> Either Affjax.Error (Affjax.Response String)
-> Either OgmiosDecodeError result
handleAffjaxOgmiosResponse (Left affjaxError) =
Left (ClientErrorResponse $ ClientHttpError affjaxError)
handleAffjaxOgmiosResponse
(Right { status: Affjax.StatusCode.StatusCode statusCode, body })
| statusCode < 200 || statusCode > 299 =
Left $ ClientErrorResponse $ ClientHttpResponseError (wrap statusCode) $
ServiceOtherError body
| otherwise = do
aeson <- lmap ResultDecodingError
$ parseJsonStringToAeson body
decodeOgmios aeson
handleAffjaxOgmiosResponse =
handleAffjaxResponseGeneric
(ClientErrorResponse <<< ClientHttpError)
( \statusCode body -> ClientErrorResponse $ ClientHttpResponseError
(wrap statusCode)
(ServiceOtherError body)
)
(\body -> ClientErrorResponse <<< ClientDecodeJsonError body)
parseJsonStringToAeson
decodeOgmios

ogmiosErrorHandler
:: forall a m
Expand Down