Skip to content

Refactor Task execution to support asynchronous callbacks #3274

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: master
Choose a base branch
from

Conversation

HY-love-sleep
Copy link

Summary

This PR refactors the existing Task execution model to support asynchronous callbacks. The executeWith method has been modified to execute tasks asynchronously using CompletableFuture, allowing the main thread to remain non-blocking. Upon task completion, the provided callback is invoked.

Changes

  • Replaced synchronous task execution with asynchronous execution using CompletableFuture.runAsync().
  • Updated method signatures and logic to accommodate asynchronous behavior.
  • Enhanced code comments to clarify the asynchronous execution flow.

Motivation

The original implementation was synchronous, potentially blocking the main thread. By introducing asynchronous execution, we improve the responsiveness and scalability of the application, especially in scenarios involving long-running tasks.In addition, Microsoft's Event-based Asynchronous Pattern (EAP) also emphasizes the use of callbacks to handle notifications and result processing after asynchronous operations.

Testing

  • Unit tests have been updated to verify asynchronous execution and callback invocation.
  • Performance tests indicate improved responsiveness with non-blocking behavior.

Please review the changes and provide feedback.

Copy link

github-actions bot commented May 3, 2025

PR Summary

This PR refactors the task execution model to support asynchronous callbacks using CompletableFuture. The executeWith method now executes tasks asynchronously, and the executeAsyncWith method is added for asynchronous callback support. Unit tests are updated to verify asynchronous execution and callback invocation.

Changes

File Summary
callback/src/main/java/com/iluwatar/callback/App.java The main method is updated to demonstrate both synchronous and asynchronous task execution with callbacks. It now calls both executeWith and executeAsyncWith methods.
callback/src/main/java/com/iluwatar/callback/Callback.java The Callback interface is annotated with @FunctionalInterface to explicitly declare it as a functional interface.
callback/src/main/java/com/iluwatar/callback/Task.java The Task class is enhanced to support asynchronous execution using CompletableFuture. The executeAsyncWith method is added to execute tasks asynchronously and invoke the callback upon completion. The executeWith method remains for synchronous execution.
callback/src/test/java/com/iluwatar/callback/CallbackTest.java Added tests for both synchronous and asynchronous callback execution. The tests use AtomicInteger to verify that callbacks are invoked the correct number of times and CompletableFuture to handle asynchronous operations. The tests also include timeout mechanisms to prevent indefinite waiting.

autogenerated by presubmit.ai

Copy link

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

Review Summary

Commits Considered (1)
  • 5d157d6: refactor: Refactor Task execution to support asynchronous callbacks
Files Processed (2)
  • callback/src/main/java/com/iluwatar/callback/App.java (1 hunk)
  • callback/src/main/java/com/iluwatar/callback/Task.java (1 hunk)
Actionable Comments (0)
Skipped Comments (1)
  • callback/src/main/java/com/iluwatar/callback/App.java [40-43]

    enhancement: "Unnecessary sleep in main method."

Copy link

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚨 Pull request needs attention.

Review Summary

Commits Considered (1)
Files Processed (1)
  • callback/src/test/java/com/iluwatar/callback/CallbackTest.java (2 hunks)
Actionable Comments (1)
  • callback/src/test/java/com/iluwatar/callback/CallbackTest.java [57-57]

    possible bug: "Test flakiness due to hardcoded timeout."

Skipped Comments (0)


task.executeWith(callback);

latch.await(5, TimeUnit.SECONDS);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test uses await(5, TimeUnit.SECONDS) which might lead to flaky tests if the task takes longer than 5 seconds to complete. Consider using a more robust mechanism for waiting, such as a timeout with a more appropriate duration or a different synchronization primitive.

Copy link

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚨 Pull request needs attention.

Review Summary

Commits Considered (1)
Files Processed (2)
  • callback/src/main/java/com/iluwatar/callback/Task.java (1 hunk)
  • callback/src/test/java/com/iluwatar/callback/CallbackTest.java (2 hunks)
Actionable Comments (1)
  • callback/src/test/java/com/iluwatar/callback/CallbackTest.java [58-70]

    possible bug: "Improve test robustness by using a more reliable waiting mechanism."

Skipped Comments (0)

Comment on lines 58 to 70
latch.await(5, TimeUnit.SECONDS);

assertEquals(Integer.valueOf(1), callingCount, "Callback called once");

callingCount = 0;
latch = new CountDownLatch(1);

task.executeWith(callback);

assertEquals(Integer.valueOf(2), callingCount, "Callback called twice");
latch.await(5, TimeUnit.SECONDS);

assertEquals(Integer.valueOf(1), callingCount, "Callback called once again");
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test uses await(5, TimeUnit.SECONDS), which might lead to flaky tests if the task takes longer than 5 seconds. Consider using a more robust waiting mechanism, such as a timeout with a more appropriate duration or a different synchronization primitive.

Comment on lines 34 to 40
CompletableFuture.runAsync(
() -> {
execute();
if (callback != null) {
callback.call();
}
});
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In general, looks good! However, I'd like to keep the synchronous callbacks (previous functionality) as well.

Could we demonstrate both sychronous and asynchronous callback in the example? The guidance would be something like

  • If your operation is short and straightforward, keep it synchronous.
  • If the operation can block or is resource-intensive, prefer asynchronous callbacks to maintain application responsiveness.

Copy link

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

Review Summary

Commits Considered (2)
  • a86c211: feat: display synchronous and asynchronous callbacks
  • 5f8069b: Merge remote-tracking branch 'upstream/master'
Files Processed (4)
  • callback/src/main/java/com/iluwatar/callback/App.java (1 hunk)
  • callback/src/main/java/com/iluwatar/callback/Callback.java (1 hunk)
  • callback/src/main/java/com/iluwatar/callback/Task.java (1 hunk)
  • callback/src/test/java/com/iluwatar/callback/CallbackTest.java (2 hunks)
Actionable Comments (0)
Skipped Comments (1)
  • callback/src/test/java/com/iluwatar/callback/CallbackTest.java [61-84]

    possible issue: "Timeout in asynchronous test might mask issues."

Copy link

@HY-love-sleep
Copy link
Author

Hi @iluwatar , thanks for your feedback!

I’ve just pushed updates to:

  • Keep both synchronous (executeWith) and asynchronous (executeAsyncWith) callbacks.

  • Replace Thread.sleep with CompletableFuture.join()/orTimeout() for async examples.

  • Refactor tests to use AtomicInteger and CompletableFuture for stable, non-blocking waits.

Please let me know if there’s anything else you’d like me to adjust!

Thanks again for reviewing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants