java: MeshJobs cancel/status/await facades (Java parity for #1074) - #1081
Conversation
|
Warning Rate limit exceeded
You’ve run out of usage credits. Purchase more in the billing tab. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (5)
📝 WalkthroughWalkthroughThis PR adds Java parity for job lifecycle facades introduced in Python and TypeScript. Three new static methods ( ChangesJob lifecycle facades by jobId
🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly Related PRs
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
docs/concepts/jobs.md (1)
692-693: ⚡ Quick winClarify "Java parity follows" wording.
The phrase "Java parity follows" is ambiguous — it could be read as "Java parity will be added later" rather than "Java follows the same pattern". Consider rephrasing for clarity.
✏️ Suggested clarification
-resolution + cached-proxy machinery. All three runtimes ship the -surface — Python and TypeScript landed in v2.2; Java parity follows. +resolution + cached-proxy machinery. All three runtimes ship the +surface with identical semantics.🤖 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 `@docs/concepts/jobs.md` around lines 692 - 693, The phrase "Java parity follows" in the sentence containing "resolution + cached-proxy machinery. All three runtimes ship the surface — Python and TypeScript landed in v2.2; Java parity follows." is ambiguous; update that wording to explicitly state that Java implements the same surface/pattern rather than implying a future action—e.g., replace "Java parity follows" with "Java follows the same pattern" or "Java provides the same surface" so the meaning is immediately clear.
🤖 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.
Inline comments:
In `@docs/concepts/jobs.md`:
- Around line 805-807: The doc incorrectly claims Object.wait() is final; update
the text to say the Java facade is named MeshJobs.await (not wait) to avoid
readability confusion with the inherited wait overload family, and reference the
existing precedent in JobProxy.await(double); mention MeshJobs.await and
JobProxy.await by name and, if needed, point readers to the JavaDoc comments in
MeshJobs.java and JobProxy.java for the detailed rationale.
---
Nitpick comments:
In `@docs/concepts/jobs.md`:
- Around line 692-693: The phrase "Java parity follows" in the sentence
containing "resolution + cached-proxy machinery. All three runtimes ship the
surface — Python and TypeScript landed in v2.2; Java parity follows." is
ambiguous; update that wording to explicitly state that Java implements the same
surface/pattern rather than implying a future action—e.g., replace "Java parity
follows" with "Java follows the same pattern" or "Java provides the same
surface" so the meaning is immediately clear.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 91d93a86-daaf-4b37-90cd-c831f821b981
📒 Files selected for processing (5)
docs/concepts/jobs.mdsrc/core/cli/man/content/jobs_java.mdsrc/runtime/java/mcp-mesh-sdk/src/main/java/io/mcpmesh/JobProxy.javasrc/runtime/java/mcp-mesh-sdk/src/main/java/io/mcpmesh/MeshJobs.javasrc/runtime/java/mcp-mesh-sdk/src/test/java/io/mcpmesh/MeshJobsTest.java
Java parity for the Python facades shipped in #1077 and TypeScript facades in #1079. Three new static methods (with overloads) on MeshJobs mirror the existing postEvent / subscribeEvents DDDI-clean shape — callers with only a jobId no longer need to construct a JobProxy(jobId, registryUrl) and pass MCP_MESH_REGISTRY_URL explicitly: public static void cancel(String jobId, String reason) public static void cancel(String jobId) public static Map<String, Object> status(String jobId) public static Object await(String jobId, double timeoutSecs) public static Object await(String jobId) Each: resolveRegistryUrl() → getOrCreateProxy() (LRU-cached) → dispatch to the existing JobProxy instance method → substring-match translation to typed exceptions (JobNotFoundException, JobTerminalException) via a new package-private translateJobError helper. Java naming nuance: 'await' (not 'wait') because Object.wait() is final. Matches the existing JobProxy.await() instance method precedent. What was already in place (no Rust/JNR/JobProxy changes needed): - FFI: mesh_job_proxy_cancel/status/wait in jobs_ffi.rs - JNR: declarations in MeshCore.java:648-670 - JobProxy.cancel/status/await instance methods - JobNotFoundException, JobTerminalException, MeshException classes - LRU proxy cache infrastructure Bonus generalization: resolveRegistryUrl's error message prefix generalized from 'MeshJobs.postEvent:' → 'MeshJobs:'. Now accurate for all four facades. Mirrors the same generalization the Python BLOCKER fix made in #1077 and the TS bonus in #1079 — the trilogy is now consistent across all three runtimes in this respect. Tests (MeshJobsTest.java): 14 → 27 (+13 new). For each new facade: arg validation (null/empty jobId), env resolution (MCP_MESH_REGISTRY_URL missing), cache hit reuse. Plus the cross-facade shared-cache test asserting cancel/status/await reuse one cached proxy (mirrors Python W6 from #1077's review fixes). await timeout: JobProxy.await contract says timeoutSecs <= 0.0 or non-finite means 'no timeout'. The MeshJobs.await(jobId) no-arg overload delegates to await(jobId, -1.0). Docs: docs/concepts/jobs.md 'Lifecycle facades by jobId' section now has Python | TypeScript | Java tabs. src/core/cli/man/content/jobs_java.md mirrors the Python/TS variants' facade documentation. Out of scope (separate work): - Strongly-typed JobStatus record — returns Map<String, Object> matching the JobProxy.status() shape; a record with typed fields is a follow-up if usage warrants - Caller authorization on lifecycle ops — design discussion at #1076 Closes #1080 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
bfcd36a to
b37638b
Compare
## Summary **v2.3.0 — Lifecycle facades across the polyglot trilogy + unified dependency-injection contract.** v2.2 introduced the MeshJob substrate. v2.3 completes the lifecycle surface so callers that hold only a `job_id` can drive `cancel` / `status` / `wait` through DDDI-clean module-level facades — the same shape `post_event` and `subscribe_events` already had. The DI rules for `McpMeshTool` and `MeshJob` parameters are unified under a single positional contract, eliminating a silent wrong-proxy footgun when both types appeared in the same tool. ## What ships ### Lifecycle facades by `job_id` (Python #1077, TS #1079, Java #1081) | Operation | Python | TypeScript | Java | | ------------------------ | -------------------------------------------------- | ------------------------------------------------ | --------------------------------------------- | | Cancel a running job | `await mesh.jobs.cancel(job_id, reason=None)` | `await mesh.jobs.cancel(jobId, reason?)` | `MeshJobs.cancel(jobId[, reason])` | | Read latest job state | `await mesh.jobs.status(job_id)` | `await mesh.jobs.status(jobId)` | `MeshJobs.status(jobId)` | | Wait for terminal state | `await mesh.jobs.wait(job_id, timeout_secs=None)` | `await mesh.jobs.wait(jobId, timeoutSecs?)` | `MeshJobs.await(jobId[, timeoutSecs])` | Underlying `JobProxy.cancel/status/wait` was already shipped in v2.2; this adds the module-level wrappers that resolve the registry URL internally — no more `JobProxy(jobId, registryUrl)` plumbing in user code. Typed errors (`JobNotFoundError` / `JobTerminalError`) translate consistently across all three runtimes. TS adds a typed `JobStatus` interface exported from `mesh.jobs`. ### Unified positional dependency injection (#1082, Python) `McpMeshTool` and `MeshJob` parameters now share a **single positional `dep_index` namespace** in parameter declaration order. Each `dependencies[i]` strictly pairs with one parameter position; the slot's type determines what gets constructed. Previously, the two types had inconsistent injection rules (positional for `McpMeshTool`, by-name for `MeshJob`), producing wrong-proxy injection when both appeared in the same tool with the `MeshJob` capability listed first in `dependencies[]`. **Behavior change to call out**: users who deliberately wrote `MeshJob` params out-of-order with their `dependencies[]` array (relying on the previous by-name resolution) now need to put params in the same order as deps. The natural same-order case continues to work unchanged. TypeScript and Java SDK DI paths still follow the orthogonal injection contract — their port to the unified positional rule is tracked separately. ### `health_check_ttl` refresh on the user loop (#1073) `@mesh.agent(health_check=fn, health_check_ttl=N)` now actually refreshes every N seconds. Previously, the result was stored exactly once at startup and served forever — a failed check during startup cached as unhealthy and permanently failed k8s readiness probes. The refresh loop runs on the user loop (same loop as `lifespan` and tools) so health checks touching loop-bound resources work without cross-loop errors. A lifespan-ready signal gates the refresh start so iterations don't fire during user `__aenter__`. ### FastMCP lifespan documentation correction (#1073) The v2.2.4 "Loop topology" docs incorrectly showed a FastAPI-style `app.state.pool` example — FastMCP's lifespan receives a server instance, not a FastAPI app. Three doc surfaces rewritten to the canonical module-level globals pattern. ## Mechanical bundle - `scripts/bump_version.py 2.2.4 → 2.3.0` (419 files updated across 36 categories) - `helm dependency update helm/mcp-mesh-core` - `cargo generate-lockfile` (src/runtime/core) - `RELEASE_NOTES.md` — new v2.3.0 entry with full narrative ## Post-merge Per the established v2.2.3 / v2.2.4 publish pattern: 1. `/dev` reset to pull the merged main 2. `gh release create v2.3.0 --target main --title "v2.3.0" --notes-file <v2.3.0 section> --latest` (one-shot) 3. Wait for all 4 publish jobs to land (npm × 7 packages, PyPI, Maven Central, crates.io) 4. Verify `npm view @mcpmesh/core version` returns `2.3.0` ## Test plan - [x] `mvn install` BUILD SUCCESS for Java - [x] Python unit suite: 1010/1010 - [x] uc02_agent_lifecycle: 23/23 - [x] uc21_meshjob (Python): 21/21 - [x] uc22_meshjob_ts: 24/24 - [x] uc23_meshjob_java: 27/27 - [x] `mkdocs build` clean - [ ] Release workflow fires cleanly across all 4 registries Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Summary
Java parity for the
mesh.jobs.cancel/status/waitfacades shipped in Python (#1077) and TypeScript (#1079). Three new static methods (with overloads) onMeshJobsmirror the existingpostEvent/subscribeEventsDDDI-clean pattern — callers with only ajobIdno longer need to constructnew JobProxy(jobId, registryUrl)and passMCP_MESH_REGISTRY_URLexplicitly.Each:
resolveRegistryUrl()→getOrCreateProxy()(LRU-cached) → dispatch to the existingJobProxyinstance method → substring-match translation to typed exceptions via a new package-privatetranslateJobErrorhelper.Java naming nuance:
await(notwait) to avoid readability confusion with the inheritedObject.wait()/wait(long)/wait(long, int)overload family, and to match the existingJobProxy.await(double)precedent.What was already in place (no work needed)
mesh_job_proxy_cancel/status/waitinjobs_ffi.rsMeshCore.java:648-670JobProxy.cancel/status/awaitinstance methodsJobNotFoundException,JobTerminalException,MeshExceptionclassesBonus generalization
resolveRegistryUrl's error message prefix generalized from"MeshJobs.postEvent:"→"MeshJobs:". Now accurate for all four facades. Mirrors the same generalization the Python BLOCKER fix made in #1077 and the TS bonus in #1079 — the trilogy is now consistent across all three runtimes in this respect.Trilogy complete
Out of scope
JobStatusrecord — returnsMap<String, Object>matching the existingJobProxy.status()shape. A record with typed fields is a follow-up if usage warrants.Review Notes
Independent review: 0 BLOCKER, 1 WARNING (addressed), 4 INFOs (3 addressed, 1 skipped as docs cosmetic).
throw translateJobError(exc);. The previous indirection (if (translated != exc) throw translated; throw exc;) was dead-equivalent on Java becausetranslateJobErrorchains the original exception ascausevia the typed constructor. Net -12 lines on the facade region.awaitnaming Javadoc accuracy: the previous text claimed "overloading would be a compile error" (wrong —wait(double)is overloading, legal). Updated wording across 3 surfaces (MeshJobs.java,JobProxy.java,jobs_java.md) to cite the real reason: readability confusion with the inheritedObject.wait()overload family + the existingJobProxy.await(double)precedent.JobTerminalExceptiontranslation test now asserts message preservation matching theJobNotFoundExceptiontest.@DisabledIfEnvironmentVariable: the three*_failsCleanlyWhenRegistryUrlUnsettests now use JUnit 5's declarative annotation instead of silentreturn— skips are visible in test reports, no green-test illusion in CI shells that exportMCP_MESH_REGISTRY_URL.I4 (4-column docs table) skipped as cosmetic.
Closes #1080
Test plan
mvn install -pl mcp-mesh-core,mcp-mesh-sdk -am: BUILD SUCCESSmvn test -pl mcp-mesh-sdk: 98 tests pass (MeshJobsTest27/27)@DisabledIfEnvironmentVariableverified visible in report when env settsuite uc23_meshjob_java --parallel 4: 27/27mkdocs buildcleanJobProxy.cancel/status/awaitinstance methods / Pythonjobs.md/ TSjobs_typescript.mdSummary by CodeRabbit
New Features
Documentation