Skip to content

Commit a3820a8

Browse files
authored
Merge pull request #2078 from IntersectMBO/2077-fix-CI-builds
Fix CI build failures
2 parents 09d16bc + 4b93365 commit a3820a8

6 files changed

Lines changed: 81 additions & 48 deletions

File tree

.github/workflows/haskell.yml

Lines changed: 10 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ jobs:
2929
env:
3030
# Increment this value to "invalidate" the cabal cache. Be sure to do this
3131
# after updating dependencies (Hackage or chap)
32-
CABAL_CACHE_VERSION: 1
32+
CABAL_CACHE_VERSION: 2
3333

3434
steps:
3535
- name: Checkout code
@@ -47,19 +47,12 @@ jobs:
4747
minimal: false
4848
# enable IOG-full flavour to bring in all the crypto libraries we need.
4949
iog-full: true
50-
# TODO: remove when input-output-hk/devx is fixed
51-
- name: Install system dependencies
52-
uses: input-output-hk/actions/base@latest
53-
with:
54-
use-sodium-vrf: true
55-
- name: Add LMDB to Nix environment
50+
- name: Export devx environment variables
5651
run: |
57-
nix-env -f '<nixpkgs>' -iA lmdb
58-
LMDB_STORE=$(find /nix/store -maxdepth 1 -name '*lmdb*-dev' -type d | head -1)
59-
if [ -n "$LMDB_STORE" ]; then
60-
echo "LMDB_PKGCONFIG=${LMDB_STORE}/lib/pkgconfig" >> $GITHUB_ENV
61-
fi
62-
shell: devx {0}
52+
echo "PKG_CONFIG_PATH=$PKG_CONFIG_PATH_FOR_TARGET" >> $GITHUB_ENV
53+
echo "PKG_CONFIG_PATH_FOR_TARGET=$PKG_CONFIG_PATH_FOR_TARGET" >> $GITHUB_ENV
54+
echo "NIX_LDFLAGS=$NIX_LDFLAGS" >> $GITHUB_ENV
55+
echo "LD_LIBRARY_PATH=$(echo $NIX_LDFLAGS | tr ' ' '\n' | grep '^-L' | sed 's/^-L//' | tr '\n' ':')" >> $GITHUB_ENV
6356
- name: cache cabal
6457
uses: actions/cache@v3
6558
with:
@@ -70,18 +63,17 @@ jobs:
7063
restore-keys: ${{ env.CABAL_CACHE_VERSION }}-${{ runner.os }}-${{ matrix.compiler-nix-name }}-
7164
- name: cabal update
7265
run: |
73-
export PKG_CONFIG_PATH_FOR_TARGET=${{ env.LMDB_PKGCONFIG }}:${PKG_CONFIG_PATH_FOR_TARGET:-}
66+
export PATH="/usr/bin:$PATH"
7467
cabal update
7568
- name: cabal build dependencies
7669
run: |
77-
export PKG_CONFIG_PATH_FOR_TARGET=${{ env.LMDB_PKGCONFIG }}:${PKG_CONFIG_PATH_FOR_TARGET:-}
70+
export PATH="/usr/bin:$PATH"
7871
cabal build all -j --enable-tests --only-dependencies
7972
- name: cabal build
8073
run: |
81-
export PKG_CONFIG_PATH_FOR_TARGET=${{ env.LMDB_PKGCONFIG }}:${PKG_CONFIG_PATH_FOR_TARGET:-}
74+
export PATH="/usr/bin:$PATH"
8275
cabal build all -j --enable-tests
8376
- name: postgres init
84-
working-directory:
8577
run: |
8678
# Set up environment
8779
PG_DIR="$(mktemp -d)"
@@ -103,7 +95,7 @@ jobs:
10395
start
10496
- name: cabal test
10597
run: |
106-
export PKG_CONFIG_PATH_FOR_TARGET=${{ env.LMDB_PKGCONFIG }}:${PKG_CONFIG_PATH_FOR_TARGET:-}
98+
export PATH="/usr/bin:$PATH"
10799
# Create pgpass file
108100
export PGPASSFILE="${PG_DIR}/pgpass-testing"
109101
echo "${PG_DIR}:5432:$DBUSER:$DBUSER:*" > $PGPASSFILE

cardano-chain-gen/src/Cardano/Mock/ChainSync/Server.hs

Lines changed: 33 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ module Cardano.Mock.ChainSync.Server (
1414
withServerHandle,
1515
stopServer,
1616
restartServer,
17+
waitForNextConnection,
1718

1819
-- * ServerHandle api
1920
ServerHandle (..),
@@ -42,8 +43,8 @@ import Control.Concurrent.Class.MonadSTM.Strict (
4243
retry,
4344
writeTVar,
4445
)
45-
import Control.Exception (bracket)
46-
import Control.Monad (forever)
46+
import Control.Exception (IOException, bracket, try)
47+
import Control.Monad (forever, unless)
4748
import Control.Tracer
4849
import Data.ByteString.Lazy.Char8 (ByteString)
4950
import qualified Data.Map.Strict as Map
@@ -101,13 +102,15 @@ import Ouroboros.Network.Snocket
101102
import qualified Ouroboros.Network.Snocket as Snocket
102103
import Ouroboros.Network.Socket
103104
import Ouroboros.Network.Util.ShowProxy (Proxy (..), ShowProxy (..))
105+
import System.Directory (removeFile)
104106

105107
{- HLINT ignore "Use readTVarIO" -}
106108

107109
data ServerHandle m blk = ServerHandle
108110
{ chainProducerState :: StrictTVar m (ChainProducerState blk)
109111
, threadHandle :: StrictTVar m (Async ())
110112
, forkAgain :: m (Async ())
113+
, socketPath :: FilePath
111114
}
112115

113116
replaceGenesis :: MonadSTM m => ServerHandle m blk -> State blk -> STM m ()
@@ -142,9 +145,11 @@ rollback handle point =
142145
restartServer :: ServerHandle IO blk -> IO ()
143146
restartServer sh = do
144147
stopServer sh
145-
-- TODO not sure why, but this delay is necessary. Without it reconnection doesn't happen
146-
-- some times.
147-
threadDelay 1_000_000
148+
-- On Unix, closing the socket fd does not remove the socket file. If the
149+
-- file still exists when the new server tries to bind, bind() fails with
150+
-- EADDRINUSE and the server thread dies silently. Explicitly remove the
151+
-- file here so the new server can always bind successfully.
152+
_ <- (try @IOException) $ removeFile (socketPath sh)
148153
thread <- forkAgain sh
149154
atomically $ writeTVar (threadHandle sh) thread
150155

@@ -153,6 +158,20 @@ stopServer sh = do
153158
srvThread <- atomically $ readTVar $ threadHandle sh
154159
cancel srvThread
155160

161+
-- | Block until db-sync has made a new connection to the (restarted) server.
162+
-- This is detected by watching 'nextFollowerId' in 'ChainProducerState': each
163+
-- new client connection calls 'newFollower', incrementing the counter.
164+
-- Call this after 'restartServer' to ensure the test does not race ahead
165+
-- before db-sync has actually reconnected.
166+
waitForNextConnection :: ServerHandle IO blk -> IO ()
167+
waitForNextConnection sh = do
168+
-- Snapshot the current follower id before the restart connection comes in.
169+
currentId <- atomically $ nextFollowerId <$> readTVar (chainProducerState sh)
170+
-- Block until a new follower (with a higher id) has been registered.
171+
atomically $ do
172+
cps <- readTVar (chainProducerState sh)
173+
unless (nextFollowerId cps > currentId) retry
174+
156175
type MockServerConstraint blk =
157176
( SerialiseNodeToClientConstraints blk
158177
, BlockSupportsLedgerQuery blk
@@ -182,7 +201,7 @@ forkServerThread iom config initSt netMagic path = do
182201
let runThread = async $ runLocalServer iom (configCodec config) netMagic path chainSt
183202
thread <- runThread
184203
threadVar <- newTVarIO thread
185-
pure $ ServerHandle chainSt threadVar runThread
204+
pure $ ServerHandle chainSt threadVar runThread path
186205

187206
withServerHandle ::
188207
MockServerConstraint blk =>
@@ -262,7 +281,7 @@ runLocalServer iom codecConfig netMagic localDomainSock chainProdState = do
262281
IO ((), Maybe ByteString)
263282
chainSyncServer' _them channel =
264283
runPeer
265-
nullTracer -- (showTracing stdoutTracer)
284+
nullTracer
266285
(cChainSyncCodec codecs)
267286
channel
268287
(chainSyncServerPeer $ chainSyncServer state codecConfig blockVersion)
@@ -332,9 +351,10 @@ chainSyncServer state codec _blockVersion =
332351
mupdate <- tryReadChainUpdate r
333352
case mupdate of
334353
Just update -> pure (Left (sendNext r update))
335-
Nothing -> pure (Right (sendNext r <$> readChainUpdate r))
336-
-- Follower is at the head, have to block and wait for
337-
-- the producer's state to change.
354+
Nothing ->
355+
-- Follower is at the head, have to block and wait for
356+
-- the producer's state to change.
357+
pure $ Right $ sendNext r <$> readChainUpdate r
338358

339359
handleFindIntersect ::
340360
FollowerId ->
@@ -352,13 +372,14 @@ chainSyncServer state codec _blockVersion =
352372
ServerStNext (Serialised blk) (Point blk) (Tip blk) m ()
353373
sendNext r (tip, AddBlock b) =
354374
SendMsgRollForward (mkSerialised (encodeDisk codec) b) tip (idle' r)
355-
sendNext r (tip, RollBack p) = SendMsgRollBackward (castPoint p) tip (idle' r)
375+
sendNext r (tip, RollBack p) =
376+
SendMsgRollBackward (castPoint p) tip (idle' r)
356377

357378
newFollower :: m FollowerId
358379
newFollower = atomically $ do
359380
cps <- readTVar state
360381
let (cps', rid) = initFollower genesisPoint cps
361-
_ <- writeTVar state cps'
382+
writeTVar state cps'
362383
pure rid
363384

364385
improveReadPoint ::

cardano-chain-gen/test/Test/Cardano/Db/Mock/Property/Property.hs

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ data Model r = Model
5656
, dbSyncMaxBlockNo :: Maybe BlockNo
5757
, dbSynsIsOn :: Bool
5858
, dbSynsHasSynced :: Bool -- This is used just to avoid restarting the node too early.
59+
, dbSyncNeedsResync :: Bool -- True after RestartNode until at least one RollForward, to avoid
60+
-- generating AssertBlockNo before db-sync has had a chance to reconnect.
5961
}
6062
deriving stock (Generic, Show)
6163

@@ -103,7 +105,7 @@ instance ToExpr (Model Symbolic)
103105
instance ToExpr (Model Concrete)
104106

105107
initModel :: Model r
106-
initModel = Model [] [] Nothing False False
108+
initModel = Model [] [] Nothing False False False
107109

108110
data Response r
109111
= NewBlockAdded (Reference (Opaque CardanoBlock) r)
@@ -127,6 +129,7 @@ transition m cmd resp = case (cmd, resp) of
127129
in m
128130
{ serverChain = serverChain'
129131
, dbSyncMaxBlockNo = dbSyncMaxBlockNo'
132+
, dbSyncNeedsResync = False
130133
}
131134
(RollBack blkNo, _) ->
132135
m {serverChain = rollbackChain blkNo (serverChain m)}
@@ -144,7 +147,7 @@ transition m cmd resp = case (cmd, resp) of
144147
, dbSynsHasSynced = False
145148
}
146149
(RestartNode, _) ->
147-
m
150+
m {dbSyncNeedsResync = True}
148151
(AssertBlockNo n, _) ->
149152
m
150153
{ dbSynsHasSynced = True
@@ -157,13 +160,13 @@ precondition m cmd = case cmd of
157160
RollBack n -> n .< serverTip m -- can it be equal?
158161
StopDBSync -> Boolean $ dbSynsIsOn m && dbSynsHasSynced m
159162
StartDBSync -> Boolean $ not $ dbSynsIsOn m
160-
RestartNode -> Boolean $ dbSynsHasSynced m
163+
RestartNode -> Boolean $ dbSynsHasSynced m && dbSynsIsOn m
161164
AssertBlockNo n | Just n' <- canAssert m -> n .== n'
162165
_ -> Bot
163166

164167
canAssert :: Model Symbolic -> Maybe (Maybe BlockNo)
165168
canAssert m =
166-
if stip >= dbtip
169+
if not (dbSyncNeedsResync m) && stip >= dbtip
167170
then Just stip
168171
else Nothing
169172
where
@@ -186,7 +189,7 @@ semantics interpreter mockServer dbSync cmd = case cmd of
186189
Just pnt -> Unit <$> rollbackTo interpreter mockServer pnt
187190
StopDBSync -> Unit <$> stopDBSync dbSync
188191
StartDBSync -> Unit <$> startDBSync dbSync
189-
RestartNode -> Unit <$> restartServer mockServer
192+
RestartNode -> Unit <$> (restartServer mockServer >> waitForNextConnection mockServer)
190193
AssertBlockNo mBlkNo -> runAssert dbSync mBlkNo
191194

192195
runAssert :: DBSyncEnv -> Maybe BlockNo -> IO (Response Concrete)
@@ -220,7 +223,7 @@ generator m =
220223
, (if not canRollback then 0 else if isOn then 10 else 20, genRollBack m)
221224
, (if isOn then 30 else 0, genStopDBSync m)
222225
, (if isOn then 0 else 60, genStartDBSync m)
223-
, (if isOn then 20 else 5, genRestartNode m)
226+
, (if isOn then 20 else 0, genRestartNode m)
224227
, (if isOn && isJust serverNotBehind then 30 else 0, genAssertBlockNo m)
225228
]
226229
where

cardano-chain-gen/test/Test/Cardano/Db/Mock/Unit/Babbage/Simple.hs

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ module Test.Cardano.Db.Mock.Unit.Babbage.Simple (
88
) where
99

1010
import Cardano.Ledger.BaseTypes (BlockNo (BlockNo))
11-
import Cardano.Mock.ChainSync.Server (IOManager, addBlock, restartServer)
11+
import Cardano.Mock.ChainSync.Server (IOManager, addBlock, restartServer, waitForNextConnection)
1212
import Cardano.Mock.Forging.Interpreter (forgeNext)
1313
import Control.Concurrent.Class.MonadSTM.Strict (atomically)
1414
import Control.Monad (void)
@@ -80,13 +80,20 @@ restartDBSync =
8080
nodeRestart :: IOManager -> [(Text, Text)] -> Assertion
8181
nodeRestart =
8282
withFullConfig babbageConfigDir testLabel $ \interpreter mockServer dbSync -> do
83-
startDBSync dbSync
83+
-- Forge blocks before starting db-sync so it syncs them cleanly in one shot.
8484
void $ forgeAndSubmitBlocks interpreter mockServer 5
85+
startDBSync dbSync
8586
assertBlockNoBackoff dbSync 5
8687

8788
restartServer mockServer
88-
89-
void $ forgeAndSubmitBlocks interpreter mockServer 5
89+
-- Wait for db-sync to actually reconnect to the restarted server before
90+
-- forging new blocks. Without this, the mux bearer on macOS CI takes up to
91+
-- 24s to detect the closed connection, and the 51s assertion budget may be
92+
-- exhausted before db-sync reconnects.
93+
waitForNextConnection mockServer
94+
void $ forgeAndSubmitBlocks interpreter mockServer 1
95+
assertBlockNoBackoff dbSync 6
96+
void $ forgeAndSubmitBlocks interpreter mockServer 4
9097
assertBlockNoBackoff dbSync 10
9198
where
9299
testLabel = "nodeRestart"
@@ -99,8 +106,12 @@ nodeRestartBoundary =
99106
assertBlockNoBackoff dbSync $ length blks
100107

101108
restartServer mockServer
102-
103-
void $ forgeAndSubmitBlocks interpreter mockServer 5
109+
-- Wait for db-sync to actually reconnect to the restarted server before
110+
-- forging new blocks and asserting.
111+
waitForNextConnection mockServer
112+
void $ forgeAndSubmitBlocks interpreter mockServer 1
113+
assertBlockNoBackoff dbSync $ length blks + 1
114+
void $ forgeAndSubmitBlocks interpreter mockServer 4
104115
assertBlockNoBackoff dbSync $ 5 + length blks
105116
where
106117
testLabel = "nodeRestartBoundary"

cardano-chain-gen/test/Test/Cardano/Db/Mock/Unit/Conway/Governance.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -485,7 +485,7 @@ hardFork =
485485
-- indexes them without errors.
486486
hardForkPostBlock :: IOManager -> [(Text, Text)] -> Assertion
487487
hardForkPostBlock =
488-
withFullConfigLog conwayConfigDir testLabel $ \interpreter server dbSync -> do
488+
withFullConfig conwayConfigDir testLabel $ \interpreter server dbSync -> do
489489
startDBSync dbSync
490490

491491
-- Register SPOs, DReps, and committee to vote

cardano-chain-gen/test/Test/Cardano/Db/Mock/Unit/Conway/Simple.hs

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ module Test.Cardano.Db.Mock.Unit.Conway.Simple (
88
) where
99

1010
import Cardano.Ledger.BaseTypes (BlockNo (..))
11-
import Cardano.Mock.ChainSync.Server (IOManager, addBlock, restartServer)
11+
import Cardano.Mock.ChainSync.Server (IOManager, addBlock, restartServer, waitForNextConnection)
1212
import Cardano.Mock.Forging.Interpreter (forgeNext)
1313
import Cardano.Prelude
1414
import Ouroboros.Network.Block (blockNo)
@@ -85,8 +85,11 @@ nodeRestart =
8585
assertBlockNoBackoff dbSync 5
8686

8787
restartServer mockServer
88-
89-
void $ forgeAndSubmitBlocks interpreter mockServer 5
88+
-- Wait for db-sync to actually reconnect before forging new blocks.
89+
waitForNextConnection mockServer
90+
void $ forgeAndSubmitBlocks interpreter mockServer 1
91+
assertBlockNoBackoff dbSync 6
92+
void $ forgeAndSubmitBlocks interpreter mockServer 4
9093
assertBlockNoBackoff dbSync 10
9194
where
9295
testLabel = "conwayNodeRestart"
@@ -99,8 +102,11 @@ nodeRestartBoundary =
99102
assertBlockNoBackoff dbSync $ length blks
100103

101104
restartServer mockServer
102-
103-
void $ forgeAndSubmitBlocks interpreter mockServer 5
105+
-- Wait for db-sync to actually reconnect before forging new blocks.
106+
waitForNextConnection mockServer
107+
void $ forgeAndSubmitBlocks interpreter mockServer 1
108+
assertBlockNoBackoff dbSync $ length blks + 1
109+
void $ forgeAndSubmitBlocks interpreter mockServer 4
104110
assertBlockNoBackoff dbSync $ 5 + length blks
105111
where
106112
testLabel = "conwayNodeRestartBoundary"

0 commit comments

Comments
 (0)