Skip to content

Commit e0b8e6f

Browse files
authored
[teams 1/5] Reset database (#3611)
So far, the `--clear-database` option to `publish` has simply dropped and then re-created the database (if it did exist). This will no longer work when databases can have "children": because dropping and re-creating is not atomic, children would either become orphans, or be dropped as well. To solve this, `reset_database` is introduced as a separate action that: - shuts down all replicas - if a `program_bytes` is supplied, replaces the database's initial program - if a `host_type` is supplied, replaces the database's host type - starts `num_replicas` or the previous number of replicas, which initialize themselves as normal As this could be its own CLI command, the action is provided as its own API endpoint (undocumented). However, since `publish` has no way of knowing whether the database it operates on actually exists, the `publish_database` handler will just invoke the `reset_database` handler if `clear=true` and the database exists, and return its result. This is to avoid starting the transfer of the program in the request body, only to receive a redirect. Some refactoring was necessary to dissect and understand the flow. # API and ABI breaking changes Introduces a new, undocumented API endpoint. We may want to nest it under `/unstable`. # Expected complexity level and risk 2 # Testing From the outside, the observed behavior should be as before, so smoketests should cover it.
1 parent 08a00ef commit e0b8e6f

File tree

10 files changed

+344
-156
lines changed

10 files changed

+344
-156
lines changed

Cargo.lock

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/cli/src/subcommands/publish.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ use std::path::PathBuf;
88
use std::{env, fs};
99

1010
use crate::config::Config;
11-
use crate::util::{add_auth_header_opt, get_auth_header, AuthHeader, ResponseExt};
12-
use crate::util::{decode_identity, unauth_error_context, y_or_n};
11+
use crate::util::{add_auth_header_opt, get_auth_header, unauth_error_context, AuthHeader, ResponseExt};
12+
use crate::util::{decode_identity, y_or_n};
1313
use crate::{build, common_args};
1414

1515
pub fn cli() -> clap::Command {

crates/client-api/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ scopeguard.workspace = true
5353
serde_with.workspace = true
5454
async-stream.workspace = true
5555
humantime.workspace = true
56+
thiserror.workspace = true
5657

5758
[target.'cfg(not(target_env = "msvc"))'.dependencies]
5859
jemalloc_pprof.workspace = true

crates/client-api/src/lib.rs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use std::sync::Arc;
33

44
use async_trait::async_trait;
55
use axum::response::ErrorResponse;
6+
use bytes::Bytes;
67
use http::StatusCode;
78

89
use spacetimedb::client::ClientActorIndex;
@@ -155,7 +156,7 @@ pub struct DatabaseDef {
155156
/// The [`Identity`] the database shall have.
156157
pub database_identity: Identity,
157158
/// The compiled program of the database module.
158-
pub program_bytes: Vec<u8>,
159+
pub program_bytes: Bytes,
159160
/// The desired number of replicas the database shall have.
160161
///
161162
/// If `None`, the edition default is used.
@@ -164,6 +165,14 @@ pub struct DatabaseDef {
164165
pub host_type: HostType,
165166
}
166167

168+
/// Parameters for resetting a database via [`ControlStateDelegate::reset_database`].
169+
pub struct DatabaseResetDef {
170+
pub database_identity: Identity,
171+
pub program_bytes: Option<Bytes>,
172+
pub num_replicas: Option<NonZeroU8>,
173+
pub host_type: Option<HostType>,
174+
}
175+
167176
/// API of the SpacetimeDB control plane.
168177
///
169178
/// The trait is the composition of [`ControlStateReadAccess`] and
@@ -233,6 +242,10 @@ pub trait ControlStateWriteAccess: Send + Sync {
233242

234243
async fn delete_database(&self, caller_identity: &Identity, database_identity: &Identity) -> anyhow::Result<()>;
235244

245+
/// Remove all data from a database, and reset it according to the
246+
/// given [DatabaseResetDef].
247+
async fn reset_database(&self, caller_identity: &Identity, spec: DatabaseResetDef) -> anyhow::Result<()>;
248+
236249
// Energy
237250
async fn add_energy(&self, identity: &Identity, amount: EnergyQuanta) -> anyhow::Result<()>;
238251
async fn withdraw_energy(&self, identity: &Identity, amount: EnergyQuanta) -> anyhow::Result<()>;
@@ -332,6 +345,10 @@ impl<T: ControlStateWriteAccess + ?Sized> ControlStateWriteAccess for Arc<T> {
332345
(**self).delete_database(caller_identity, database_identity).await
333346
}
334347

348+
async fn reset_database(&self, caller_identity: &Identity, spec: DatabaseResetDef) -> anyhow::Result<()> {
349+
(**self).reset_database(caller_identity, spec).await
350+
}
351+
335352
async fn add_energy(&self, identity: &Identity, amount: EnergyQuanta) -> anyhow::Result<()> {
336353
(**self).add_energy(identity, amount).await
337354
}

0 commit comments

Comments
 (0)