Skip to content

Commit e55816e

Browse files
committed
Reset database
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.
1 parent db21fce commit e55816e

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;
@@ -162,7 +163,7 @@ pub struct DatabaseDef {
162163
/// The [`Identity`] the database shall have.
163164
pub database_identity: Identity,
164165
/// The compiled program of the database module.
165-
pub program_bytes: Vec<u8>,
166+
pub program_bytes: Bytes,
166167
/// The desired number of replicas the database shall have.
167168
///
168169
/// If `None`, the edition default is used.
@@ -171,6 +172,14 @@ pub struct DatabaseDef {
171172
pub host_type: HostType,
172173
}
173174

175+
/// Parameters for resetting a database via [`ControlStateDelegate::reset_database`].
176+
pub struct DatabaseResetDef {
177+
pub database_identity: Identity,
178+
pub program_bytes: Option<Bytes>,
179+
pub num_replicas: Option<NonZeroU8>,
180+
pub host_type: Option<HostType>,
181+
}
182+
174183
/// API of the SpacetimeDB control plane.
175184
///
176185
/// The trait is the composition of [`ControlStateReadAccess`] and
@@ -240,6 +249,10 @@ pub trait ControlStateWriteAccess: Send + Sync {
240249

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

252+
/// Remove all data from a database, and reset it according to the
253+
/// given [DatabaseResetDef].
254+
async fn reset_database(&self, caller_identity: &Identity, spec: DatabaseResetDef) -> anyhow::Result<()>;
255+
243256
// Energy
244257
async fn add_energy(&self, identity: &Identity, amount: EnergyQuanta) -> anyhow::Result<()>;
245258
async fn withdraw_energy(&self, identity: &Identity, amount: EnergyQuanta) -> anyhow::Result<()>;
@@ -339,6 +352,10 @@ impl<T: ControlStateWriteAccess + ?Sized> ControlStateWriteAccess for Arc<T> {
339352
(**self).delete_database(caller_identity, database_identity).await
340353
}
341354

355+
async fn reset_database(&self, caller_identity: &Identity, spec: DatabaseResetDef) -> anyhow::Result<()> {
356+
(**self).reset_database(caller_identity, spec).await
357+
}
358+
342359
async fn add_energy(&self, identity: &Identity, amount: EnergyQuanta) -> anyhow::Result<()> {
343360
(**self).add_energy(identity, amount).await
344361
}

0 commit comments

Comments
 (0)