Skip to content

Conversation

@not-elm
Copy link
Owner

@not-elm not-elm commented Mar 15, 2025

Significantly improved performance.
Previously, the reactor was executed every frame, but with this change, it is now called only when each of runner has completed its processing.

Features

Added StepAllReactors and StepReactor trigger events to step the reactor manually.

Breaking Changes

When the runner’s processing is finished, the reactor now steps immediately.
For example, when running the following test, Count was 1, but from this version onward, it will be 3.

#[test]
fn count_is_3() {
   #[derive(Resource, Debug, Default, Eq, PartialEq)]
   struct Count(usize);

   let mut app = test_app();
   app.insert_resource(Count(0));

   app.add_systems(Startup, |mut commands: Commands| {
       commands.spawn(Reactor::schedule(|task| async move {
           task.will(Update, once::run(|mut count: ResMut<Count>| {
               count.0 += 1;
           })).await;
           task.will(Update, once::run(|mut count: ResMut<Count>| {
               count.0 += 1;
           })).await;
           task.will(Update, once::run(|mut count: ResMut<Count>| {
               count.0 += 1;
           })).await;
       }));
   });
   app.update();
   assert_eq!(app.world().resource::<Count>(), &Count(3));
}

From this version onward, if you invoke asynchronous processing other than an Action within the reactor’s async block as shown below, you will need to manually advance the reactor by triggering either StepAllReactors or StepReactor.

fn main() {
   App::new()
       .add_plugins((
           MinimalPlugins,
           LogPlugin::default(),
           FlurxPlugin,
       ))
       .add_systems(Startup, spawn_reactor)
       .add_systems(Update, step_reactors.run_if(switch_is_on::<TokioTaskRunning>))
       .run();
}

struct TokioTaskRunning;

fn spawn_reactor(mut commands: Commands) {
   commands.spawn(Reactor::schedule(|task| async move {
       task.will(Update, once::switch::on::<TokioTaskRunning>()).await;
       // By turning on feature flag `tokio`,
       // you can also directly write asynchronous functions depending on tokio's runtime in the reactor.
       // However, you need to manually advance the reactor.
       tokio::time::sleep(Duration::from_secs(1)).await;
       task.will(Update, once::switch::off::<TokioTaskRunning>()).await;
   }));
}

fn step_reactors(
   mut commands: Commands,
){
   commands.trigger(StepAllReactors);
}

In this PR, I optimized the execution of the Reactor.
 Previously, the reactor was executed every frame, but with this change, it is now called only when the runner has completed its processing.

 ## Breaking Change

 When the runner’s processing is finished, the reactor now advances immediately.
 For example, the following code used to yield Count(1), but now it yields Count(2).
 ```rust
 #[test]
 fn reactor_process_complete() {
     #[derive(Resource, Debug, Default, Eq, PartialEq)]
     struct Count(usize);

     let mut app = test_app();
     app.insert_resource(Count(0));

     app.add_systems(Startup, |mut commands: Commands| {
         commands.spawn(Reactor::schedule(|task| async move {
             task.will(Update, once::run(|mut count: ResMut<Count>| {
                 count.0 += 1;
             })).await;
             task.will(Update, once::run(|mut count: ResMut<Count>| {
                 count.0 += 1;
             })).await;
         }));
     });
     app.update();
     assert_eq!(app.world().resource::<Count>(), &Count(2));
 }
 ```

 From this version onward, if you invoke asynchronous processing other than an Action within the reactor’s async block as shown below, you will need to manually advance the reactor by triggering either StepAllReactors or StepReactor.
 ```rust
 Reactor::schedule(|task| async move {
     tokio::time::sleep(Duration::from_secs(1)).await;
 });
 ```
@not-elm not-elm added the improvement Improvement to existing features label Mar 15, 2025
@not-elm not-elm merged commit 64a394e into main Mar 15, 2025
4 checks passed
@not-elm not-elm deleted the improvement-reactor branch March 15, 2025 12:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

breaking-change improvement Improvement to existing features

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants