Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Fix commit error on GraphQL service startup #1802

Merged
merged 16 commits into from
Apr 4, 2024
Merged
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ Description of the upcoming release here.

### Fixed

- [#1802](https://github.com/FuelLabs/fuel-core/pull/1802): Fixed a runtime panic that occurred when restarting a node. The panic was caused by an invalid database commit while loading an existing off-chain database. The invalid commit is removed in this PR.
- [#1795](https://github.com/FuelLabs/fuel-core/pull/1795): Fixed the building of the `fuel-core-wasm-executor` to work outside of the `fuel-core` context. The change uses the path to the manifest file of the `fuel-core-upgradable-executor` to build the `fuel-core-wasm-executor` instead of relying on the workspace.

## [Version 0.24.1]
Expand Down
3 changes: 3 additions & 0 deletions crates/fuel-core/src/graphql_api/ports.rs
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,9 @@ pub mod worker {
/// Returns the total count after the update.
fn increase_tx_count(&mut self, new_txs_count: u64) -> StorageResult<u64>;

/// Gets the total number of transactions on the chain from metadata.
fn get_tx_count(&self) -> StorageResult<u64>;

/// Commits the underlying changes into the database.
fn commit(self) -> StorageResult<()>;
}
Expand Down
9 changes: 9 additions & 0 deletions crates/fuel-core/src/graphql_api/storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ use fuel_core_storage::{
Error as StorageError,
Result as StorageResult,
StorageAsMut,
StorageInspect,
StorageMutate,
};
use fuel_core_types::{
Expand Down Expand Up @@ -141,6 +142,14 @@ where
Ok(new_tx_count)
}

fn get_tx_count(&self) -> StorageResult<u64> {
const TX_COUNT: &str = "total_tx_count";
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be nice to move it on one level upper. And reuse inside of the increase_tx_count

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By one level up, do you mean the Transactional trait?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean reuse one constant in two functions=) Define it on file level instead of function level


let tx_count = *<_ as StorageInspect<StatisticTable<u64>>>::get(self, TX_COUNT)?
.unwrap_or_default();
Ok(tx_count)
}

fn commit(self) -> StorageResult<()> {
self.commit()?;
Ok(())
Expand Down
9 changes: 5 additions & 4 deletions crates/fuel-core/src/graphql_api/worker_service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -323,10 +323,11 @@ where
_: &StateWatcher,
_: Self::TaskParams,
) -> anyhow::Result<Self::Task> {
let mut db_tx = self.database.transaction();
let total_tx_count = db_tx.increase_tx_count(0).unwrap_or_default();
db_tx.commit()?;
graphql_metrics().total_txs_count.set(total_tx_count as i64);
{
let db_tx = self.database.transaction();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if we aren't doing a commit here, do we still need a transaction?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, we don't, but it will require changing of constraints for the port=D I'm okay with using transaction for now to just fix the issue and release a new fuel-core with the fix=)

let total_tx_count = db_tx.get_tx_count().unwrap_or_default();
graphql_metrics().total_txs_count.set(total_tx_count as i64);
}

// TODO: It is possible that the node was shut down before we processed all imported blocks.
// It could lead to some missed blocks and the database's inconsistent state.
Expand Down
37 changes: 37 additions & 0 deletions tests/tests/health.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
use fuel_core::{
combined_database::CombinedDatabase,
database::Database,
service::{
Config,
FuelService,
},
types::fuel_tx::Transaction,
};
use fuel_core_client::client::FuelClient;

Expand Down Expand Up @@ -41,3 +43,38 @@ async fn can_restart_node() {
.unwrap();
}
}

#[tokio::test]
async fn can_restart_node_with_transactions() {
use fuel_core::service::ServiceTrait;

let capacity = 1024 * 1024;
let tmp_dir = tempfile::TempDir::new().unwrap();

{
let database = CombinedDatabase::open(tmp_dir.path(), capacity).unwrap();
let service = FuelService::from_combined_database(database, Config::local_node())
.await
.unwrap();
let client = FuelClient::from(service.bound_address);
client.health().await.unwrap();

for _ in 0..5 {
let tx = Transaction::default_test_tx();
client.submit_and_await_commit(&tx).await.unwrap();
}

service.stop_and_await().await.unwrap();
}

{
let database = CombinedDatabase::open(tmp_dir.path(), capacity).unwrap();
let service = FuelService::from_combined_database(database, Config::local_node())
.await
.unwrap();
let client = FuelClient::from(service.bound_address);
client.health().await.unwrap();

service.stop_and_await().await.unwrap();
}
}
Loading