Skip to content

Commit 00e5fa3

Browse files
authored
Merge pull request #2006 from IntersectMBO/1992-custom-snapshots-freq
1992-custom-snapshot-intervals
2 parents b3fcefd + 7bf3d1b commit 00e5fa3

File tree

10 files changed

+91
-36
lines changed

10 files changed

+91
-36
lines changed

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

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -295,8 +295,6 @@ mkSyncNodeParams staticDir mutableDir CommandLineArgs {..} = do
295295
, enpHasCache = claHasCache
296296
, enpForceIndexes = claForceIndexes
297297
, enpHasInOut = True
298-
, enpSnEveryFollowing = 35
299-
, enpSnEveryLagging = 35
300298
, enpMaybeRollback = Nothing
301299
}
302300

cardano-db-sync/app/cardano-db-sync.hs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,8 +89,6 @@ pRunDbSyncNode = do
8989
<*> pHasCache
9090
<*> pForceIndexes
9191
<*> pHasInOut
92-
<*> pure 500
93-
<*> pure 10000
9492
<*> optional pRollbackSlotNo
9593

9694
pConfigFile :: Parser ConfigFile

cardano-db-sync/src/Cardano/DbSync.hs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -295,8 +295,7 @@ extractSyncOptions snp aop snc =
295295
isTxOutConsumedBootstrap'
296296
forceTxIn'
297297
, soptInsertOptions = iopts
298-
, snapshotEveryFollowing = enpSnEveryFollowing snp
299-
, snapshotEveryLagging = enpSnEveryLagging snp
298+
, soptSnapshotInterval = dncSnapshotInterval snc
300299
}
301300
where
302301
maybeKeepMNames =

cardano-db-sync/src/Cardano/DbSync/Api/Types.hs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ import Ouroboros.Network.Magic (NetworkMagic (..))
2828

2929
import qualified Cardano.Db as DB
3030
import Cardano.DbSync.Cache.Types (CacheStatistics, CacheStatus)
31-
import Cardano.DbSync.Config.Types (SyncNodeConfig)
31+
import Cardano.DbSync.Config.Types (SnapshotIntervalConfig, SyncNodeConfig)
3232
import Cardano.DbSync.Ledger.Types (HasLedgerEnv)
3333
import Cardano.DbSync.LocalStateQuery (NoLedgerEnv)
3434
import Cardano.DbSync.Types (
@@ -70,8 +70,7 @@ data SyncOptions = SyncOptions
7070
, soptCache :: !Bool
7171
, soptPruneConsumeMigration :: !DB.PruneConsumeMigration
7272
, soptInsertOptions :: !InsertOptions
73-
, snapshotEveryFollowing :: !Word64
74-
, snapshotEveryLagging :: !Word64
73+
, soptSnapshotInterval :: !SnapshotIntervalConfig
7574
}
7675
deriving (Show)
7776

cardano-db-sync/src/Cardano/DbSync/Config.hs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ coalesceConfig pcfg ncfg adjustGenesisPath = do
9292
, dncConwayHardFork = ncConwayHardFork ncfg
9393
, dncInsertOptions = extractInsertOptions pcfg
9494
, dncIpfsGateway = endsInSlash <$> pcIpfsGateway pcfg
95+
, dncSnapshotInterval = pcSnapshotInterval pcfg
9596
}
9697

9798
mkAdjustPath :: SyncPreConfig -> (FilePath -> FilePath)

cardano-db-sync/src/Cardano/DbSync/Config/Types.hs

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ module Cardano.DbSync.Config.Types (
3939
GovernanceConfig (..),
4040
OffchainPoolDataConfig (..),
4141
JsonTypeConfig (..),
42+
SnapshotIntervalConfig (..),
4243
LedgerStateDir (..),
4344
LogFileDir (..),
4445
NetworkName (..),
@@ -85,6 +86,8 @@ import Ouroboros.Consensus.Protocol.Praos (Praos)
8586
import Ouroboros.Consensus.Protocol.TPraos (TPraos)
8687
import Ouroboros.Consensus.Shelley.Ledger.Block (ShelleyBlock)
8788

89+
{- HLINT ignore "Reduce duplication" -}
90+
8891
newtype LogFileDir = LogFileDir
8992
{ unLogFileDir :: FilePath
9093
}
@@ -109,8 +112,6 @@ data SyncNodeParams = SyncNodeParams
109112
, enpHasCache :: !Bool
110113
, enpForceIndexes :: !Bool
111114
, enpHasInOut :: !Bool
112-
, enpSnEveryFollowing :: !Word64
113-
, enpSnEveryLagging :: !Word64
114115
, enpMaybeRollback :: !(Maybe SlotNo)
115116
}
116117
deriving (Show)
@@ -147,6 +148,7 @@ data SyncNodeConfig = SyncNodeConfig
147148
, dncConwayHardFork :: !(CardanoHardForkTrigger (ShelleyBlock (Praos StandardCrypto) ConwayEra))
148149
, dncInsertOptions :: !SyncInsertOptions
149150
, dncIpfsGateway :: [Text]
151+
, dncSnapshotInterval :: !SnapshotIntervalConfig
150152
}
151153

152154
data SyncPreConfig = SyncPreConfig
@@ -159,6 +161,7 @@ data SyncPreConfig = SyncPreConfig
159161
, pcPrometheusPort :: !Int
160162
, pcInsertConfig :: !SyncInsertConfig
161163
, pcIpfsGateway :: ![Text]
164+
, pcSnapshotInterval :: !SnapshotIntervalConfig
162165
}
163166
deriving (Show)
164167

@@ -279,6 +282,11 @@ data JsonTypeConfig
279282
| JsonTypeDisable
280283
deriving (Eq, Show)
281284

285+
newtype SnapshotIntervalConfig = SnapshotIntervalConfig
286+
{ sicNearTipEpoch :: Word64
287+
}
288+
deriving (Eq, Show)
289+
282290
newtype GenesisFile = GenesisFile
283291
{ unGenesisFile :: FilePath
284292
}
@@ -407,6 +415,7 @@ parseGenSyncNodeConfig o =
407415
<*> fmap (fromMaybe 8080) (o .:? "PrometheusPort")
408416
<*> o .:? "insert_options" .!= def
409417
<*> o .:? "ipfs_gateway" .!= ["https://ipfs.io/ipfs"]
418+
<*> o .:? "snapshot_interval" .!= def
410419

411420
instance FromJSON SyncProtocol where
412421
parseJSON o =
@@ -728,6 +737,23 @@ instance FromJSON JsonTypeConfig where
728737
"disable" -> pure JsonTypeDisable
729738
other -> fail $ "unexpected json_type: " <> show other
730739

740+
instance ToJSON SnapshotIntervalConfig where
741+
toJSON cfg =
742+
Aeson.object
743+
[ "near_tip_epoch" .= sicNearTipEpoch cfg
744+
]
745+
746+
instance FromJSON SnapshotIntervalConfig where
747+
parseJSON = Aeson.withObject "snapshot_interval" $ \obj ->
748+
SnapshotIntervalConfig
749+
<$> obj .:? "near_tip_epoch" .!= sicNearTipEpoch def
750+
751+
instance Default SnapshotIntervalConfig where
752+
def =
753+
SnapshotIntervalConfig
754+
{ sicNearTipEpoch = 580 -- Epoch threshold to consider being near tip
755+
}
756+
731757
instance Default SyncInsertConfig where
732758
def = SyncInsertConfig Nothing def
733759

cardano-db-sync/src/Cardano/DbSync/Ledger/State.hs

Lines changed: 10 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,6 @@ import qualified Cardano.Ledger.BaseTypes as Ledger
5454
import Cardano.Ledger.Shelley.AdaPots (AdaPots)
5555
import qualified Cardano.Ledger.Shelley.LedgerState as Shelley
5656
import Cardano.Prelude hiding (atomically)
57-
import Cardano.Slotting.Block (BlockNo (..))
5857
import Cardano.Slotting.EpochInfo (EpochInfo, epochInfoEpoch)
5958
import Cardano.Slotting.Slot (
6059
EpochNo (..),
@@ -128,7 +127,7 @@ import qualified Ouroboros.Consensus.Shelley.Ledger.Ledger as Consensus
128127
import Ouroboros.Consensus.Storage.Serialisation (DecodeDisk (..), EncodeDisk (..))
129128
import Ouroboros.Network.AnchoredSeq (AnchoredSeq (..))
130129
import qualified Ouroboros.Network.AnchoredSeq as AS
131-
import Ouroboros.Network.Block (HeaderHash, Point (..), blockNo)
130+
import Ouroboros.Network.Block (HeaderHash, Point (..))
132131
import qualified Ouroboros.Network.Point as Point
133132
import System.Directory (doesFileExist, listDirectory, removeFile)
134133
import System.FilePath (dropExtension, takeExtension, (</>))
@@ -186,8 +185,7 @@ mkHasLedgerEnv trce protoInfo dir nw systemStart syncOptions = do
186185
, leNetwork = nw
187186
, leSystemStart = systemStart
188187
, leAbortOnPanic = soptAbortOnInvalid syncOptions
189-
, leSnapshotEveryFollowing = snapshotEveryFollowing syncOptions
190-
, leSnapshotEveryLagging = snapshotEveryLagging syncOptions
188+
, leSnapshotNearTipEpoch = sicNearTipEpoch $ soptSnapshotInterval syncOptions
191189
, leInterpreter = intervar
192190
, leStateVar = svar
193191
, leStateWriteQueue = swQueue
@@ -218,7 +216,8 @@ readStateUnsafe env = do
218216
applyBlockAndSnapshot :: HasLedgerEnv -> CardanoBlock -> Bool -> IO (ApplyResult, Bool)
219217
applyBlockAndSnapshot ledgerEnv blk isCons = do
220218
(oldState, appResult) <- applyBlock ledgerEnv blk
221-
tookSnapshot <- storeSnapshotAndCleanupMaybe ledgerEnv oldState appResult (blockNo blk) isCons (isSyncedWithinSeconds (apSlotDetails appResult) 600)
219+
-- 864000 seconds = 10 days; consider synced "near tip" if within 10 days of current time
220+
tookSnapshot <- storeSnapshotAndCleanupMaybe ledgerEnv oldState appResult isCons (isSyncedWithinSeconds (apSlotDetails appResult) 864000)
222221
pure (appResult, tookSnapshot)
223222

224223
-- The function 'tickThenReapply' does zero validation, so add minimal validation ('blockPrevHash'
@@ -321,32 +320,21 @@ storeSnapshotAndCleanupMaybe ::
321320
HasLedgerEnv ->
322321
CardanoLedgerState ->
323322
ApplyResult ->
324-
BlockNo ->
325323
Bool ->
326324
SyncState ->
327325
IO Bool
328-
storeSnapshotAndCleanupMaybe env oldState appResult blkNo isCons syncState =
326+
storeSnapshotAndCleanupMaybe env oldState appResult isCons syncState =
329327
case maybeFromStrict (apNewEpoch appResult) of
330328
Just newEpoch
331329
| newEpochNo <- unEpochNo (Generic.neEpoch newEpoch)
332330
, newEpochNo > 0
333-
, isCons || (newEpochNo `mod` 10 == 0) || newEpochNo >= 530 ->
331+
, -- Snapshot every epoch when near tip, every 10 epochs when lagging, or always for epoch >= threshold
332+
(isCons && syncState == SyncFollowing) || (newEpochNo `mod` 10 == 0) || newEpochNo >= leSnapshotNearTipEpoch env ->
334333
do
335334
-- TODO: Instead of newEpochNo - 1, is there any way to get the epochNo from 'lssOldState'?
336335
liftIO $ saveCleanupState env oldState (Just $ EpochNo $ newEpochNo - 1)
337336
pure True
338-
_ ->
339-
if timeToSnapshot syncState blkNo && isCons
340-
then do
341-
liftIO $ saveCleanupState env oldState Nothing
342-
pure True
343-
else pure False
344-
where
345-
timeToSnapshot :: SyncState -> BlockNo -> Bool
346-
timeToSnapshot syncSt bNo =
347-
case (syncSt, unBlockNo bNo) of
348-
(SyncFollowing, bno) -> bno `mod` leSnapshotEveryFollowing env == 0
349-
(SyncLagging, _) -> False
337+
_ -> pure False
350338

351339
saveCurrentLedgerState :: HasLedgerEnv -> CardanoLedgerState -> Maybe EpochNo -> IO ()
352340
saveCurrentLedgerState env lState mEpochNo = do
@@ -403,7 +391,8 @@ ledgerStateWriteLoop tracer swQueue codecConfig =
403391

404392
mkLedgerStateFilename :: LedgerStateDir -> ExtLedgerState CardanoBlock -> Maybe EpochNo -> WithOrigin FilePath
405393
mkLedgerStateFilename dir ledger mEpochNo =
406-
lsfFilePath . dbPointToFileName dir mEpochNo
394+
lsfFilePath
395+
. dbPointToFileName dir mEpochNo
407396
<$> getPoint (ledgerTipPoint @CardanoBlock (ledgerState ledger))
408397

409398
saveCleanupState :: HasLedgerEnv -> CardanoLedgerState -> Maybe EpochNo -> IO ()

cardano-db-sync/src/Cardano/DbSync/Ledger/Types.hs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,7 @@ data HasLedgerEnv = HasLedgerEnv
6767
, leNetwork :: !Ledger.Network
6868
, leSystemStart :: !SystemStart
6969
, leAbortOnPanic :: !Bool
70-
, leSnapshotEveryFollowing :: !Word64
71-
, leSnapshotEveryLagging :: !Word64
70+
, leSnapshotNearTipEpoch :: !Word64
7271
, leInterpreter :: !(StrictTVar IO (Strict.Maybe CardanoInterpreter))
7372
, leStateVar :: !(StrictTVar IO (Strict.Maybe LedgerDB))
7473
, leStateWriteQueue :: !(TBQueue (FilePath, CardanoLedgerState))

cardano-db-sync/test/Cardano/DbSync/Gen.hs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,12 @@ syncPreConfig =
5858
<*> Gen.int (Range.linear 0 10000)
5959
<*> syncInsertConfig
6060
<*> Gen.list (Range.linear 0 10) (Gen.text (Range.linear 0 100) Gen.unicode)
61+
<*> snapshotIntervalConfig
62+
63+
snapshotIntervalConfig :: Gen SnapshotIntervalConfig
64+
snapshotIntervalConfig =
65+
SnapshotIntervalConfig
66+
<$> Gen.word64 (Range.linear 100 1000)
6167

6268
syncNodeParams :: MonadGen m => m SyncNodeParams
6369
syncNodeParams =
@@ -71,8 +77,6 @@ syncNodeParams =
7177
<*> Gen.bool
7278
<*> Gen.bool
7379
<*> Gen.bool
74-
<*> Gen.word64 (Range.linear 0 1000)
75-
<*> Gen.word64 (Range.linear 0 1000)
7680
<*> pure Nothing
7781

7882
syncNodeConfig :: Logging.Configuration -> Gen SyncNodeConfig
@@ -104,6 +108,7 @@ syncNodeConfig loggingCfg =
104108
<*> triggerHardFork
105109
<*> syncInsertOptions
106110
<*> pure []
111+
<*> snapshotIntervalConfig
107112

108113
syncInsertConfig :: Gen SyncInsertConfig
109114
syncInsertConfig =

doc/configuration.md

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ Below is a sample `insert_options` section that shows all the defaults:
6666
| [pool\_stat](#pool-stat) | `enum` | Optional |
6767
| [remove\_jsonb_from_schema](#remove-jsonb-from-schema) | `enum` | Optional |
6868
| [stop\_at\_block](#stop-at-block) | `integer` | Optional |
69+
| [snapshot\_interval](#snapshot-interval) | `object` | Optional |
6970

7071
## Preset
7172

@@ -602,3 +603,43 @@ Stops db-sync after processing the specified block number. Useful for testing an
602603
}
603604
```
604605

606+
## Snapshot Interval
607+
608+
`snapshot_interval`
609+
610+
* Type: `object`
611+
* Optional: When not specified, uses default values
612+
613+
Controls how frequently ledger state snapshots are taken during sync. Taking snapshots less frequently during initial sync can significantly improve sync performance by reducing IOPS and disk throughput consumption.
614+
615+
Snapshot Interval Properties:
616+
617+
| Property | Type | Required | Default |
618+
| :------------------------------- | :-------- | :------- | :------ |
619+
| [near\_tip\_epoch](#near-tip-epoch) | `integer` | Optional | 580 |
620+
621+
### Near Tip Epoch
622+
623+
`snapshot_interval.near_tip_epoch`
624+
625+
* Type: `integer`
626+
* Default: `580`
627+
628+
Epoch threshold used to determine snapshot behavior. When syncing reaches this epoch or later, db-sync is considered to be approaching or at the current tip of the chain. Combined with time-based detection (within 10 days of current time), this ensures snapshots are taken every epoch when near the tip for fast rollback recovery. During earlier epochs or when syncing behind, snapshots are taken every 10 epochs.
629+
630+
### Example
631+
632+
```json
633+
{
634+
"snapshot_interval": {
635+
"near_tip_epoch": 580
636+
}
637+
}
638+
```
639+
640+
### Performance Considerations
641+
642+
- **Lower `near_tip_epoch` value**: Start taking frequent epoch-based snapshots earlier in the chain history
643+
- **Higher `near_tip_epoch` value**: Delay frequent snapshots until later in the chain, improving sync speed for longer. During initial sync (before reaching `near_tip_epoch`), snapshots are taken every 10 epochs
644+
- **Near tip detection**: Automatically switches to epoch-based snapshots when within 10 days of current time, regardless of epoch number
645+

0 commit comments

Comments
 (0)