fix(plugins): synchronize event batch handling (#3367)

* fix(plugins): synchronize event batch handling

* style(fmt): rustfmt

* fix(tests): graceful shutdown for async tasks
This commit is contained in:
Aram Drevekenin 2024-05-22 11:09:10 +02:00 committed by GitHub
parent 64a5ac095c
commit fda5ab1830
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -563,57 +563,62 @@ impl WasmBridge {
.contains_key(&plugin_id) .contains_key(&plugin_id)
}) })
.collect(); .collect();
for (pid, cid, event) in updates.drain(..) { task::spawn({
for (plugin_id, client_id, running_plugin, subscriptions) in &plugins_to_update { let mut updates = updates.clone();
let subs = subscriptions.lock().unwrap().clone(); let senders = self.senders.clone();
// FIXME: This is very janky... Maybe I should write my own macro for Event -> EventType? let s = shutdown_sender.clone();
let event_type = async move {
EventType::from_str(&event.to_string()).with_context(err_context)?; let _s = s;
if (subs.contains(&event_type) || event_type == EventType::PermissionRequestResult) for (pid, cid, event) in updates.drain(..) {
&& Self::message_is_directed_at_plugin(pid, cid, plugin_id, client_id) for (plugin_id, client_id, running_plugin, subscriptions) in &plugins_to_update
{ {
task::spawn({ let subs = subscriptions.lock().unwrap().clone();
let senders = self.senders.clone(); // FIXME: This is very janky... Maybe I should write my own macro for Event -> EventType?
let running_plugin = running_plugin.clone(); if let Ok(event_type) = EventType::from_str(&event.to_string()) {
let event = event.clone(); if (subs.contains(&event_type)
let plugin_id = *plugin_id; || event_type == EventType::PermissionRequestResult)
let client_id = *client_id; && Self::message_is_directed_at_plugin(
let _s = shutdown_sender.clone(); pid, cid, plugin_id, client_id,
async move { )
let mut running_plugin = running_plugin.lock().unwrap(); {
let mut plugin_render_assets = vec![]; let mut running_plugin = running_plugin.lock().unwrap();
let _s = _s; // guard to allow the task to complete before cleanup/shutdown let mut plugin_render_assets = vec![];
match apply_event_to_plugin( match apply_event_to_plugin(
plugin_id, *plugin_id,
client_id, *client_id,
&mut running_plugin, &mut running_plugin,
&event, &event,
&mut plugin_render_assets, &mut plugin_render_assets,
senders.clone(), senders.clone(),
) { ) {
Ok(()) => { Ok(()) => {
let _ = senders.send_to_screen(ScreenInstruction::PluginBytes( let _ = senders.send_to_screen(
plugin_render_assets, ScreenInstruction::PluginBytes(plugin_render_assets),
)); );
}, },
Err(e) => { Err(e) => {
log::error!("{:?}", e); log::error!("{:?}", e);
// https://stackoverflow.com/questions/66450942/in-rust-is-there-a-way-to-make-literal-newlines-in-r-using-windows-c // https://stackoverflow.com/questions/66450942/in-rust-is-there-a-way-to-make-literal-newlines-in-r-using-windows-c
let stringified_error = let stringified_error =
format!("{:?}", e).replace("\n", "\n\r"); format!("{:?}", e).replace("\n", "\n\r");
handle_plugin_crash( handle_plugin_crash(
plugin_id, *plugin_id,
stringified_error, stringified_error,
senders.clone(), senders.clone(),
); );
}, },
}
} }
} }
}); }
} }
} }
});
// loop once more to update the cached events for the pending plugins (probably currently
// being loaded, we'll send them these events when they load)
for (pid, _cid, event) in updates.drain(..) {
for (plugin_id, cached_events) in self.cached_events_for_pending_plugins.iter_mut() { for (plugin_id, cached_events) in self.cached_events_for_pending_plugins.iter_mut() {
if pid.is_none() || pid.as_ref() == Some(plugin_id) { if pid.is_none() || pid.as_ref() == Some(plugin_id) {
cached_events.push(EventOrPipeMessage::Event(event.clone())); cached_events.push(EventOrPipeMessage::Event(event.clone()));