Skip to content

Commit 0c7e9bb

Browse files
authored
fix(core): fix client crashes on large TLS responses (#15)
1 parent 666e234 commit 0c7e9bb

4 files changed

Lines changed: 1174 additions & 37 deletions

File tree

.claude/skills/review-pr/SKILL.md

Lines changed: 210 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,210 @@
1+
---
2+
name: review-pr
3+
description: Review a GitHub pull request against QuestDB coding standards
4+
argument-hint: [PR number or URL]
5+
allowed-tools: Bash(gh *), Read, Grep, Glob, Agent
6+
---
7+
8+
Review the pull request `$ARGUMENTS`.
9+
10+
## Review mindset
11+
12+
You are a senior QuestDB engineer performing a blocking code review. QuestDB is mission-critical software deployed on spacecraft — bugs can cause data loss or system failures that cannot be patched after deployment. There is zero tolerance for correctness issues, resource leaks, or undefined behavior. Be critical, thorough, and opinionated. Your job is to catch problems before they ship, not to be nice.
13+
14+
- **Assume nothing is correct until you've verified it.** Read surrounding code to understand context — don't just look at the diff in isolation.
15+
- **Flag every issue you find**, no matter how small. Do not soften language or hedge. Say "this is wrong" not "this might be an issue".
16+
- **Do not praise the code.** Skip "looks good", "nice work", "clever approach". Focus entirely on problems and risks.
17+
- **Think adversarially.** For each change, ask: what inputs break this? What happens under concurrent access? What if this runs on a 10-billion-row table? What if the column is NULL? What if the partition is empty?
18+
- **Check what's missing**, not just what's there. Missing tests, missing error handling, missing edge cases, missing documentation for non-obvious behavior.
19+
- **Verify every claim.** If the PR title says "fix", verify the bug actually existed and the fix is correct. If it says "improve performance", look for benchmarks or reason about the algorithmic change — does it actually improve things, or could it regress in other cases? If it says "simplify", verify the new code is actually simpler and doesn't drop behavior. Treat the PR description as an unverified hypothesis, not a statement of fact.
20+
- **Read the full context of changed files** when the diff alone is ambiguous. Use Read/Grep/Glob to inspect the surrounding code, callers, and related tests.
21+
- **Assess reachability before reporting.** For every potential bug, trace the actual callers and inputs. If a problem
22+
requires physically impossible conditions (billions of columns, corrupted JNI inputs, values that no caller can
23+
produce), it is not a real finding — drop it. Focus on bugs that real workloads can trigger, not theoretical edge
24+
cases that exist only in the type system.
25+
- **QuestDB runs with Java assertions enabled (`-ea`).** Assertions are a valid guard for invariants that indicate
26+
corruption or internal bugs. Do NOT flag `assert` as insufficient — it is the preferred mechanism for conditions
27+
that should never occur in a non-corrupt database. Only flag an `assert` if the condition can plausibly be triggered
28+
by normal (non-corrupt) user operations.
29+
30+
## Step 1: Gather PR context
31+
32+
Fetch PR metadata, diff, and any review comments:
33+
34+
```bash
35+
gh pr view $ARGUMENTS --json number,title,body,labels,state
36+
gh pr diff $ARGUMENTS
37+
gh pr view $ARGUMENTS --comments
38+
```
39+
40+
## Step 2: PR title and description
41+
42+
Check against CLAUDE.md conventions:
43+
- Title follows Conventional Commits: `type(scope): description`
44+
- Description repeats the verb (e.g., `fix(sql): fix ...` not `fix(sql): DECIMAL ...`)
45+
- Description speaks to end-user impact, not implementation internals
46+
- If fixing an issue, `Fixes #NNN` is at the top of the body
47+
- Tone is level-headed and analytical, no superlatives or bold emphasis on numbers
48+
- Labels match the PR scope (SQL, Performance, Core, etc.)
49+
50+
## Step 3: Parallel review
51+
52+
Launch the following agents in parallel. Each agent receives the full PR diff and should read surrounding source files as needed for context.
53+
54+
**Agent 1 — Correctness & bugs:** NULL handling, edge cases, logic errors, off-by-one, operator precedence, error paths.
55+
56+
**Agent 2 — Concurrency:** Race conditions, shared mutable state, missing volatile, lock ordering, thread-safety of data structures.
57+
58+
**Agent 3 — Performance & allocations:** Regressions, zero-GC violations, `java.util.*` collections vs `io.questdb.std`, string creation/concatenation on hot paths, SIMD opportunities. Algorithmic complexity: for each new loop, traversal, or data structure, analyze how it scales with data size (row count, partition count, join fan-out). Flag any O(n^2) or worse patterns that could regress on large tables (1M+ rows, 1000+ partitions). Check whether new code paths are compile-time-only or data-path — compile-time allocations are acceptable, data-path allocations are not.
59+
60+
**Agent 4 — Resource management:** Leaks on all code paths (especially errors), try-with-resources, native memory, pool management.
61+
62+
**Agent 5 — Test review & coverage:** Coverage gaps, error path tests, NULL tests, boundary conditions, regression tests, test quality, `assertMemoryLeak()` usage.
63+
64+
**Agent 6 — Code quality & standards:** Code smell, member ordering, naming conventions, modern Java features, dead code, third-party dependencies.
65+
66+
**Agent 7 — PR metadata & conventions:** Title format, description quality, commit messages, labels, SQL style in tests.
67+
68+
**Agent 8 — Rust safety (only if PR contains .rs files):** Check for any code that can panic at runtime — `unwrap()`,
69+
`expect()`, array indexing without bounds checks, `panic!()`, `unreachable!()`, `todo!()`, integer overflow in release
70+
mode, `slice::from_raw_parts` with invalid inputs. In mission-critical software a panic in Rust code called via JNI/FFI
71+
will abort the entire JVM process with no recovery. Every fallible operation must use `Result`/`Option` with proper
72+
error propagation. Flag every potential panic site.
73+
74+
Combine all agent findings into a single deduplicated **draft** report. Do NOT present this draft to the user yet — it goes straight into verification.
75+
76+
## Step 3b: Verify every finding against source code
77+
78+
The parallel review agents work from the diff alone and frequently produce false positives — especially around memory ownership, polymorphic dispatch, Rust control-flow guarantees, and JNI lifecycle conventions. Every finding MUST be verified before it is reported.
79+
80+
For each finding in the draft report:
81+
82+
1. **Read the actual source code** at the exact lines cited. Do not rely on the agent's description alone.
83+
2. **Trace the full code path**: follow callers, inheritance hierarchies, and runtime types. A method called on a base-class reference may dispatch to a subclass override (e.g., `PartitionDescriptor.clear()` vs `OwnedMemoryPartitionDescriptor.clear()`).
84+
3. **Check both sides of JNI/FFI boundaries**: if a finding involves Java↔Rust interaction, read both the Java caller and the Rust JNI function. Verify ownership transfer, error propagation, and cleanup on both sides.
85+
4. **For resource leak claims**: trace every allocation to its corresponding free/close on ALL code paths (happy path,
86+
error path, finally blocks). Check for polymorphic `close()`/`clear()` overrides. Before claiming a leak between
87+
allocation and cleanup registration, verify that the intervening code can actually throw.
88+
5. **For Rust panic claims**: verify whether the panic site is actually reachable. Trace control flow backwards — a
89+
preceding guard or early return may make it unreachable.
90+
6. **For Rust panic claims via JNI**: trace the Java caller to check whether it can actually pass parameters that
91+
trigger the panic. If every caller validates inputs before the JNI call, the panic is unreachable — drop it.
92+
7. **For Rust numeric overflow claims**: check whether the overflow is reachable at realistic scale. QuestDB handles
93+
billions to a few trillion rows, thousands of tables, and thousands of columns — not billions of columns or
94+
quintillions of rows. If overflow requires values beyond that scale, drop it.
95+
8. **For performance claims**: check whether the cost is measurable in a realistic scenario. Downgrade to a nit if the
96+
saving is negligible relative to the surrounding work. Exception: GC allocations on a hot path are always worth
97+
flagging, even a single one.
98+
9. **Classify each finding** as:
99+
- **CONFIRMED** — the bug is real and reproducible via the traced code path
100+
- **FALSE POSITIVE** — the code is actually correct (explain why)
101+
- **CONFIRMED with nuance** — the issue exists but is less severe than stated (explain)
102+
103+
**Move false positives to a separate "Downgraded" section** at the end of the report. For each, give a one-line explanation of why it was dismissed. This lets the PR author verify the reasoning and catch verification mistakes.
104+
105+
Launch verification agents in parallel where findings are independent. Each verification agent should read surrounding source files, not just the diff.
106+
107+
## Review checklists
108+
109+
Review the diff for:
110+
111+
### Correctness & bugs
112+
- NULL handling: distinguish sentinel NULL vs actual NULL
113+
- Edge cases and error paths
114+
- SqlException positions point at the offending character, not the expression start
115+
- Logic errors, off-by-one, incorrect bounds, wrong operator precedence
116+
117+
### Concurrency
118+
- Race conditions: unsynchronized shared mutable state, missing volatile, unsafe publication
119+
- Lock ordering issues that could cause deadlocks
120+
- Thread-safety of data structures used across threads
121+
122+
### Performance
123+
- Performance regressions: changes that make hot paths slower or increase complexity
124+
- Unnecessary allocations on data paths (zero-GC requirement)
125+
- Use of `java.util.*` collections (HashMap, ArrayList, etc.) instead of QuestDB's own zero-GC collections in `io.questdb.std`
126+
- String creation or concatenation on hot paths (use CharSink, StringSink, or direct char[] instead)
127+
- Capturing lambdas on hot paths — lambdas that capture local variables or instance fields allocate a new object on every invocation. Non-capturing lambdas (static method refs, no closed-over state) are safe as the JVM caches them. Flag any capturing lambda on a data path.
128+
- Autoboxing on hot paths — primitive-to-wrapper conversions (`int``Integer`, `long``Long`, etc.) allocate silently. Watch for primitives passed to generic methods, stored in `java.util.*` collections, or returned from methods with wrapper return types.
129+
- Missing SIMD or vectorization opportunities
130+
- Inefficient algorithms where QuestDB already provides optimized alternatives
131+
- Algorithmic complexity at scale: for each new loop or traversal, what is the time complexity as a function of row count, partition count, or join fan-out? Flag O(n^2) or worse patterns. Consider: what happens with 1M outer rows? 10K partitions? 100-way fan-out per row?
132+
- Compile-time vs data-path distinction: allocations and O(n) scans during SQL compilation/optimization are acceptable; the same on per-row data paths are not
133+
134+
### Code quality
135+
- Code smell: overly complex methods, deep nesting, unclear intent, dead code
136+
- No third-party Java dependencies on data paths
137+
138+
### QuestDB coding standards
139+
- Class members grouped by kind (static vs instance) and visibility, sorted alphabetically
140+
- Boolean names use `is...` / `has...` prefix
141+
- Modern Java features: enhanced switch, multiline strings, pattern variables in instanceof
142+
143+
### Resource management
144+
- Resources properly closed in all code paths (especially error paths)
145+
- try-with-resources used where applicable
146+
- Native memory freed correctly
147+
148+
### SQL conventions (if tests or SQL involved)
149+
- Keywords in UPPERCASE
150+
- `expr::TYPE` cast syntax preferred over CAST()
151+
- Underscores in numbers >= 5 digits (e.g., 1_000_000)
152+
- Multiline strings for complex queries
153+
- No DELETE statements (suggest DROP PARTITION or soft delete)
154+
- Tests use `assertMemoryLeak()`, `assertQueryNoLeakCheck()`, `execute()` for DDL
155+
- Single INSERT for multiple rows
156+
157+
### Enterprise permissions & ACL (if PR introduces new SQL statements or ALTER operations)
158+
- New ALTER TABLE operations almost always require a new enterprise permission. If the PR adds a new ALTER statement (or any new SQL statement that modifies state), flag it if there is no corresponding `SecurityContext.authorize*()` call in the execution path.
159+
- New features in OSS should have an enterprise counterpart that wires up ACL. Check whether the PR introduces `authorize*` methods in `SecurityContext` and whether all enterprise `SecurityContext` implementations (`EntSecurityContextBase`, `AdminSecurityContext`, `AbstractReplicaSecurityContext`, and test mocks) are updated.
160+
- New permissions must be registered in `Permission.java` (constant, name maps, and included in `TABLE_PERMISSIONS`/`ALL_PERMISSIONS` as appropriate).
161+
- The `PermissionParser` must be able to parse GRANT/REVOKE for the new permission name — especially if the name contains SQL keywords like `ON`, `TO`, or `FROM` that could conflict with parser grammar.
162+
- Replica security contexts must deny new write operations (`deniedOnReplica()`).
163+
164+
### Test review
165+
- **Coverage gaps:** For every new or changed code path, verify a corresponding test exists. If not, flag it explicitly as "missing test for X".
166+
- **Error path coverage:** Are failure cases, exceptions, and edge conditions tested — not just the happy path?
167+
- **NULL tests:** Are NULL inputs, NULL columns, and NULL expression results tested?
168+
- **Boundary conditions:** Empty tables, empty partitions, single-row tables, max-value inputs, zero-length strings.
169+
- **Concurrency tests:** If the code touches shared state, are there tests that exercise concurrent access?
170+
- **Resource leak tests:** Tests must use `assertMemoryLeak()` for anything that allocates native memory.
171+
- **Test quality:** Are tests actually asserting the right thing? Watch for tests that pass trivially, assert on wrong values, or test implementation details instead of behavior.
172+
- **Regression tests:** If this PR fixes a bug, is there a test that reproduces the original bug and would fail without the fix?
173+
- Use Grep/Glob to find existing test files for the changed classes and verify they cover the new behavior.
174+
175+
### Unresolved TODOs and FIXMEs
176+
- Scan the diff for `TODO`, `FIXME`, `HACK`, `XXX`, and `WORKAROUND` comments. For each one found:
177+
- Is it a pre-existing comment that was just moved/reformatted, or newly introduced in this PR?
178+
- If newly introduced: does it represent unfinished work that should block the merge, or a known limitation that is acceptable to ship? Flag any that look like deferred bugs or incomplete implementations.
179+
- If the TODO references a ticket/issue number, verify the reference exists.
180+
181+
### Commit messages
182+
- Plain English titles (no Conventional Commits prefix), under 50 chars
183+
- Full long-form body description, line breaks at 72 chars
184+
- Active voice, naming the acting subject
185+
186+
## Step 4: Output
187+
188+
Present ONLY verified findings (false positives are excluded). Structure as:
189+
190+
### Critical
191+
Issues that must be fixed before merge. Each must include:
192+
- Exact file path and line numbers
193+
- Code path trace showing why the bug is real
194+
- Suggested fix
195+
196+
### Moderate
197+
Issues worth addressing but not blocking.
198+
199+
### Minor
200+
Style nits and suggestions.
201+
202+
### Downgraded (false positives)
203+
Findings from the initial review that were dismissed after source code verification. For each, state:
204+
- The original claim (one line)
205+
- Why it was dismissed (one line, citing the specific code that disproves it)
206+
207+
### Summary
208+
- One-line verdict: approve, request changes, or needs discussion
209+
- Highlight any regressions or tradeoffs
210+
- State how many draft findings were verified vs dropped as false positives (e.g., "8 findings verified, 4 false positives removed")

0 commit comments

Comments
 (0)