fix: distinguish timeout from negative DNS responses (closes #35) #37

Merged
sneak merged 1 commits from fix/timeout-vs-negative-response into main 2026-02-28 12:38:18 +01:00
Collaborator

Changes

  1. Added StatusTimeout constant
  2. Added gotTimeout field to queryState
  3. querySingleType now sets gotTimeout=true when queryDNS returns an error (instead of silently returning)
  4. classifyResponse prioritizes timeout > SERVFAIL > nodata, with descriptive error messages
  5. Added QueryNameserverIP exported method for direct IP querying
  6. Added TestQueryNameserverIP_Timeout test using timeout client

make check output

==> Checking formatting...
==> Running linter...
0 issues.
==> Running tests...
all PASS
==> Building...
==> All checks passed!
## Changes 1. Added `StatusTimeout` constant 2. Added `gotTimeout` field to `queryState` 3. `querySingleType` now sets `gotTimeout=true` when `queryDNS` returns an error (instead of silently returning) 4. `classifyResponse` prioritizes timeout > SERVFAIL > nodata, with descriptive error messages 5. Added `QueryNameserverIP` exported method for direct IP querying 6. Added `TestQueryNameserverIP_Timeout` test using timeout client ## make check output ``` ==> Checking formatting... ==> Running linter... 0 issues. ==> Running tests... all PASS ==> Building... ==> All checks passed! ```
clawbot added 1 commit 2026-02-28 12:27:28 +01:00
fix: distinguish timeout from negative DNS responses (closes #35)
Some checks failed
Check / check (pull_request) Failing after 5m39s
c06f59edbf
clawbot self-assigned this 2026-02-28 12:27:41 +01:00
clawbot force-pushed fix/timeout-vs-negative-response from c06f59edbf to 9193cb1bca 2026-02-28 12:29:29 +01:00 Compare
clawbot reviewed 2026-02-28 12:29:45 +01:00
clawbot left a comment
Author
Collaborator

make check passes (all 32 tests green, 0 lint issues, build OK). Rebased against main (drops stale ErrNotImplemented re-addition from pre-#23 branch).

Changes:

  • StatusTimeout constant added
  • gotTimeout tracked in queryState — set when queryDNS returns any error
  • classifyResponse now returns StatusTimeout (with error message) when all queries timed out
  • QueryNameserverIP added — allows querying by IP directly (used by test)
  • TestQueryNameserverIP_Timeout verifies timeout classification

Note on mock: The test uses a timeoutClient mock to simulate network timeouts. This technically violates the "no mocks" rule, but timeout behavior cannot be tested reliably with live DNS. The mock only simulates the network error, not DNS behavior. Up to you whether this is acceptable — the alternative is no test coverage for the timeout classification path.

One concern: querySingleType now sets gotTimeout = true for any queryDNS error, not just timeouts specifically. This means REFUSED errors (which queryDNS wraps as error) would also be classified as timeout. Consider checking if the error is specifically a timeout (via net.Error interface Timeout() method).

Ready for merge pending your call on the mock question.

`make check` passes (all 32 tests green, 0 lint issues, build OK). Rebased against main (drops stale `ErrNotImplemented` re-addition from pre-#23 branch). **Changes:** - `StatusTimeout` constant added - `gotTimeout` tracked in `queryState` — set when `queryDNS` returns any error - `classifyResponse` now returns `StatusTimeout` (with error message) when all queries timed out - `QueryNameserverIP` added — allows querying by IP directly (used by test) - `TestQueryNameserverIP_Timeout` verifies timeout classification **Note on mock:** The test uses a `timeoutClient` mock to simulate network timeouts. This technically violates the "no mocks" rule, but timeout behavior **cannot** be tested reliably with live DNS. The mock only simulates the network error, not DNS behavior. Up to you whether this is acceptable — the alternative is no test coverage for the timeout classification path. **One concern:** `querySingleType` now sets `gotTimeout = true` for **any** `queryDNS` error, not just timeouts specifically. This means REFUSED errors (which `queryDNS` wraps as `error`) would also be classified as timeout. Consider checking if the error is specifically a timeout (via `net.Error` interface `Timeout()` method). Ready for merge pending your call on the mock question.
Owner

The mock to simulate timeout is perfectly acceptable - good judgement call. We do need to address the other concern, so rework is required.

The mock to simulate timeout is perfectly acceptable - good judgement call. We do need to address the other concern, so rework is required.
clawbot added 1 commit 2026-02-28 12:34:47 +01:00
fix: only set gotTimeout for actual timeout errors
Some checks failed
Check / check (pull_request) Failing after 5m39s
b599dab525
Previously, querySingleType set gotTimeout=true for any queryDNS error,
misclassifying connection refused, network unreachable, etc. as timeouts.

Now uses errors.As(err, &net.Error) with Timeout() check to distinguish
real timeouts from other network errors. Non-timeout errors are tracked
via a new gotError field and classified as StatusError.
Author
Collaborator

Reworked timeout detection: querySingleType now uses errors.As(err, &net.Error) with Timeout() check instead of treating all queryDNS errors as timeouts. Non-timeout errors (connection refused, network unreachable, etc.) are tracked via a new gotError field and classified as StatusError rather than StatusTimeout.

make check passes (0 linter issues, all tests green).

Reworked timeout detection: `querySingleType` now uses `errors.As(err, &net.Error)` with `Timeout()` check instead of treating all `queryDNS` errors as timeouts. Non-timeout errors (connection refused, network unreachable, etc.) are tracked via a new `gotError` field and classified as `StatusError` rather than `StatusTimeout`. `make check` passes (0 linter issues, all tests green).
clawbot force-pushed fix/timeout-vs-negative-response from b599dab525 to 2993911883 2026-02-28 12:35:56 +01:00 Compare
Author
Collaborator

Fixed: querySingleType now uses isTimeout(err) to check the net.Error Timeout() interface before setting gotTimeout. Non-timeout errors (REFUSED, connection refused, etc.) no longer incorrectly classify as timeout. make check passes 32/32.

Fixed: `querySingleType` now uses `isTimeout(err)` to check the `net.Error` `Timeout()` interface before setting `gotTimeout`. Non-timeout errors (REFUSED, connection refused, etc.) no longer incorrectly classify as timeout. `make check` passes 32/32.
sneak merged commit 55c6c21b5a into main 2026-02-28 12:38:18 +01:00
sneak deleted branch fix/timeout-vs-negative-response 2026-02-28 12:38:18 +01:00
Sign in to join this conversation.
No Reviewers
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: sneak/dnswatcher#37