Cut v0.4.0#11
Merged
Merged
Conversation
ApiError subclass for cgminer's "access denied" response (STATUS=E
Code 45) and the gem's own access_denied? local guard. Inherits
from ApiError so existing `rescue ApiError` clauses still catch
it; callers wanting finer dispatch use `rescue AccessDeniedError`
instead of pattern-matching on `e.code == :access_denied`.
- lib/cgminer_api_client/errors.rb: new AccessDeniedError class.
Constructor pins code: :access_denied so the symbolic tag is
consistent regardless of which call site raised. Also adds
ApiError.for_status — factory used by the wire-side emission
point that picks AccessDeniedError when the cgminer integer
maps to :access_denied, falling back to ApiError otherwise.
- lib/cgminer_api_client/miner.rb: check_status now delegates to
ApiError.for_status. Removes the inline Integer coercion and
class-picking from the case statement.
- lib/cgminer_api_client/miner/commands.rb: access_denied? raises
AccessDeniedError directly (legacy raise(class, message) form,
cgminer_code stays nil because privileged's rescue dropped it).
- Tests: dedicated access_denied_error_spec.rb covers class
hierarchy + constructor + rescue dispatch (subclass, ApiError,
Error). api_error_spec.rb gains .for_status coverage including
the String-Code defensive coercion. Existing emission-site
tests in miner_spec.rb, commands_spec.rb, and the wire-side
integration test extended to assert the subclass type.
Tests: 258 → 276 examples (+18). Rubocop clean. Coverage 99.7%.
ApiError.new("msg", code: 42) previously raised NoMethodError on
.to_sym deep in the constructor — opaque failure mode. code: false
silently bypassed to map lookup because false || x evaluates to x.
Both rejected at the library boundary now with a clear ArgumentError.
Symbol and String forms still work (the to_sym coercion stays for
ergonomic callers); nil still falls through to map lookup or
:unknown. Seven new tests pin the boundaries (Integer, Hash, Array,
false rejected; Symbol, String, nil accepted).
Tests: 276 → 283 examples (+7). Rubocop clean. Coverage 99.7%.
The fatal-status test asserts that an unmapped cgminer Code falls through to code: :unknown — but the assertion silently degrades if a future PR maps 23 to a symbol (the test would still pass, but exercise the mapped path while claiming to test the fallback). A precondition example asserting CGMINER_CODES has no key for 23 trips loudly the moment 23 gets mapped, so the unmapped fixture gets updated alongside the map change.
CHANGELOG:
- New [Unreleased] ### Added entry for AccessDeniedError +
ApiError.for_status factory.
- Existing structured-codes entry updated with the e.code-not-
e.cgminer_code dispatch advisory and the corrected mechanism
description (privileged hits the wire and discards the integer
in its rescue, rather than the previously stated "before any
wire interaction").
- New [Unreleased] ### Changed entry for the constructor's
Integer/Symbol-or-String input validation.
- Drops the "real cgminer 4.11.1 fixtures" version pin in favor
of "real cgminer wire fixtures" — the version isn't
load-bearing for the claim and would date when fixtures
refresh against a newer cgminer.
AGENTS.md:
- errors.rb tree-line picks up AccessDeniedError.
- Error-handling section gains the dispatch advisory ("prefer
e.code over e.cgminer_code") and a paragraph naming
AccessDeniedError + the asymmetry rule for adding new
ApiError subclasses (only when a code earns enough dispatch-
site interest).
- Same version-pin removal as the CHANGELOG.
- New paragraph names ApiError.for_status as the wire-side
factory and notes that non-wire paths raise the right class
directly rather than going through the factory.
Releases the Unreleased work accumulated since v0.3.0:
* on_wire: kwarg on Miner#initialize and MinerPool#initialize
* -v / --verbose flag on the bin/cgminer_api_client CLI with
addpool/setconfig/ascset/pgaset password redaction
* Structured cgminer_code (Integer) + code (Symbol) fields on
ApiError; CGMINER_CODES map (14, 45)
* AccessDeniedError < ApiError subclass + ApiError.for_status
factory for the most-dispatched-on case
* Constructor input validation: cgminer_code: Integer-or-nil,
code: Symbol/String-or-nil; ArgumentError on bad input
* MinerPool#load_miners! raises CgminerApiClient::Error (was
RuntimeError) when config/miners.yml is missing
* docs/logging.md silent-by-design stub + bundle-audit + Dependabot
* cgminer_test_support extraction (FakeCgminer + Fixtures)
Required by cgminer_manager v1.6.0 trace-id propagation work, which
threads request_id into per-request Miner instances via the on_wire:
closure pattern.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Release the [Unreleased] work since v0.3.0 so cgminer_manager v1.6.0 can depend on the on_wire: kwarg via the closure-based wiring pattern.
Highlights
Required by cgminer_manager v1.6.0 — the trace-id propagation work threads request_id into per-request Miner instances via on_wire:.
Test plan