Capstone Project
The Capstone is the bridge from "I have read the Tez codebase" to "I have shipped a
non-trivial fix that an Apache Tez committer merged into master." Everything in
Levels 1–7 was preparation. This is the work.
You will pick one real, open Apache Tez JIRA, reproduce it against a current build, trace the failure through the codebase, identify the root cause, write a minimum-diff patch with deterministic tests, get it through precommit (Yetus + the GitHub Actions build), respond to review comments on the PR, and land the change. Then you write it up so the next person can learn from your investigation.
Tez contribution is JIRA-tracked and GitHub-native. The permanent record of the
bug lives in a TEZ-NNNN issue on issues.apache.org; the code review happens in a
Pull Request against github.com/apache/tez. Every
commit that lands carries the JIRA key in its subject line — run
git log --oneline -20 on your clone and you will see the shape:
TEZ-4580: Slow preemption of new containers when re-use is enabled (#374). You open
the JIRA (or claim an existing one), open the PR, cross-link them, iterate in the PR
conversation, and a committer squashes-and-merges with that subject line. Keep that
model in your head — every step below assumes it.
This chapter is the table of contents. The ten step-chapters that follow are the work itself.
Prerequisites: the gate
Do not start the Capstone until you can answer "yes" to every one of these. This is a gate, not a suggestion. The Capstone is unforgiving of partial preparation — you will spend three weeks confused instead of three weeks shipping.
- Levels 1–7 complete. You can read
DAGImpl,VertexImpl,TaskImpl,TaskAttemptImpl,AsyncDispatcher, the shuffle path (ShuffleManager,Fetcher,FetcherOrderedGrouped, the merge path), and at least oneVertexManagerPlugin(ShuffleVertexManagerorRootInputVertexManager) without a guide open. If those names are not instantly familiar, go back to the state-machine deep dive and the vertex-lifecycle deep dive. - You have built Tez from source.
mvn clean install -DskipTestssucceeds on your machine (JDK 21 — Tez moved to JDK 21+ in TEZ-4636, after the earlier JDK 17 move in TEZ-4598), andmvn test -pl tez-dagfinishes (some flakes are normal — see the flaky-test stage). - You have run
MiniTezClusterlocally.mvn test -pl tez-tests -Dtest=TestOrderedWordCountgoes green, so you know the in-JVM YARN +DAGAppMasterharness works on your box. - You have run a local-mode DAG.
mvn test -pl tez-tests -Dtest=TestLocalModepasses — the lightest end-to-end harness, and the one you will reach for most in Step 2. See the local-mode deep dive. - You have a working Apache JIRA account (register at
issues.apache.org/jira) and a GitHub account ready to fork and PR. - You have read the Tez contribution guide:
tez.apache.org/contribution_guide.htmlandcwiki.apache.org/confluence/display/TEZ/How+to+Contribute.
If any of these is "no," stop. Go back. Fix it before you spend a single evening on Step 1.
The 10-step flow
flowchart TD
A[Step 1: Issue Selection] --> B[Step 2: Reproduction]
B --> C[Step 3: Execution Path Analysis]
C --> D[Step 4: Root Cause Identification]
D --> E[Step 5: Implementation]
E --> F[Step 6: Testing]
F --> G[Step 7: Validation]
G --> H[Step 8: Patch / PR]
H --> I[Step 9: JIRA + Docs]
I --> J[Step 10: Engineering Write-Up]
C -.hypothesis wrong.-> B
D -.hypothesis wrong.-> C
F -.test fail.-> E
G -.precommit fail.-> E
H -.review round.-> E
I -.CI red.-> F
The dotted arrows are the loops you will actually run. Nobody gets root cause right on the first hypothesis. Nobody passes precommit on the first push. Nobody clears committer review in one round. Plan for two or three iterations through Steps 4–9 before the merge button turns green.
Read every step-chapter once, end-to-end, before you touch Step 1 — you need the shape of the whole journey in your head. Step 4 (root cause) makes choices that Step 6 (testing) depends on; Step 8 (patch) assumes you have artifacts from Steps 2 and 7; Step 9 assumes your tests cleared CI. Skim now, deep-read each as you arrive:
- Step 1: Issue Selection — pick a right-sized JIRA.
- Step 2: Reproduction — a deterministic failing test.
- Step 3: Execution Path Analysis — trace repro to code.
- Step 4: Root Cause Identification — the one wrong line.
- Step 5: Implementation — the minimum diff.
- Step 6: Testing — regression protection that convinces.
- Step 7: Validation — precommit, checkstyle, spotbugs, RAT.
- Step 8: Patch / PR — the PR against
apache/tez:master. - Step 9: JIRA + Docs — the permanent record.
- Step 10: Engineering Write-Up — teach the next person.
What "done" means
The Capstone is done when either:
- A committer has merged your PR — the ideal outcome. Your fix appears in
git log apache/masterwith theTEZ-NNNNsubject line and your authorship, and the JIRA flips to "Resolved / Fixed in X.Y.Z." Or, - You have a credibly-submitted patch under active review — a PR open against
master, green CI, a linked JIRA in "Patch Available," a reproducer a committer can run in one command, and a review conversation you are driving. Merges can take weeks that are outside your control; a patch that a committer would merge, blocked only on their calendar, counts as done for grading.
What does not count: a local branch you never pushed; a PR with red CI you stopped babysitting; "I think this fixes it" with no failing test. The bar is a patch another engineer trusts, not code that compiles.
And in both cases: the engineering write-up exists. 500–1000 words — problem, investigation, design, alternatives, lessons. It is not optional. It is how the community and your future self learn from the investigation, and it is 10 rubric points (Step 10).
The deliverable set
By the time you mark the Capstone done, every one of these artifacts exists. Track them with a checklist:
| # | Artifact | Lives in |
|---|---|---|
| 1 | Failing reproducer test — red on master without your patch, green with it | tez-tests/ or a module-local src/test/java/... |
| 2 | Root-cause document (200–500 words, with file#method citations) | capstone-work/root-cause.md in your fork |
| 3 | Minimum-diff patch | A branch on your fork of apache/tez |
| 4 | Unit tests with a drainable dispatcher (if state-machine related) | The relevant src/test/java |
| 5 | Integration test on MiniTezCluster (if end-to-end behavior changed) | tez-tests/src/test/java/org/apache/tez/test/ |
| 6 | Validation report (mvn test -pl <module>, checkstyle, spotbugs, RAT output) | capstone-work/validation.md |
| 7 | GitHub PR against apache/tez:master, JIRA key in the title | github.com/apache/tez/pulls |
| 8 | JIRA updated: "Patch Available," PR linked, release-note filled if user-visible | issues.apache.org/jira/browse/TEZ-NNNN |
| 9 | Engineering write-up (problem, investigation, design, alternatives, lessons) | Blog, Apache wiki, or dev@tez.apache.org summary |
-
Failing reproducer committed and confirmed red on
master -
capstone-work/root-cause.mdwritten - Minimum-diff patch on a feature branch
- Unit tests cover every branch you added
- Integration test if behavior is end-to-end
-
capstone-work/validation.mdwith a clean precommit -
PR opened against
master, JIRA-keyed title - JIRA at "Patch Available," PR linked
- Write-up published
How the Capstone is assessed
The full rubric — 100 points, self-graded, honestly — lives in
evaluation-rubric.md. Read it before Step 1, not after
Step 10; it tells you what "good" looks like at every step, and you should be scoring
yourself against it as you go. Headline weights:
| Area | Weight |
|---|---|
| Problem articulation (symptom vs. root cause, trigger conditions) | 20 |
Execution-path mastery (file#method citations, accurate diagram) | 20 |
| Implementation quality (minimum diff, conventions, no scope creep) | 20 |
| Testing (unit + integration, deterministic, branch coverage) | 15 |
| Review responsiveness (addresses comments, iteration cadence) | 10 |
| Documentation (JIRA, code comments, write-up) | 10 |
| Community interaction (mailing-list etiquette, handoff hygiene) | 5 |
Tier thresholds:
- 80+ — credible Tez contributor. You can sustain a steady patch flow.
- 90+ — committer-ready. You are doing work a committer would do without hand-holding.
- 95+ — PMC-track. You are leading work others want to follow.
You self-grade in Step 10. Be honest — inflated self-grades are visible from orbit the moment a committer reads your write-up next to your diff.
Time budget
The Capstone is a 4–6 week effort if you have one focused evening per weekday plus weekend mornings. Less than that and you risk losing context between sessions — far more expensive than people expect for state-machine and scheduler code, where the bug lives in the interleaving of events across three classes and you have to rebuild the whole mental picture every time you sit down.
| Week | Steps | Hours |
|---|---|---|
| 1 | 1–2: Pick an issue, build a deterministic reproducer | 10–15 |
| 2 | 3–4: Trace execution, identify root cause | 12–18 |
| 3 | 5–6: Implement fix, write unit + integration tests | 12–18 |
| 4 | 7–8: Validate, prepare patch / PR, push | 8–12 |
| 5 | 8–9: Review iteration (two or three rounds is normal) | 6–10 |
| 6 | 10: Write-up, JIRA cleanup, retrospective | 4–6 |
If you blow past six weeks, that is a signal — not a failure. Either the issue is
larger than it looked (pause and renegotiate scope in the JIRA), or you are stuck on a
specific step (ask on dev@tez.apache.org). Do not silently grind for another month.
Failure modes of Capstone attempts
Most Capstones that stall die from one of four self-inflicted wounds. Recognize them early; each has a specific antidote.
1. Picking a too-big issue
The single most expensive mistake, made in Step 1 and paid for over six weeks. A
"rewrite the shuffle scheduler" or "add speculative execution to X" JIRA is a
multi-committer, multi-month effort, not a Capstone. The tell: you cannot state the
fix as "change the behavior of one method under one condition." The antidote is in
Step 1 — size the issue by the diff you predict, not by
how interesting it sounds. A landable first patch is typically under ~150 lines of
production change touching one or two classes. Look at the exemplar commits:
TEZ-4580 changed YarnTaskSchedulerService by 16 lines; TEZ-4569 changed VertexImpl
by 63. That is the size that merges.
2. Skipping reproduction
You read the JIRA, form a theory, and start editing in Step 5 with no failing test in
hand. Now every "fix" is theater — you cannot prove it fixes anything, and you cannot
prove you did not break something else. This is the deadliest failure mode because it
feels like progress. The antidote is the repro-first rule in
Step 2: no code changes until a test fails on master with
an assertion error. If you find yourself in Step 5 without a red test, you are not in
Step 5. Go back to Step 2.
3. Silent scope creep
You went in to fix an NPE in TaskAttemptImpl and now your diff also renames three
fields, "cleans up" a switch statement, and adds a helper you thought was missing.
Every unrelated line you touch is a line a committer must review, a line that can
break, and a reason to send the PR back. The antidote: keep a one-sentence scope
statement at the top of capstone-work/root-cause.md and reject any change that does
not serve it. Refactors are separate JIRAs. See
Step 5.
4. Arguing instead of iterating
Review comes back with a request you disagree with, and you spend three days debating in PR comments instead of either making the change or asking a clarifying question. Committers have finite patience and infinite backlog. The antidote: treat every review comment as either "change the code" or "ask one precise question," never "defend the code." Review responsiveness is 10 rubric points and, more importantly, it is the difference between a merge and a stale PR the committer quietly stops reading.
Success indicators
You will know it is working when:
- A committer comments "+1" / "LGTM, will commit shortly" on your PR, and CI is green.
- Your fix appears in
git log apache/masterwith theTEZ-NNNNsubject line and your authorship. - The JIRA you claimed flips to "Resolved / Fixed in X.Y.Z" with your name on it.
- Your write-up gets traffic — search hits, a reply on
user@, a committer pointing the next contributor at it. - The next time you pick a JIRA, you reach root cause in days, not weeks.
You will know it is failing when: you are still editing files in Step 5 with no failing
test from Step 2; your PR description says "I think this might fix it"; you have not run
mvn test -pl tez-dag end-to-end in over a week; or you are arguing in PR comments
instead of changing code. If you spot a failure signal, do not push through — stop,
reread the relevant step chapter, and reset.
Validation / Self-check
Before starting Step 1, confirm:
- You can produce, from memory, the source path of
DAGAppMaster,DAGImpl,VertexImpl,TaskImpl, andAsyncDispatcher. mvn clean install -DskipTestscompletes against your localtezclone on JDK 21.mvn test -pl tez-tests -Dtest=TestOrderedWordCountand-Dtest=TestLocalModeboth pass.- You have a
capstone-work/directory in your fork ready forroot-cause.md,validation.md, andwriteup.md. - You have skimmed every step-chapter once and read the rubric.
- You have set aside 4–6 calendar weeks with a realistic time budget.
- You have subscribed to
dev@tez.apache.org(send any mail todev-subscribe@tez.apache.org) andissues@tez.apache.org.
The clock starts when you comment "Working on this" on the JIRA. Go to Step 1: Issue Selection.