-
Notifications
You must be signed in to change notification settings - Fork 24
/
Copy pathChainIndex.hs
102 lines (92 loc) · 3.72 KB
/
ChainIndex.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
module Test.Plutip.Internal.ChainIndex (
handleChainIndexLaunch,
) where
import Cardano.Api qualified as CAPI
import Cardano.BM.Configuration.Model qualified as CM
import Cardano.BM.Data.Severity qualified as Severity
import Cardano.Launcher.Node (nodeSocketFile)
import Control.Concurrent.Async (Async, async)
import Control.Retry (constantDelay, limitRetries, recoverAll)
import Plutus.ChainIndex.App qualified as ChainIndex
import Plutus.ChainIndex.Config qualified as ChainIndex
import Plutus.ChainIndex.Logging (defaultConfig)
import Servant.Client (BaseUrl (BaseUrl), Scheme (Http), mkClientEnv, runClientM)
import System.FilePath ((</>))
import Test.Plutip.Config (
ChainIndexMode (CustomPort, DefaultPort, NotNeeded),
)
import Test.Plutip.Internal.Types (
RunningNode (RunningNode),
)
import UnliftIO.Exception (throwString)
import Cardano.Wallet.Primitive.Types (
NetworkParameters (NetworkParameters),
SlotLength (SlotLength),
SlottingParameters (SlottingParameters),
)
import Data.Default (Default (def))
import Data.Function ((&))
import Data.Time (nominalDiffTimeToSeconds)
import Ledger (Slot (Slot))
import Ledger.TimeSlot (SlotConfig (scSlotLength))
import Network.HTTP.Client (defaultManagerSettings, newManager)
import Plutus.ChainIndex (Tip (Tip))
import Plutus.ChainIndex.Client qualified as ChainIndexClient
import Plutus.ChainIndex.Config qualified as CIC
import PlutusPrelude ((.~), (^.))
type ChainIndexPort = Int
-- | Handle launch of `chain-index`. Depending on `ChainIndexMode`, it can be
-- launched on default port, on custom port or not launched at all.
-- In the latter case no port will be returned.
handleChainIndexLaunch ::
ChainIndexMode ->
RunningNode ->
FilePath ->
IO (Maybe (ChainIndexPort, Async ()))
handleChainIndexLaunch mode rn dir = do
maybePort <-
case mode of
DefaultPort -> do
Just <$> launchChainIndex (CIC.cicPort ChainIndex.defaultConfig) rn dir
CustomPort port' -> do
Just <$> launchChainIndex (fromEnum port') rn dir
NotNeeded -> pure Nothing
reportLaunch $ fst <$> maybePort
pure maybePort
where
reportLaunch = \case
Just p -> putStrLn $ "Chain index started at port " <> show p
_ -> pure ()
-- | Launch the chain index in a separate thread.
launchChainIndex :: Int -> RunningNode -> FilePath -> IO (Int, Async ())
launchChainIndex port (RunningNode sp _block0 (netParams, _vData) _) dir = do
let (NetworkParameters _ (SlottingParameters (SlotLength slotLen) _ _ _) _) = netParams
config <- defaultConfig
CM.setMinSeverity config Severity.Notice
let dbPath = dir </> "chain-index.db"
chainIndexConfig =
CIC.defaultConfig
& CIC.socketPath .~ nodeSocketFile sp
& CIC.dbPath .~ dbPath
& CIC.networkId .~ CAPI.Mainnet
& CIC.port .~ port
& CIC.slotConfig .~ (def {scSlotLength = toMilliseconds slotLen})
running <- async $ ChainIndex.runMainWithLog (const $ return ()) config chainIndexConfig
waitForChainIndex
return (chainIndexConfig ^. CIC.port, running)
where
toMilliseconds = floor . (1e3 *) . nominalDiffTimeToSeconds
waitForChainIndex = do
-- TODO: move this to config; ideally, separate chain-index launch from cluster launch
let policy = constantDelay 1_000_000 <> limitRetries 60
recoverAll policy $ \_ -> do
tip <- queryTipWithChIndex
case tip of
Right (Tip (Slot _) _ _) -> pure ()
a ->
throwString $
"Timeout waiting for chain-index to start indexing. Last response:\n"
<> either show show a
queryTipWithChIndex = do
manager' <- newManager defaultManagerSettings
runClientM ChainIndexClient.getTip $ mkClientEnv manager' (BaseUrl Http "localhost" port "")