Skip to content

feat(java): report executor progress, logs and toggles over the side-channel - #602

Merged
kartikeya-27 merged 6 commits into
ByteVeda:masterfrom
stromanni:feat/589-side-channel-java
Aug 2, 2026
Merged

feat(java): report executor progress, logs and toggles over the side-channel#602
kartikeya-27 merged 6 commits into
ByteVeda:masterfrom
stromanni:feat/589-side-channel-java

Conversation

@stromanni

@stromanni stromanni commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

Part 4 of #589 and the last SDK, on top of #599 (core), #600 (Python) and #601 (Node). A task running on an attached Java executor gets its progress, its task logs, its published partials and its dashboard middleware toggles back, without the executor holding a database connection.

What changes

JobContext — the API a handler actually uses

New ambient context, resolved per thread through the existing ScopeContext:

@TaskHandler("resize")
public String resize(Args args) {
    JobContext job = JobContext.current();
    job.setProgress(50);
    job.log("halfway");
    job.publish(Map.of("stage", "halfway"));
    return "done";
}

Identical under a Worker and an attached Executor, which is the point: only the route differs. A worker writes straight to its own storage; an executor reports to the scheduler, which applies the write. A task cannot tell, and should not have to. Every method is best-effort — losing a progress update is a degradation, failing the job over one would not be, so nothing here throws.

The dispatch carries more

WorkerBridge.onJob grows metadataJson and disabledMiddlewareJson. Middleware reads job metadata, and an executor cannot fetch the row; the toggle list is resolved by the scheduler for the same reason. MiddlewareDisables decodes the list, and WorkerDispatchBridge applies it per dispatch rather than per task name.

The executor reports back

NativeExecutor gains reportProgress and writeTaskLog natives, backed by the session's ExecutorSideChannel. JniExecutorControl routes a job's writes there, so JobContext's sink is the side channel under an executor and storage under a worker.

One thing worth calling out

jni-config.json was stale. onJob's JNI upcall went from four parameters to six, and the shipped reachability metadata still registered the four-parameter form. The JVM build does not notice — ./gradlew build passes either way — but under native-image the six-argument onJob would not have been registered for JNI, and the smoke binary would have failed at its first dispatch. Fixed in 71b8c1f; the built jar was checked to ship the corrected entry.

I could not run :graalvm-smoke:nativeCompile locally — no GraalVM on this machine — so that CI leg is the first real exercise of it. The new native methods on NativeExecutor are downcalls and need no metadata, consistent with the existing ones, none of which appear in the config either.

Tests

  • sendsProgressAndLogsToASchedulerThatAdvertisedTheSideChannel
  • sendsNothingToASchedulerThatAdvertisedNoSideChannel
  • skipsAMiddlewareTheDispatchSaysIsDisabled
  • middlewareReadsMetadataOffTheDispatch

Verification

cargo test --workspace, cargo clippy --all-targets --all-features -- -D warnings and cargo fmt --check are clean. ./gradlew build -x cargoBuild is green — Spotless, Checkstyle and the full suite at 515 tests, 0 failures, up from 487 on master.

Refs #589.

Summary by CodeRabbit

  • New Features

    • Added task progress reporting, structured task logs, and partial-result publishing through a new job execution context.
    • Added support for optional job metadata and per-job middleware disabling.
    • Added middleware filtering based on supplied configuration.
  • Bug Fixes

    • Improved handling of missing, empty, malformed, or invalid metadata and middleware settings.
    • Added support for optional task-log details without errors.

@coderabbitai

coderabbitai Bot commented Aug 2, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@stromanni, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 31 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 5277a3bf-0d16-4bf5-83a7-d992f1f8d3ba

📥 Commits

Reviewing files that changed from the base of the PR and between 71b8c1f and f214d47.

📒 Files selected for processing (12)
  • crates/taskito-java/src/dispatcher.rs
  • crates/taskito-java/src/executor.rs
  • sdks/java/src/main/java/org/byteveda/taskito/JobContext.java
  • sdks/java/src/main/java/org/byteveda/taskito/internal/JniExecutorControl.java
  • sdks/java/src/main/java/org/byteveda/taskito/internal/MiddlewareDisables.java
  • sdks/java/src/main/java/org/byteveda/taskito/internal/NativeExecutor.java
  • sdks/java/src/main/java/org/byteveda/taskito/spi/WorkerBridge.java
  • sdks/java/src/main/java/org/byteveda/taskito/spi/WorkerControl.java
  • sdks/java/src/main/java/org/byteveda/taskito/worker/WorkerDispatchBridge.java
  • sdks/java/src/main/resources/META-INF/native-image/org.byteveda/taskito/jni-config.json
  • sdks/java/src/test/java/org/byteveda/taskito/worker/ExecutorAttachTest.java
  • sdks/java/test-support/src/main/java/org/byteveda/taskito/test/InMemoryQueueBackend.java
📝 Walkthrough

Walkthrough

The PR adds Java JobContext APIs for progress, logs, and partial results. It propagates job metadata and disabled middleware through worker dispatch and JNI. Attached executors use an executor side channel for progress and task-log delivery.

Changes

Java executor side-channel integration

Layer / File(s) Summary
Java task context and control contracts
sdks/java/src/main/java/org/byteveda/taskito/...
Adds JobContext, progress and task-log control APIs, partial-result publishing, middleware filtering, and nullable JNI contracts.
Worker dispatch and context routing
sdks/java/src/main/java/org/byteveda/taskito/worker/..., sdks/java/src/main/resources/..., sdks/java/test-support/...
Dispatch resolves metadata and disabled middleware, binds JobContext, routes events through the backend or WorkerControl, and updates the JNI signature.
Rust dispatcher and JNI transport
crates/taskito-java/src/...
Propagates nullable dispatch data, installs the executor side channel, and forwards progress and task logs through JNI.
Framed executor integration validation
sdks/java/src/test/java/...
Extends the fake scheduler and adds end-to-end coverage for capability negotiation, side-channel events, metadata, and middleware suppression.

Estimated code review effort: 4 (Complex) | ~60 minutes

Possibly related issues

  • ByteVeda/taskito issue 594 — Directly covers Java attached-executor side-channel progress, logging, metadata propagation, and middleware disabling.

Possibly related PRs

Suggested labels: java, tests

Suggested reviewers: pratyush618

Sequence Diagram(s)

sequenceDiagram
  participant TaskHandler
  participant JobContext
  participant NativeExecutor
  participant JavaDispatcher
  participant Scheduler
  TaskHandler->>JobContext: report progress or write task log
  JobContext->>NativeExecutor: invoke native operation
  NativeExecutor->>JavaDispatcher: forward JNI request
  JavaDispatcher->>Scheduler: send side-channel event
  Scheduler-->>JavaDispatcher: acknowledge executor communication
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 31.82% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the Java side-channel changes for executor progress, logs, and middleware toggles.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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.

@kartikeya-27

Copy link
Copy Markdown
Contributor

@CodeRabbit full review

@coderabbitai

coderabbitai Bot commented Aug 2, 2026

Copy link
Copy Markdown
✅ Action performed

Full review finished.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
sdks/java/src/main/java/org/byteveda/taskito/JobContext.java (1)

100-108: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add a TaskLogLevel overload to JobContext.log.

log(String level, ...) exposes a caller-chosen closed-set level as a raw string. The SDK already uses TaskLogLevel for writeTaskLog, so add a matching log(TaskLogLevel level, ...) overload in JobContext and keep the existing string overload for compatibility.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@sdks/java/src/main/java/org/byteveda/taskito/JobContext.java` around lines
100 - 108, Add a JobContext.log overload accepting TaskLogLevel alongside the
existing string-based overload, and delegate it to sink.writeTaskLog using the
enum level. Preserve the current log(String, String, `@Nullable` String) method
unchanged for compatibility, including the convenience log(String) behavior.

Source: Learnings

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@sdks/java/src/main/java/org/byteveda/taskito/JobContext.java`:
- Around line 100-108: Add a JobContext.log overload accepting TaskLogLevel
alongside the existing string-based overload, and delegate it to
sink.writeTaskLog using the enum level. Preserve the current log(String, String,
`@Nullable` String) method unchanged for compatibility, including the convenience
log(String) behavior.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 70d03d02-8c42-408e-afe5-45d35742fcea

📥 Commits

Reviewing files that changed from the base of the PR and between 99847e2 and 71b8c1f.

📒 Files selected for processing (12)
  • crates/taskito-java/src/dispatcher.rs
  • crates/taskito-java/src/executor.rs
  • sdks/java/src/main/java/org/byteveda/taskito/JobContext.java
  • sdks/java/src/main/java/org/byteveda/taskito/internal/JniExecutorControl.java
  • sdks/java/src/main/java/org/byteveda/taskito/internal/MiddlewareDisables.java
  • sdks/java/src/main/java/org/byteveda/taskito/internal/NativeExecutor.java
  • sdks/java/src/main/java/org/byteveda/taskito/spi/WorkerBridge.java
  • sdks/java/src/main/java/org/byteveda/taskito/spi/WorkerControl.java
  • sdks/java/src/main/java/org/byteveda/taskito/worker/WorkerDispatchBridge.java
  • sdks/java/src/main/resources/META-INF/native-image/org.byteveda/taskito/jni-config.json
  • sdks/java/src/test/java/org/byteveda/taskito/worker/ExecutorAttachTest.java
  • sdks/java/test-support/src/main/java/org/byteveda/taskito/test/InMemoryQueueBackend.java
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • ByteVeda/taskito (manual)

@kartikeya-27
kartikeya-27 force-pushed the feat/589-side-channel-java branch from 71b8c1f to 875375b Compare August 2, 2026 01:18
@stromanni

Copy link
Copy Markdown
Contributor Author

Applied in f214d47, with one deviation from the suggestion.

JobContext.log now takes TaskLogLevel:

public void log(String message)                                        // info convenience, unchanged
public void log(TaskLogLevel level, String message)
public void log(TaskLogLevel level, String message, @Nullable String extra)

The deviation: the suggestion was to keep the string-typed overload for compatibility. I removed it instead. JobContext is new in this PR and unreleased, so there is nothing to be compatible with — and Taskito.writeTaskLog(String jobId, String taskName, String level, ...) is already @deprecated in favour of the TaskLogLevel form. Shipping a new API in the shape the SDK just deprecated would mean deprecating it on its first release. Nothing called the three-argument string overload: the only caller anywhere, in ExecutorAttachTest and in the docs, is log("halfway"), which is unchanged.

RESULT_LEVEL now derives from TaskLogLevel.RESULT.wire() rather than restating "result", so the wire form has one source. The internal JobContext.Sink still takes the wire string, since it bridges to JNI; the conversion happens at that boundary.

./gradlew build -x cargoBuild is green — Spotless, Checkstyle, 515 tests, 0 failures.

@kartikeya-27
kartikeya-27 merged commit a91ebde into ByteVeda:master Aug 2, 2026
31 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants