Errors
One error class, what it carries, and branching on it with pattern matching.
One rescue covers everything the gem raises:
begin
channel.publish('status', payload)
rescue Blackevin::Error => error
error.status_code # 403, 429, … or nil when no response arrived
error.reason # 'queue_limit', 'connection_limit', 'message_rate_limit', or nil
error.quota? # a plan ceiling — show an upgrade prompt, retry later
error.message # the server's own sentence
endBranch on status_code and reason. The message is written for a person, and
its wording can change.
The three classes
| when | retry? | |
|---|---|---|
Blackevin::Error | the node answered with a refusal | depends on the status |
Blackevin::ConnectionError | no response: DNS, refused, TLS, timeout | yes |
Blackevin::ConfigurationError | a missing or malformed key, a bad argument — raised before any request | no, fix the call |
The last two inherit from the first.
The statuses worth handling
| status | meaning |
|---|---|
401 | unknown, revoked or malformed credentials — or a token request whose MAC, timestamp or nonce was refused |
403 | the key or token does not hold this operation on this channel |
404 | no such queue or rule in this account |
429 | a plan ceiling. Always carries reason |
A 429 is not a 403 on purpose: retrying can succeed, because a slot frees or
a plan is upgraded.
Pattern matching
Errors, token requests and every returned value implement deconstruct_keys, so
a rescue can branch by shape:
rescue Blackevin::Error => error
case error
in {reason: 'queue_limit'} then redirect_to upgrade_path
in {status_code: 401 | 403} then raise
in {status_code: nil} then retry_job wait: 30.seconds
endSecrets stay out of logs
inspect on a key, a client or a token never prints the secret or the token, so
an error report that captures local variables does not leak one.