Skip to content

Commit d69797a

Browse files
Add a database bootstrap generation
1 parent 58660ad commit d69797a

6 files changed

Lines changed: 23 additions & 16 deletions

File tree

crates/core/src/host/host_controller.rs

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -100,14 +100,14 @@ pub struct ModuleHostWithBootstrap {
100100
/// The handle owns any wait state needed to prove that the database has a
101101
/// durable `st_module` row.
102102
pub struct BootstrapCompletion {
103-
program_hash: Hash,
103+
bootstrap_generation: u64,
104104
status: ProgramBootstrap,
105105
}
106106

107107
/// Has the module been bootstrapped from the controldb?
108108
///
109109
/// Once we have inserted into `st_module`, bootstrapping is no longer necessary,
110-
/// and the initial program bytes can be dropped fromt the controldb.
110+
/// and the initial program bytes can be dropped from the controldb.
111111
enum ProgramBootstrap {
112112
/// The module's program bytes have already been written to `st_module`
113113
Durable,
@@ -119,32 +119,32 @@ enum ProgramBootstrap {
119119
}
120120

121121
impl BootstrapCompletion {
122-
fn durable(program_hash: Hash) -> Self {
122+
fn durable(bootstrap_generation: u64) -> Self {
123123
Self {
124-
program_hash,
124+
bootstrap_generation,
125125
status: ProgramBootstrap::Durable,
126126
}
127127
}
128128

129-
fn pending(program_hash: Hash, tx_offset: TransactionOffset, durable_offset: Option<DurableOffset>) -> Self {
129+
fn pending(bootstrap_generation: u64, tx_offset: TransactionOffset, durable_offset: Option<DurableOffset>) -> Self {
130130
Self {
131-
program_hash,
131+
bootstrap_generation,
132132
status: ProgramBootstrap::Pending {
133133
tx_offset,
134134
durable_offset,
135135
},
136136
}
137137
}
138138

139-
pub fn program_hash(&self) -> Hash {
140-
self.program_hash
139+
pub fn bootstrap_generation(&self) -> u64 {
140+
self.bootstrap_generation
141141
}
142142

143143
/// Wait until it is safe to complete program bootstrap in controldb.
144144
/// That is, wait until the initial `st_module` insert becomes durable.
145-
pub async fn wait(self) -> anyhow::Result<Hash> {
145+
pub async fn wait(self) -> anyhow::Result<()> {
146146
match self.status {
147-
ProgramBootstrap::Durable => Ok(self.program_hash),
147+
ProgramBootstrap::Durable => Ok(()),
148148
ProgramBootstrap::Pending {
149149
tx_offset,
150150
durable_offset,
@@ -160,7 +160,7 @@ impl BootstrapCompletion {
160160
.context("failed waiting for initialized program to become durable")?;
161161
}
162162

163-
Ok(self.program_hash)
163+
Ok(())
164164
}
165165
}
166166
}
@@ -1132,7 +1132,8 @@ impl Host {
11321132
(program, true)
11331133
}
11341134
};
1135-
let mut bootstrap_completion = Some(BootstrapCompletion::durable(program.hash));
1135+
let bootstrap_generation = database.bootstrap_generation;
1136+
let mut bootstrap_completion = Some(BootstrapCompletion::durable(bootstrap_generation));
11361137

11371138
let relational_db = Arc::new(db);
11381139
let (program, launched) = match HostType::from(program.kind) {
@@ -1222,13 +1223,12 @@ impl Host {
12221223
};
12231224

12241225
if program_needs_init {
1225-
let program_hash = program.hash;
12261226
let InitDatabaseResult { reducer, tx_offset } = launched.module_host.init_database(program).await?;
12271227
if let Some(call_result) = reducer {
12281228
Result::from(call_result)?;
12291229
}
12301230
bootstrap_completion = Some(BootstrapCompletion::pending(
1231-
program_hash,
1231+
bootstrap_generation,
12321232
tx_offset,
12331233
launched.module_host.durable_tx_offset(),
12341234
));
@@ -1540,6 +1540,7 @@ pub(crate) async fn extract_schema_with_pools(
15401540
owner_identity,
15411541
host_type,
15421542
initial_program: program.hash,
1543+
bootstrap_generation: 0,
15431544
};
15441545

15451546
let core = AllocatedJobCore::default();

crates/core/src/host/instance_env.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1377,6 +1377,7 @@ mod test {
13771377
owner_identity: Identity::ZERO,
13781378
host_type: HostType::Wasm,
13791379
initial_program: Hash::ZERO,
1380+
bootstrap_generation: 0,
13801381
},
13811382
replica_id: 0,
13821383
logger,

crates/core/src/messages/control_db.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ pub struct Database {
3737
///
3838
/// Updating the database's module will **not** change this value.
3939
pub initial_program: Hash,
40+
/// Generation of the current bootstrap requirement for `initial_program`.
41+
pub bootstrap_generation: u64,
4042
}
4143

4244
#[derive(Clone, PartialEq, Serialize, Deserialize)]

crates/standalone/src/control_db.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -668,6 +668,7 @@ mod compat {
668668
owner_identity,
669669
host_type,
670670
initial_program,
671+
bootstrap_generation: 0,
671672
}
672673
}
673674
}
@@ -680,6 +681,7 @@ mod compat {
680681
owner_identity,
681682
host_type,
682683
initial_program,
684+
bootstrap_generation: _,
683685
}: CanonicalDatabase,
684686
) -> Self {
685687
Self {

crates/standalone/src/control_db/tests.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ fn test_decode() -> ResultTest<()> {
126126
owner_identity: id,
127127
host_type: HostType::Wasm,
128128
initial_program: Hash::ZERO,
129+
bootstrap_generation: 0,
129130
};
130131

131132
cdb.insert_database(db.clone())?;

crates/standalone/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,7 @@ impl spacetimedb_client_api::ControlStateWriteAccess for StandaloneEnv {
292292
owner_identity: *publisher,
293293
host_type: spec.host_type,
294294
initial_program: program.hash,
295+
bootstrap_generation: 0,
295296
};
296297

297298
let _hash_for_assert = program.hash;
@@ -432,9 +433,8 @@ impl spacetimedb_client_api::ControlStateWriteAccess for StandaloneEnv {
432433
.await?;
433434
let _stored_hash_for_assert = self.program_store.put(program_bytes).await?;
434435
debug_assert_eq!(_hash_for_assert, _stored_hash_for_assert);
435-
436-
self.control_db.update_database(database)?;
437436
}
437+
self.control_db.update_database(database)?;
438438

439439
for instance in self.control_db.get_replicas_by_database(database_id)? {
440440
self.delete_replica(instance.id).await?;

0 commit comments

Comments
 (0)