Skip to content

Commit d25a038

Browse files
committed
1986 Fix duplicate pool stats
1 parent e00405d commit d25a038

File tree

4 files changed

+71
-2
lines changed

4 files changed

+71
-2
lines changed

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ unitTests iom knownMigrations =
120120
, test "rollback stake address cache" Rollback.stakeAddressRollback
121121
, test "rollback change order of txs" Rollback.rollbackChangeTxOrder
122122
, test "rollback full tx" Rollback.rollbackFullTx
123+
, test "pool stat rollback no duplicates" Rollback.poolStatRollback
123124
]
124125
, testGroup
125126
"different configs"

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

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ module Test.Cardano.Db.Mock.Unit.Conway.Rollback (
1010
stakeAddressRollback,
1111
rollbackChangeTxOrder,
1212
rollbackFullTx,
13+
poolStatRollback,
1314
) where
1415

1516
import Cardano.Ledger.Coin (Coin (..))
@@ -25,9 +26,11 @@ import Ouroboros.Network.Block (blockPoint)
2526
import Test.Cardano.Db.Mock.Config
2627
import Test.Cardano.Db.Mock.Examples (mockBlock0, mockBlock1, mockBlock2)
2728
import Test.Cardano.Db.Mock.UnifiedApi
28-
import Test.Cardano.Db.Mock.Validate (assertBlockNoBackoff, assertTxCount)
29-
import Test.Tasty.HUnit (Assertion ())
29+
import Test.Cardano.Db.Mock.Validate (assertBlockNoBackoff, assertTxCount, runQuery)
30+
import Test.Tasty.HUnit (Assertion (), assertBool, assertEqual)
3031
import Prelude (last)
32+
import qualified Test.Cardano.Db.Mock.UnifiedApi as Api
33+
import qualified Cardano.Db as Db
3134

3235
simpleRollback :: IOManager -> [(Text, Text)] -> Assertion
3336
simpleRollback =
@@ -291,3 +294,40 @@ rollbackFullTx =
291294
assertTxCount dbSync 14
292295
where
293296
testLabel = "conwayRollbackFullTx"
297+
298+
poolStatRollback :: IOManager -> [(Text, Text)] -> Assertion
299+
poolStatRollback =
300+
withFullConfigAndDropDB conwayConfigDir testLabel $ \interpreter mockServer dbSync -> do
301+
startDBSync dbSync
302+
303+
-- Create pools and stake to generate pool stats
304+
void $ Api.registerAllStakeCreds interpreter mockServer
305+
void $ Api.fillEpochs interpreter mockServer 2
306+
307+
-- Create rollback point
308+
blks <- Api.forgeAndSubmitBlocks interpreter mockServer 10
309+
assertBlockNoBackoff dbSync (2 + length blks)
310+
311+
-- Check initial pool stat count
312+
initialCount <- runQuery dbSync Db.queryPoolStatCount
313+
314+
-- Forge more blocks to create additional pool stats
315+
void $ Api.fillEpochs interpreter mockServer 1
316+
assertBlockNoBackoff dbSync (3 + length blks)
317+
318+
-- Verify pool stats increased
319+
afterCount <- runQuery dbSync Db.queryPoolStatCount
320+
assertBool "Pool stats should have increased" (afterCount > initialCount)
321+
322+
-- Rollback to previous point
323+
atomically $ rollback mockServer (blockPoint $ last blks)
324+
assertBlockNoBackoff dbSync (3 + length blks) -- Delayed rollback
325+
326+
-- Re-sync the same blocks - should not create duplicates
327+
void $ Api.fillEpochs interpreter mockServer 1
328+
finalCount <- runQuery dbSync Db.queryPoolStatCount
329+
330+
-- Verify count matches and no constraint violations occurred
331+
assertEqual "Pool stat count should match after rollback" afterCount finalCount
332+
where
333+
testLabel = "conwayPoolStatRollback"

cardano-db/src/Cardano/Db/Operations/Query.hs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ module Cardano.Db.Operations.Query (
6969
queryReservedTicker,
7070
queryReservedTickers,
7171
queryDelistedPools,
72+
queryPoolStatCount,
7273
queryOffChainPoolFetchError,
7374
existsDelistedPool,
7475
-- queries used in tools
@@ -922,6 +923,13 @@ queryDelistedPools = do
922923
pure $ delistedPool ^. DelistedPoolHashRaw
923924
pure $ unValue <$> res
924925

926+
queryPoolStatCount :: MonadIO m => ReaderT SqlBackend m Word64
927+
queryPoolStatCount = do
928+
res <- select $ do
929+
_ <- from $ table @PoolStat
930+
pure countRows
931+
pure $ maybe 0 unValue (listToMaybe res)
932+
925933
-- Returns also the metadata hash
926934
queryOffChainPoolFetchError :: MonadIO m => ByteString -> Maybe UTCTime -> ReaderT SqlBackend m [(OffChainPoolFetchError, ByteString)]
927935
queryOffChainPoolFetchError hash Nothing = do

schema/migration-2-0045-20250708.sql

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
-- Persistent generated migration.
2+
3+
CREATE FUNCTION migrate() RETURNS void AS $$
4+
DECLARE
5+
next_version int ;
6+
BEGIN
7+
SELECT stage_two + 1 INTO next_version FROM schema_version ;
8+
IF next_version = 45 THEN
9+
EXECUTE 'ALTER TABLE "pool_stat" ADD CONSTRAINT "unique_pool_stat_epoch"
10+
UNIQUE ("pool_hash_id", "epoch_no")' ;
11+
-- Hand written SQL statements can be added here.
12+
UPDATE schema_version SET stage_two = next_version ;
13+
RAISE NOTICE 'DB has been migrated to stage_two version %', next_version ;
14+
END IF ;
15+
END ;
16+
$$ LANGUAGE plpgsql ;
17+
18+
SELECT migrate() ;
19+
20+
DROP FUNCTION migrate() ;

0 commit comments

Comments
 (0)