Skip to content

Commit

Permalink
[ENG-7377] Block storage access if backend not running (#30127)
Browse files Browse the repository at this point in the history
GitOrigin-RevId: 589909c731163f8e4ccb1195997a6a5c7d0cf506
  • Loading branch information
pashabitz authored and Convex, Inc. committed Sep 26, 2024
1 parent 096031c commit 3a53718
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 0 deletions.
17 changes: 17 additions & 0 deletions crates/application/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ use minitrace::{
};
use model::{
auth::AuthInfoModel,
backend_state::BackendStateModel,
components::{
config::ComponentConfigModel,
handles::FunctionHandlesModel,
Expand Down Expand Up @@ -2312,6 +2313,19 @@ impl<RT: Runtime> Application<RT> {
Ok(())
}

async fn bail_if_not_running(&self) -> anyhow::Result<()> {
let backend_state = BackendStateModel::new(&mut self.begin(Identity::Unknown).await?)
.get_backend_state()
.await?;
if backend_state.is_stopped() {
anyhow::bail!(ErrorMetadata::bad_request(
"BackendIsNotRunning",
"Cannot perform this operation when the backend is not running"
));
}
Ok(())
}

pub async fn store_file(
&self,
component: ComponentId,
Expand All @@ -2320,6 +2334,7 @@ impl<RT: Runtime> Application<RT> {
expected_sha256: Option<Sha256Digest>,
body: BoxStream<'_, anyhow::Result<Bytes>>,
) -> anyhow::Result<DeveloperDocumentId> {
self.bail_if_not_running().await?;
let storage_id = self
.file_storage
.store_file(
Expand Down Expand Up @@ -2374,6 +2389,7 @@ impl<RT: Runtime> Application<RT> {
component: ComponentId,
storage_id: FileStorageId,
) -> anyhow::Result<FileStream> {
self.bail_if_not_running().await?;
let file_entry = self.get_file_entry(component, storage_id).await?;
self
.file_storage
Expand All @@ -2389,6 +2405,7 @@ impl<RT: Runtime> Application<RT> {
storage_id: FileStorageId,
bytes_range: (Bound<u64>, Bound<u64>),
) -> anyhow::Result<FileRangeStream> {
self.bail_if_not_running().await?;
let mut file_storage_tx = self.begin(Identity::system()).await?;

let Some(file_entry) = self
Expand Down
1 change: 1 addition & 0 deletions crates/application/src/tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ mod returns_validation;
mod scheduled_jobs;
mod schema;
mod source_package;
mod storage;

const NODE_SOURCE: &str = r#"
var nodeFunction = () => {};
Expand Down
46 changes: 46 additions & 0 deletions crates/application/src/tests/storage.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
use common::{
components::ComponentId,
types::BackendState,
};
use errors::ErrorMetadataAnyhowExt;
use futures::stream;
use keybroker::Identity;
use model::backend_state::BackendStateModel;
use runtime::testing::TestRuntime;

use crate::{
test_helpers::ApplicationTestExt,
Application,
};

#[convex_macro::test_runtime]
pub(crate) async fn test_backend_not_running_cannot_store_file(
rt: TestRuntime,
) -> anyhow::Result<()> {
let app = Application::new_for_tests(&rt).await?;

let file_body = Box::pin(stream::once(async {
Ok(bytes::Bytes::from(vec![55; 1024 + 1]))
}));
let ok_result = app
.store_file(ComponentId::Root, None, None, None, file_body)
.await;
assert!(ok_result.is_ok());

let mut tx = app.begin(Identity::system()).await?;
BackendStateModel::new(&mut tx)
.toggle_backend_state(BackendState::Disabled)
.await?;
app.commit_test(tx).await?;
let file_body = Box::pin(stream::once(async {
Ok(bytes::Bytes::from(vec![55; 1024 + 1]))
}));
let result = app
.store_file(ComponentId::Root, None, None, None, file_body)
.await;
assert!(result.is_err());
let error = result.unwrap_err();
assert!(error.is_bad_request());
assert_eq!(error.short_msg(), "BackendIsNotRunning");
Ok(())
}

0 comments on commit 3a53718

Please sign in to comment.