MCPcopy Create free account
hub / github.com/clockworklabs/SpacetimeDB / update_module

Method update_module

crates/core/src/host/host_controller.rs:1193–1261  ·  view source on GitHub ↗
(
        &mut self,
        runtimes: Arc<HostRuntimes>,
        program: Program,
        policy: MigrationPolicy,
        energy_monitor: Arc<dyn EnergyMonitor>,
        on_panic: impl Fn() + Send 

Source from the content-addressed store, hash-verified

1191 /// Either way, the [`UpdateDatabaseResult`] is returned.
1192 #[allow(clippy::too_many_arguments)]
1193 async fn update_module(
1194 &mut self,
1195 runtimes: Arc<HostRuntimes>,
1196 program: Program,
1197 policy: MigrationPolicy,
1198 energy_monitor: Arc<dyn EnergyMonitor>,
1199 on_panic: impl Fn() + Send + Sync + 'static,
1200 core: AllocatedJobCore,
1201 ) -> anyhow::Result<UpdateDatabaseResult> {
1202 let replica_ctx = &self.replica_ctx;
1203 let (scheduler, scheduler_starter) = Scheduler::open(self.replica_ctx.relational_db().clone());
1204
1205 let (program, module) = make_module_host(
1206 runtimes,
1207 replica_ctx.clone(),
1208 scheduler.clone(),
1209 program,
1210 energy_monitor,
1211 on_panic,
1212 core,
1213 )
1214 .await?;
1215
1216 // Get the old module info to diff against when building a migration plan.
1217 let old_module_info = self.module.borrow().info.clone();
1218
1219 let update_result =
1220 update_module(replica_ctx.relational_db(), &module, program, old_module_info, policy).await?;
1221
1222 // Only replace the module + scheduler if the update succeeded.
1223 // Otherwise, we want the database to continue running with the old state.
1224 match update_result {
1225 UpdateDatabaseResult::NoUpdateNeeded | UpdateDatabaseResult::UpdatePerformed { .. } => {
1226 self.scheduler = scheduler;
1227 scheduler_starter.start(&module)?;
1228 let old_module = self.module.send_replace(module);
1229 old_module.exit().await;
1230 }
1231
1232 // In this case, we need to disconnect all clients connected to the old module
1233 UpdateDatabaseResult::UpdatePerformedWithClientDisconnect { .. } => {
1234 // Replace the module first, so that new clients get the new module.
1235 let old_watcher = std::mem::replace(&mut self.module, watch::Sender::new(module.clone()));
1236
1237 // Disconnect all clients connected to the old module.
1238 let connected_clients = replica_ctx.relational_db().connected_clients()?;
1239 for (identity, connection_id) in connected_clients {
1240 let client_actor_id = ClientActorId {
1241 identity,
1242 connection_id,
1243 name: ClientName(0),
1244 };
1245 //NOTE: This will call disconnect reducer of the new module, not the old one.
1246 //It makes sense, as relationaldb is already updated to the new module.
1247 module.disconnect_client(client_actor_id).await;
1248 }
1249
1250 self.scheduler = scheduler;

Callers 1

update_module_hostMethod · 0.80

Calls 13

make_module_hostFunction · 0.85
update_moduleFunction · 0.85
ClientNameClass · 0.85
exitMethod · 0.80
openFunction · 0.50
newFunction · 0.50
OkFunction · 0.50
cloneMethod · 0.45
relational_dbMethod · 0.45
borrowMethod · 0.45
startMethod · 0.45
connected_clientsMethod · 0.45

Tested by

no test coverage detected