Skip to content

Conversation

@DropSnorz
Copy link
Owner

No description provided.

@coderabbitai
Copy link

coderabbitai bot commented Nov 18, 2025

Walkthrough

TaskRunner moved from ListenableFuture to CompletableFuture with an executor-backed submission path and WorkerStateEvent handlers; Task/TaskResult APIs were simplified (success() → completed(), TaskResult now always reports completed), and multiple tasks adjusted to return completed().

Changes

Cohort / File(s) Summary
Async scheduling refactor
owlplug-client/src/main/java/com/owlplug/core/components/TaskRunner.java
Replaced ListenableFuture-based scheduling with CompletableFuture; added private submitCompletable(...) wiring WorkerStateEvent (SUCCEEDED/FAILED/CANCELLED) to a CompletableFuture; scheduleNext now uses thenAccept/exceptionally; executor, taskQueue, taskHistory made final and initialized; import updates and log text tweak ("Task submitted to queue head - ...").
Task API rename & result simplification
owlplug-client/src/main/java/com/owlplug/core/tasks/AbstractTask.java, owlplug-client/src/main/java/com/owlplug/core/tasks/TaskResult.java
Renamed AbstractTask.success() → completed(); TaskResult no longer stores a mutable success flag (removed field and isSuccess/setSuccess), added isCompleted() that returns true unconditionally.
Tasks updated to use completed()
owlplug-client/src/main/java/com/owlplug/explore/tasks/BundleInstallTask.java, owlplug-client/src/main/java/com/owlplug/explore/tasks/SourceSyncTask.java, owlplug-client/src/main/java/com/owlplug/plugin/tasks/DirectoryRemoveTask.java, owlplug-client/src/main/java/com/owlplug/plugin/tasks/FileSyncTask.java, owlplug-client/src/main/java/com/owlplug/plugin/tasks/PluginRemoveTask.java, owlplug-client/src/main/java/com/owlplug/plugin/tasks/PluginScanTask.java, owlplug-client/src/main/java/com/owlplug/plugin/tasks/SymlinkRemoveTask.java, owlplug-client/src/main/java/com/owlplug/project/tasks/PluginLookupTask.java, owlplug-client/src/main/java/com/owlplug/project/tasks/ProjectSyncTask.java
Replaced returns of success()/null with completed() (no other logic changes). One unused import removed in FileSyncTask.

Sequence Diagram(s)

sequenceDiagram
    participant Scheduler as TaskRunner.scheduleNext()
    participant Submit as submitCompletable()
    participant Exec as Executor
    participant Worker as Task Worker
    participant Event as WorkerStateEvent
    participant Future as CompletableFuture
    participant UI as UI (TaskBarController)

    rect rgb(240,248,255)
    Note over Scheduler,Submit: New submission flow (high-level)
    Scheduler->>Submit: submit task
    Submit->>Future: create CompletableFuture
    Submit->>Exec: execute task
    Exec->>Worker: run
    par Success
        Worker->>Event: SUCCEEDED
        Event->>Future: complete()
        Future->>UI: thenAccept -> UI update (Platform.runLater)
    and Failure
        Worker->>Event: FAILED
        Event->>Future: completeExceptionally()
        Future->>UI: exceptionally -> log & UI report
    and Cancel
        Worker->>Event: CANCELLED
        Event->>Future: cancel()
    end
    Future->>Scheduler: continuation (remove current, schedule next)
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Areas needing extra attention:
    • TaskRunner.submitCompletable: verify WorkerStateEvent handlers accurately map to CompletableFuture completion/cancellation and no event races.
    • scheduleNext continuation logic: ensure tasks are removed and the next task is scheduled in all success/failure/cancel paths.
    • TaskResult API change: ensure callers do not rely on previous isSuccess/setSuccess semantics; verify downstream behavior assumes unconditional completion.
    • AbstractTask rename: search for any remaining success() call sites or overrides.

Possibly related PRs

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 15.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Description check ❓ Inconclusive No pull request description was provided by the author, making it impossible to assess whether the description relates to the changeset. Add a pull request description explaining the motivation, scope, and impact of the CompletableFuture refactoring and method name changes.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main refactoring objective—migrating from ListenableFuture to CompletableFuture in the task runner—which aligns with the primary changes across the codebase.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch chore/completable-future

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@DropSnorz
Copy link
Owner Author

@coderabbitai review

@coderabbitai
Copy link

coderabbitai bot commented Nov 18, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@DropSnorz DropSnorz self-assigned this Nov 18, 2025
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5e05af7 and 8a8459e.

📒 Files selected for processing (1)
  • owlplug-client/src/main/java/com/owlplug/core/components/TaskRunner.java (4 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Codacy Static Code Analysis
🔇 Additional comments (3)
owlplug-client/src/main/java/com/owlplug/core/components/TaskRunner.java (3)

27-28: LGTM! Clean migration to CompletableFuture with improved field immutability.

The import changes correctly reflect the migration from deprecated ListenableFuture to CompletableFuture. Making the executor, taskQueue, and taskHistory fields final is good practice and ensures they cannot be reassigned after construction.

Also applies to: 32-32, 53-55, 57-57


60-62: LGTM! Modern initialization with diamond operators.

The constructor initialization is clean and uses appropriate diamond operators.


84-84: LGTM! More descriptive logging.

The updated log message "Task submitted to queue head" better reflects the behavior of submitTaskOnQueueHead.

@DropSnorz DropSnorz force-pushed the chore/completable-future branch from 8a8459e to 482d8d7 Compare November 18, 2025 18:30
@DropSnorz
Copy link
Owner Author

@coderabbitai review

@coderabbitai
Copy link

coderabbitai bot commented Nov 18, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
owlplug-client/src/main/java/com/owlplug/core/components/TaskRunner.java (1)

144-155: Consider removing event handlers after firing to reduce memory footprint.

While the developer noted that the CompletableFuture will be garbage collected, the JavaFX Task objects are retained in taskHistory (up to 10 tasks) with their event handlers still attached. Each handler holds a reference to its corresponding CompletableFuture, creating a retention chain.

For cleaner resource management, consider storing handler references and removing them after the CompletableFuture completes:

 private CompletableFuture<TaskResult> submitCompletable(AbstractTask task, Executor exec) {
   CompletableFuture<TaskResult> cf = new CompletableFuture<>();
-  task.addEventHandler(WorkerStateEvent.WORKER_STATE_SUCCEEDED,
-      e -> cf.complete(task.getValue()));
-  task.addEventHandler(WorkerStateEvent.WORKER_STATE_FAILED,
-      e -> cf.completeExceptionally(task.getException()));
-  task.addEventHandler(WorkerStateEvent.WORKER_STATE_CANCELLED,
-      e -> cf.cancel(true));
+  
+  EventHandler<WorkerStateEvent> successHandler = e -> {
+    cf.complete(task.getValue());
+    task.removeEventHandler(WorkerStateEvent.WORKER_STATE_SUCCEEDED, successHandler);
+    task.removeEventHandler(WorkerStateEvent.WORKER_STATE_FAILED, failHandler);
+    task.removeEventHandler(WorkerStateEvent.WORKER_STATE_CANCELLED, cancelHandler);
+  };
+  EventHandler<WorkerStateEvent> failHandler = e -> {
+    cf.completeExceptionally(task.getException());
+    task.removeEventHandler(WorkerStateEvent.WORKER_STATE_SUCCEEDED, successHandler);
+    task.removeEventHandler(WorkerStateEvent.WORKER_STATE_FAILED, failHandler);
+    task.removeEventHandler(WorkerStateEvent.WORKER_STATE_CANCELLED, cancelHandler);
+  };
+  EventHandler<WorkerStateEvent> cancelHandler = e -> {
+    cf.cancel(true);
+    task.removeEventHandler(WorkerStateEvent.WORKER_STATE_SUCCEEDED, successHandler);
+    task.removeEventHandler(WorkerStateEvent.WORKER_STATE_FAILED, failHandler);
+    task.removeEventHandler(WorkerStateEvent.WORKER_STATE_CANCELLED, cancelHandler);
+  };
+  
+  task.addEventHandler(WorkerStateEvent.WORKER_STATE_SUCCEEDED, successHandler);
+  task.addEventHandler(WorkerStateEvent.WORKER_STATE_FAILED, failHandler);
+  task.addEventHandler(WorkerStateEvent.WORKER_STATE_CANCELLED, cancelHandler);

   exec.execute(task);
   return cf;
 }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8a8459e and 482d8d7.

📒 Files selected for processing (12)
  • owlplug-client/src/main/java/com/owlplug/core/components/TaskRunner.java (4 hunks)
  • owlplug-client/src/main/java/com/owlplug/core/tasks/AbstractTask.java (1 hunks)
  • owlplug-client/src/main/java/com/owlplug/core/tasks/TaskResult.java (1 hunks)
  • owlplug-client/src/main/java/com/owlplug/explore/tasks/BundleInstallTask.java (1 hunks)
  • owlplug-client/src/main/java/com/owlplug/explore/tasks/SourceSyncTask.java (1 hunks)
  • owlplug-client/src/main/java/com/owlplug/plugin/tasks/DirectoryRemoveTask.java (1 hunks)
  • owlplug-client/src/main/java/com/owlplug/plugin/tasks/FileSyncTask.java (1 hunks)
  • owlplug-client/src/main/java/com/owlplug/plugin/tasks/PluginRemoveTask.java (1 hunks)
  • owlplug-client/src/main/java/com/owlplug/plugin/tasks/PluginScanTask.java (1 hunks)
  • owlplug-client/src/main/java/com/owlplug/plugin/tasks/SymlinkRemoveTask.java (1 hunks)
  • owlplug-client/src/main/java/com/owlplug/project/tasks/PluginLookupTask.java (1 hunks)
  • owlplug-client/src/main/java/com/owlplug/project/tasks/ProjectSyncTask.java (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-11-03T18:35:06.941Z
Learnt from: DropSnorz
Repo: DropSnorz/OwlPlug PR: 359
File: owlplug-client/src/main/java/com/owlplug/plugin/tasks/PluginScanTask.java:104-113
Timestamp: 2025-11-03T18:35:06.941Z
Learning: In OwlPlug's PluginScanTask (owlplug-client/src/main/java/com/owlplug/plugin/tasks/PluginScanTask.java), all plugin paths are absolute paths, never relative, as they are normalized via FileUtils.convertPath before being stored or used as directory scopes.

Applied to files:

  • owlplug-client/src/main/java/com/owlplug/project/tasks/PluginLookupTask.java
  • owlplug-client/src/main/java/com/owlplug/plugin/tasks/PluginScanTask.java
  • owlplug-client/src/main/java/com/owlplug/plugin/tasks/PluginRemoveTask.java
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Codacy Static Code Analysis
🔇 Additional comments (14)
owlplug-client/src/main/java/com/owlplug/plugin/tasks/DirectoryRemoveTask.java (1)

37-51: Consistent TaskResult completion usage

Returning completed() after a successful delete keeps the previous control flow (exceptions still bubble) while aligning with the new unified completion semantics and ensuring a non‑null TaskResult on success.

owlplug-client/src/main/java/com/owlplug/plugin/tasks/FileSyncTask.java (1)

55-79: Return of completed() matches existing error model

On normal completion you now return completed(), while failures still throw TaskException. This keeps semantics intact and matches the updated TaskResult/AbstractTask API.

owlplug-client/src/main/java/com/owlplug/explore/tasks/SourceSyncTask.java (1)

130-140: Completed result correctly reflects existing “best‑effort” semantics

You now return completed() after finishing sync and messaging, while network/parse issues still surface only as logged warnings. That preserves the previous behavior and fits the new TaskResult contract.

owlplug-client/src/main/java/com/owlplug/plugin/tasks/SymlinkRemoveTask.java (1)

36-54: Unified completion signaling for symlink removal

The new return completed(); on the success path cleanly harmonizes this task with the rest of the framework while leaving failure behavior (exception on delete error) unchanged.

owlplug-client/src/main/java/com/owlplug/project/tasks/PluginLookupTask.java (1)

41-65: TaskResult completion aligned with lookup flow

Returning completed() after the lookup loop and final progress update is consistent with the revised TaskResult API and keeps the task’s observable behavior the same.

owlplug-client/src/main/java/com/owlplug/plugin/tasks/PluginScanTask.java (1)

85-95: Clear mapping between success and exceptional completion

Switching from the old success signaling to return completed(); in the try block, while still wrapping failures in TaskException in the catch, cleanly supports the new CompletableFuture/TaskResult model without changing scan behavior.

owlplug-client/src/main/java/com/owlplug/plugin/tasks/PluginRemoveTask.java (1)

47-76: Non‑null completion result on successful plugin removal

The new completed() return on the success branch ensures callers always receive a TaskResult for successful removals, while failures still throw TaskException. This matches the project‑wide completion refactor.

owlplug-client/src/main/java/com/owlplug/project/tasks/ProjectSyncTask.java (1)

49-95: Project sync now returns a concrete completed TaskResult

After synchronizing projects and updating progress/messages, returning completed() makes this task consistent with the new TaskResult/TaskRunner contract while keeping the functional behavior identical.

owlplug-client/src/main/java/com/owlplug/explore/tasks/BundleInstallTask.java (1)

127-127: LGTM! Method rename aligns with the AbstractTask refactoring.

The change from success() to completed() is consistent with the project-wide migration to CompletableFuture-based task completion signaling.

owlplug-client/src/main/java/com/owlplug/core/tasks/AbstractTask.java (1)

89-91: LGTM! Method rename improves semantic clarity.

Renaming success() to completed() better aligns with CompletableFuture terminology and accurately represents task completion signaling across the codebase.

owlplug-client/src/main/java/com/owlplug/core/tasks/TaskResult.java (1)

23-25: LGTM! Simplified semantics align with CompletableFuture architecture.

The change to have isCompleted() always return true is correct in the new CompletableFuture-based design. When a task throws an exception, the CompletableFuture completes exceptionally and TaskResult is never examined. TaskResult instances only exist for successfully completed tasks, so the constant true return value is semantically accurate.

owlplug-client/src/main/java/com/owlplug/core/components/TaskRunner.java (3)

52-61: LGTM! Field finalization and inline initialization improve immutability.

Making the executor, task queue, and task history fields final and initializing them directly in the constructor is a good defensive coding practice that prevents accidental reassignment.


83-83: LGTM! Log message clarification improves debugging.

The updated log message "Task submitted to queue head" more clearly indicates priority submission versus regular queue submission.


103-130: LGTM! CompletableFuture flow correctly handles success and error paths with proper thread synchronization.

The refactored scheduling logic properly:

  • Uses thenAccept for successful completion
  • Uses exceptionally for error handling with appropriate null checks (lines 113-124)
  • Wraps JavaFX UI updates in Platform.runLater to ensure thread safety
  • Maintains task lifecycle (remove and schedule next) in both paths

@DropSnorz DropSnorz merged commit 5a81db5 into master Nov 19, 2025
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

2 participants