@@ -54,6 +54,7 @@ import (
54
54
"github.com/onflow/flow-go/engine/execution/ingestion/fetcher"
55
55
"github.com/onflow/flow-go/engine/execution/ingestion/stop"
56
56
"github.com/onflow/flow-go/engine/execution/ingestion/uploader"
57
+ "github.com/onflow/flow-go/engine/execution/migration"
57
58
exeprovider "github.com/onflow/flow-go/engine/execution/provider"
58
59
exepruner "github.com/onflow/flow-go/engine/execution/pruner"
59
60
"github.com/onflow/flow-go/engine/execution/rpc"
@@ -92,10 +93,13 @@ import (
92
93
"github.com/onflow/flow-go/state/protocol/blocktimer"
93
94
storageerr "github.com/onflow/flow-go/storage"
94
95
storage "github.com/onflow/flow-go/storage/badger"
96
+ "github.com/onflow/flow-go/storage/dbops"
95
97
"github.com/onflow/flow-go/storage/operation"
98
+ "github.com/onflow/flow-go/storage/operation/badgerimpl"
96
99
"github.com/onflow/flow-go/storage/operation/pebbleimpl"
97
100
storagepebble "github.com/onflow/flow-go/storage/pebble"
98
101
"github.com/onflow/flow-go/storage/store"
102
+ "github.com/onflow/flow-go/storage/store/chained"
99
103
)
100
104
101
105
const (
@@ -136,13 +140,17 @@ type ExecutionNode struct {
136
140
registerStore * storehouse.RegisterStore
137
141
138
142
// storage
139
- events storageerr.Events
140
- serviceEvents storageerr.ServiceEvents
141
- txResults storageerr.TransactionResults
142
- results storageerr.ExecutionResults
143
- receipts storageerr.ExecutionReceipts
144
- myReceipts storageerr.MyExecutionReceipts
145
- commits storageerr.Commits
143
+ events storageerr.Events
144
+ eventsReader storageerr.EventsReader
145
+ serviceEvents storageerr.ServiceEvents
146
+ txResults storageerr.TransactionResults
147
+ txResultsReader storageerr.TransactionResultsReader
148
+ results storageerr.ExecutionResults
149
+ resultsReader storageerr.ExecutionResultsReader
150
+ receipts storageerr.ExecutionReceipts
151
+ myReceipts storageerr.MyExecutionReceipts
152
+ commits storageerr.Commits
153
+ commitsReader storageerr.CommitsReader
146
154
147
155
chunkDataPackDB * pebble.DB
148
156
chunkDataPacks storageerr.ChunkDataPacks
@@ -216,11 +224,11 @@ func (builder *ExecutionNodeBuilder) LoadComponentsAndModules() {
216
224
Module ("blobservice peer manager dependencies" , exeNode .LoadBlobservicePeerManagerDependencies ).
217
225
Module ("bootstrap" , exeNode .LoadBootstrapper ).
218
226
Module ("register store" , exeNode .LoadRegisterStore ).
227
+ Module ("migrate last executed block" , exeNode .MigrateLastSealedExecutedResultToPebble ).
219
228
AdminCommand ("get-transactions" , func (conf * NodeConfig ) commands.AdminCommand {
220
229
return storageCommands .NewGetTransactionsCommand (conf .State , conf .Storage .Payloads , exeNode .collections )
221
230
}).
222
231
Component ("execution state ledger" , exeNode .LoadExecutionStateLedger ).
223
-
224
232
// TODO: Modules should be able to depends on components
225
233
// Because all modules are always bootstrapped first, before components,
226
234
// its not possible to have a module depending on a Component.
@@ -331,15 +339,32 @@ func (exeNode *ExecutionNode) LoadExecutionStorage(
331
339
node * NodeConfig ,
332
340
) error {
333
341
db := node .ProtocolDB
342
+
343
+ exeNode .events = store .NewEvents (node .Metrics .Cache , db )
344
+ exeNode .serviceEvents = store .NewServiceEvents (node .Metrics .Cache , db )
334
345
exeNode .commits = store .NewCommits (node .Metrics .Cache , db )
335
346
exeNode .results = store .NewExecutionResults (node .Metrics .Cache , db )
336
347
exeNode .receipts = store .NewExecutionReceipts (node .Metrics .Cache , db , exeNode .results , storage .DefaultCacheSize )
337
348
exeNode .myReceipts = store .NewMyExecutionReceipts (node .Metrics .Cache , db , exeNode .receipts )
338
-
339
- // Needed for gRPC server, make sure to assign to main scoped vars
340
- exeNode .events = store .NewEvents (node .Metrics .Cache , db )
341
- exeNode .serviceEvents = store .NewServiceEvents (node .Metrics .Cache , db )
342
349
exeNode .txResults = store .NewTransactionResults (node .Metrics .Cache , db , exeNode .exeConf .transactionResultsCacheSize )
350
+
351
+ if dbops .IsBadgerBased (node .dbops ) {
352
+ // if data are stored in badger, we can use the same storage for all data
353
+ exeNode .eventsReader = exeNode .events
354
+ exeNode .commitsReader = exeNode .commits
355
+ exeNode .resultsReader = exeNode .results
356
+ exeNode .txResultsReader = exeNode .txResults
357
+ } else if dbops .IsPebbleBatch (node .dbops ) {
358
+ // when data are stored in pebble, we need to use chained storage to query data from
359
+ // both pebble and badger
360
+ // note the pebble storage is the first argument, and badger storage is the second, so
361
+ // the data will be queried from pebble first, then badger
362
+ badgerDB := badgerimpl .ToDB (node .DB )
363
+ exeNode .eventsReader = chained .NewEvents (exeNode .events , store .NewEvents (node .Metrics .Cache , badgerDB ))
364
+ exeNode .commitsReader = chained .NewCommits (exeNode .commits , store .NewCommits (node .Metrics .Cache , badgerDB ))
365
+ exeNode .resultsReader = chained .NewExecutionResults (exeNode .results , store .NewExecutionResults (node .Metrics .Cache , badgerDB ))
366
+ exeNode .txResultsReader = chained .NewTransactionResults (exeNode .txResults , store .NewTransactionResults (node .Metrics .Cache , badgerDB , exeNode .exeConf .transactionResultsCacheSize ))
367
+ }
343
368
return nil
344
369
}
345
370
@@ -470,6 +495,7 @@ func (exeNode *ExecutionNode) LoadGCPBlockDataUploader(
470
495
)
471
496
472
497
// Setting up RetryableUploader for GCP uploader
498
+ // deprecated
473
499
retryableUploader := uploader .NewBadgerRetryableUploaderWrapper (
474
500
asyncUploader ,
475
501
node .Storage .Blocks ,
@@ -730,6 +756,16 @@ func (exeNode *ExecutionNode) LoadExecutionDataGetter(node *NodeConfig) error {
730
756
return nil
731
757
}
732
758
759
+ func (exeNode * ExecutionNode ) MigrateLastSealedExecutedResultToPebble (node * NodeConfig ) error {
760
+ // Migrate the last sealed executed
761
+ err := migration .MigrateLastSealedExecutedResultToPebble (node .Logger , node .DB , node .PebbleDB , node .State , node .RootSeal )
762
+ if err != nil {
763
+ return fmt .Errorf ("could not migrate last sealed executed result to pebble: %w" , err )
764
+ }
765
+
766
+ return nil
767
+ }
768
+
733
769
func (exeNode * ExecutionNode ) LoadExecutionState (
734
770
node * NodeConfig ,
735
771
) (
@@ -765,6 +801,8 @@ func (exeNode *ExecutionNode) LoadExecutionState(
765
801
exeNode .chunkDataPackDB = chunkDataPackDB
766
802
exeNode .chunkDataPacks = chunkDataPacks
767
803
804
+ // migrate execution data for last sealed and executed block
805
+
768
806
exeNode .executionState = state .NewExecutionState (
769
807
exeNode .ledgerStorage ,
770
808
exeNode .commits ,
@@ -1353,10 +1391,10 @@ func (exeNode *ExecutionNode) LoadGrpcServer(
1353
1391
exeNode .scriptsEng ,
1354
1392
node .Storage .Headers ,
1355
1393
node .State ,
1356
- exeNode .events ,
1357
- exeNode .results ,
1358
- exeNode .txResults ,
1359
- exeNode .commits ,
1394
+ exeNode .eventsReader ,
1395
+ exeNode .resultsReader ,
1396
+ exeNode .txResultsReader ,
1397
+ exeNode .commitsReader ,
1360
1398
exeNode .metricsProvider ,
1361
1399
node .RootChainID ,
1362
1400
signature .NewBlockSignerDecoder (exeNode .committee ),
@@ -1370,7 +1408,10 @@ func (exeNode *ExecutionNode) LoadBootstrapper(node *NodeConfig) error {
1370
1408
// check if the execution database already exists
1371
1409
bootstrapper := bootstrap .NewBootstrapper (node .Logger )
1372
1410
1373
- commit , bootstrapped , err := bootstrapper .IsBootstrapped (node .ProtocolDB )
1411
+ // in order to support switching from badger to pebble in the middle of the spork,
1412
+ // we will check if the execution database has been bootstrapped by reading the state from badger db.
1413
+ // and if not, bootstrap both badger and pebble db.
1414
+ commit , bootstrapped , err := bootstrapper .IsBootstrapped (badgerimpl .ToDB (node .DB ))
1374
1415
if err != nil {
1375
1416
return fmt .Errorf ("could not query database to know whether database has been bootstrapped: %w" , err )
1376
1417
}
@@ -1395,7 +1436,12 @@ func (exeNode *ExecutionNode) LoadBootstrapper(node *NodeConfig) error {
1395
1436
return fmt .Errorf ("could not load bootstrap state from checkpoint file: %w" , err )
1396
1437
}
1397
1438
1398
- err = bootstrapper .BootstrapExecutionDatabase (node .ProtocolDB , node .RootSeal )
1439
+ err = bootstrapper .BootstrapExecutionDatabase (badgerimpl .ToDB (node .DB ), node .RootSeal )
1440
+ if err != nil {
1441
+ return fmt .Errorf ("could not bootstrap execution database: %w" , err )
1442
+ }
1443
+
1444
+ err = bootstrapper .BootstrapExecutionDatabase (pebbleimpl .ToDB (node .PebbleDB ), node .RootSeal )
1399
1445
if err != nil {
1400
1446
return fmt .Errorf ("could not bootstrap execution database: %w" , err )
1401
1447
}
0 commit comments