Skip to content

ADFA-4128 (9/11): quickbuild:daemon — the incremental compile service - #1721

Open
fryanpan wants to merge 2 commits into
feature/ADFA-4128-qb-08-core-orchestrationfrom
feature/ADFA-4128-qb-09-daemon
Open

ADFA-4128 (9/11): quickbuild:daemon — the incremental compile service#1721
fryanpan wants to merge 2 commits into
feature/ADFA-4128-qb-08-core-orchestrationfrom
feature/ADFA-4128-qb-09-daemon

Conversation

@fryanpan

@fryanpan fryanpan commented Aug 22, 2026

Copy link
Copy Markdown
Contributor

Part 9/11 of the stacked split of #1669 (requested by Akash). Base: feature/ADFA-4128-qb-08-core-orchestration. Stack overview + review mechanics: PR 1 (#1713). Terms are defined in quickbuild/README.md (lands in PR 1).

This is where the speed comes from: keeping a compiler warm between edits, so a save costs seconds instead of a full cold build.

flowchart LR
    core[":quickbuild:core (PRs 5-8)"] -- "line-delimited JSON on stdin/stdout<br/>(:quickbuild:protocol, PR 3)" --> svc
    subgraph d["<b>This PR: :quickbuild:daemon — separate JVM child process</b>"]
        svc["DaemonService<br/>exception backstop on every op<br/><i>DaemonService.kt</i>"] --> kt["IncrementalCompiler<br/>Kotlin Build Tools API, warm caches<br/><i>IncrementalCompiler.kt</i>"]
        svc --> jv["JavaCompileStep<br/>ABI fingerprint: does a .java edit<br/>force a Kotlin recompile?<br/><i>JavaCompileStep.kt</i>"]
        svc --> dx["FinalStripper + DexTool (d8)<br/><i>FinalStripper.kt</i>"]
        svc --> lk["aapt2 relink<br/>kill-on-timeout<br/><i>Aapt2Link.kt</i>"]
    end
    sdk["device SDK toolchain<br/>aapt2, d8.jar, android.jar"] -.-> d
    classDef thisPrBox fill:#dbeafe,stroke:#93c5fd,color:#1e3a5f
    classDef inPr fill:#ffffff,stroke:#64748b,color:#000
    class d thisPrBox
    class svc,kt,jv,dx,lk inPr
Loading

What to review

  • DaemonService.kt — exception backstop; a throwing handler never kills the daemon. Line-by-line.
  • IncrementalCompiler.kt, JavaCompileStep.kt — warm caches; ABI fingerprint decides Kotlin recompiles.
  • FinalStripper.kt — strips final so generated proxies can subclass user classes.
  • Aapt2Link.kt — relink killed on timeout so a hung linker cannot wedge.

How this PR Was Tested

  • 25 test files, including the OfflineGuard network check.
  • Toolchain-guarded tests would skip green without an SDK; analyze.yml forces failure.
  • [verified 2026-08-21] At this cut: :quickbuild:daemon:test green with PRs 1–9 applied — 25 test files (24 suites; TestSdk is the toolchain guard, not a suite), 193 tests, 0 failures, 0 errors. 0 skipped, so the SDK-guarded aapt2/d8/Compose tests genuinely ran rather than skipping green. Coverage 97.4% line / 87.9% branch.
  • End-to-end evidence: PR 11. No JVM test runs the real daemon jar.

Coverage (JaCoCo at the stack tip, single run):

Package Line Branch Note
…quickbuild.daemon 100.0% 80.9% socket lifecycle branches
…quickbuild.daemon.compile 96.1% 88.3%
…quickbuild.daemon.dex 99.0% 57.1% d8-invocation variants need the real tool
…quickbuild.daemon.protocol 95.2% 97.0%
…quickbuild.daemon.res 98.2% 95.7%
NON-UI TOTAL 97.4% 87.9% 895 lines, 431 branches

11 source files in the diff, all 11 measured.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Kj9YeCDHGp9DU8LPtfWJ7W

@fryanpan
fryanpan force-pushed the feature/ADFA-4128-qb-09-daemon branch from 81fc5e9 to 5df8930 Compare August 22, 2026 06:41
fryanpan and others added 2 commits August 21, 2026 23:58
…nc caches warm: incremental Kotlin/Java, d8, aapt2

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Kj9YeCDHGp9DU8LPtfWJ7W
… d8 + stable-ids surfacing

Review findings (PR #1721, all four Important items):

1. Stale shrunk-snapshot on re-configure -> configure fingerprints the classpath
   jars (path+size+CRC) and wipes shrunk-classpath-snapshot.bin plus ic/ when the
   bytes changed, keeping them when identical. Covered by IncrementalCompilerTest
   "re-configuring over an in-place rewritten classpath jar discards the stale
   shrunk snapshot" and its byte-identical keep-warm companion.

2. "Deployed" baseline that no deploy ever acks -> deployedOutputs renamed to
   lastGoodOutputs with honest KDoc, and a compile declaring EVERY source changed
   now rebaselines: the output diff runs against nothing and reports the whole
   tree, giving clients a wire-compatible recovery after a failed dex/deploy.
   Covered by IncrementalCompilerTest "declaring every source changed rebaselines
   - the whole output tree is reported changed". ROUTED(qb-08 core-orchestration
   / qb-11 app): the orchestrator must still force a full-changed compile
   (ChangedFiles.Unknown) after a failed dex/deploy; today it only re-queues the
   batch. No protocol-module change.

3. d8 diagnostics not captured -> a DiagnosticsHandler proxy is installed via
   D8Command.builder(handler); collected error diagnostics are appended (bounded)
   to the Failed message instead of the bare "Compilation failed to complete".
   Covered by DexToolEdgeTest "a d8 failure surfaces d8's own error diagnostics,
   not only the generic message" (runtime-compiled fake r8, runs untethered).

4. Silent stable-ids degrade -> relink fails a named-but-missing stableIds file
   before aapt2 runs; only an explicit null links unpinned. Covered by
   Aapt2LinkEdgeTest "a named but missing stable-ids file fails the relink
   instead of silently linking unpinned".

Tests are written to fail without their fix but were NOT executed here (no-build
constraint on this fix pass); verify with :quickbuild:daemon:test.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Kj9YeCDHGp9DU8LPtfWJ7W
@fryanpan
fryanpan force-pushed the feature/ADFA-4128-qb-09-daemon branch from 5df8930 to 06f55a2 Compare August 22, 2026 07:05
@fryanpan
fryanpan marked this pull request as ready for review August 23, 2026 02:31

@claude claude 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.

Claude Code Review

This repository is configured for manual code reviews. Comment @claude review for a one-time review, or @claude review always to subscribe this PR to a review on every future push.

Tip: disable this comment in your organization's Code Review settings.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant