Skip to content

Commit faf1694

Browse files
committed
1992-custom-snapshot-intervals
1 parent 238a84f commit faf1694

File tree

9 files changed

+101
-17
lines changed

9 files changed

+101
-17
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: 30 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 (..),
@@ -109,8 +110,6 @@ data SyncNodeParams = SyncNodeParams
109110
, enpHasCache :: !Bool
110111
, enpForceIndexes :: !Bool
111112
, enpHasInOut :: !Bool
112-
, enpSnEveryFollowing :: !Word64
113-
, enpSnEveryLagging :: !Word64
114113
, enpMaybeRollback :: !(Maybe SlotNo)
115114
}
116115
deriving (Show)
@@ -147,6 +146,7 @@ data SyncNodeConfig = SyncNodeConfig
147146
, dncConwayHardFork :: !(CardanoHardForkTrigger (ShelleyBlock (Praos StandardCrypto) ConwayEra))
148147
, dncInsertOptions :: !SyncInsertOptions
149148
, dncIpfsGateway :: [Text]
149+
, dncSnapshotInterval :: !SnapshotIntervalConfig
150150
}
151151

152152
data SyncPreConfig = SyncPreConfig
@@ -159,6 +159,7 @@ data SyncPreConfig = SyncPreConfig
159159
, pcPrometheusPort :: !Int
160160
, pcInsertConfig :: !SyncInsertConfig
161161
, pcIpfsGateway :: ![Text]
162+
, pcSnapshotInterval :: !SnapshotIntervalConfig
162163
}
163164
deriving (Show)
164165

@@ -279,6 +280,12 @@ data JsonTypeConfig
279280
| JsonTypeDisable
280281
deriving (Eq, Show)
281282

283+
data SnapshotIntervalConfig = SnapshotIntervalConfig
284+
{ sicFollowing :: !Word64
285+
, sicLagging :: !Word64
286+
}
287+
deriving (Eq, Show)
288+
282289
newtype GenesisFile = GenesisFile
283290
{ unGenesisFile :: FilePath
284291
}
@@ -407,6 +414,7 @@ parseGenSyncNodeConfig o =
407414
<*> fmap (fromMaybe 8080) (o .:? "PrometheusPort")
408415
<*> o .:? "insert_options" .!= def
409416
<*> o .:? "ipfs_gateway" .!= ["https://ipfs.io/ipfs"]
417+
<*> o .:? "snapshot_interval" .!= def
410418

411419
instance FromJSON SyncProtocol where
412420
parseJSON o =
@@ -728,6 +736,26 @@ instance FromJSON JsonTypeConfig where
728736
"disable" -> pure JsonTypeDisable
729737
other -> fail $ "unexpected json_type: " <> show other
730738

739+
instance ToJSON SnapshotIntervalConfig where
740+
toJSON cfg =
741+
Aeson.object
742+
[ "following" .= sicFollowing cfg
743+
, "lagging" .= sicLagging cfg
744+
]
745+
746+
instance FromJSON SnapshotIntervalConfig where
747+
parseJSON = Aeson.withObject "snapshot_interval" $ \obj ->
748+
SnapshotIntervalConfig
749+
<$> obj .: "following"
750+
<*> obj .: "lagging"
751+
752+
instance Default SnapshotIntervalConfig where
753+
def =
754+
SnapshotIntervalConfig
755+
{ sicFollowing = 500 -- Every 500 blocks when near tip
756+
, sicLagging = 100000 -- Every 100,000 blocks when syncing (less frequent)
757+
}
758+
731759
instance Default SyncInsertConfig where
732760
def = SyncInsertConfig Nothing def
733761

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

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -186,8 +186,8 @@ mkHasLedgerEnv trce protoInfo dir nw systemStart syncOptions = do
186186
, leNetwork = nw
187187
, leSystemStart = systemStart
188188
, leAbortOnPanic = soptAbortOnInvalid syncOptions
189-
, leSnapshotEveryFollowing = snapshotEveryFollowing syncOptions
190-
, leSnapshotEveryLagging = snapshotEveryLagging syncOptions
189+
, leSnapshotEveryFollowing = sicFollowing $ soptSnapshotInterval syncOptions
190+
, leSnapshotEveryLagging = sicLagging $ soptSnapshotInterval syncOptions
191191
, leInterpreter = intervar
192192
, leStateVar = svar
193193
, leStateWriteQueue = swQueue
@@ -330,7 +330,8 @@ storeSnapshotAndCleanupMaybe env oldState appResult blkNo isCons syncState =
330330
Just newEpoch
331331
| newEpochNo <- unEpochNo (Generic.neEpoch newEpoch)
332332
, newEpochNo > 0
333-
, isCons || (newEpochNo `mod` 10 == 0) || newEpochNo >= 530 ->
333+
, -- Snapshot every epoch when near tip, every 10 epochs when lagging, or always for epoch >= 580
334+
(isCons && syncState == SyncFollowing) || (newEpochNo `mod` 10 == 0) || newEpochNo >= 580 ->
334335
do
335336
-- TODO: Instead of newEpochNo - 1, is there any way to get the epochNo from 'lssOldState'?
336337
liftIO $ saveCleanupState env oldState (Just $ EpochNo $ newEpochNo - 1)
@@ -403,7 +404,8 @@ ledgerStateWriteLoop tracer swQueue codecConfig =
403404

404405
mkLedgerStateFilename :: LedgerStateDir -> ExtLedgerState CardanoBlock -> Maybe EpochNo -> WithOrigin FilePath
405406
mkLedgerStateFilename dir ledger mEpochNo =
406-
lsfFilePath . dbPointToFileName dir mEpochNo
407+
lsfFilePath
408+
. dbPointToFileName dir mEpochNo
407409
<$> getPoint (ledgerTipPoint @CardanoBlock (ledgerState ledger))
408410

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

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

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,13 @@ 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)
67+
<*> Gen.word64 (Range.linear 10000 100000)
6168

6269
syncNodeParams :: MonadGen m => m SyncNodeParams
6370
syncNodeParams =
@@ -71,8 +78,6 @@ syncNodeParams =
7178
<*> Gen.bool
7279
<*> Gen.bool
7380
<*> Gen.bool
74-
<*> Gen.word64 (Range.linear 0 1000)
75-
<*> Gen.word64 (Range.linear 0 1000)
7681
<*> pure Nothing
7782

7883
syncNodeConfig :: Logging.Configuration -> Gen SyncNodeConfig
@@ -104,6 +109,7 @@ syncNodeConfig loggingCfg =
104109
<*> triggerHardFork
105110
<*> syncInsertOptions
106111
<*> pure []
112+
<*> snapshotIntervalConfig
107113

108114
syncInsertConfig :: Gen SyncInsertConfig
109115
syncInsertConfig =

doc/configuration.md

Lines changed: 53 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,55 @@ 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+
| [following](#following) | `integer` | Optional | 500 |
620+
| [lagging](#lagging) | `integer` | Optional | 100000 |
621+
622+
### Following
623+
624+
`snapshot_interval.following`
625+
626+
* Type: `integer`
627+
* Default: `500`
628+
629+
Number of blocks between snapshots when db-sync is near the tip of the chain (within approximately 10 minutes). More frequent snapshots when following the tip ensure faster recovery from rollbacks.
630+
631+
### Lagging
632+
633+
`snapshot_interval.lagging`
634+
635+
* Type: `integer`
636+
* Default: `100000`
637+
638+
Number of blocks between snapshots when db-sync is syncing and significantly behind the tip of the chain. Less frequent snapshots during initial sync improves performance by reducing expensive disk operations.
639+
640+
### Example
641+
642+
```json
643+
{
644+
"snapshot_interval": {
645+
"following": 500,
646+
"lagging": 100000
647+
}
648+
}
649+
```
650+
651+
### Performance Considerations
652+
653+
- **Smaller `following` value**: Faster recovery from rollbacks when near the tip, but more frequent disk writes
654+
- **Larger `lagging` value**: Faster initial sync with reduced IOPS, but slower recovery if rollback is needed during sync
655+
- **Recommended for initial sync**: Use a large `lagging` value (50000-100000) to maximise sync speed
656+
- **Recommended when near tip**: Use a small `following` value (500-1000) to enable quick rollback recovery
657+

0 commit comments

Comments
 (0)