Created
May 22, 2024 10:52
-
-
Save RStankov/2b76e1d3e6631db2732887e9cecd3151 to your computer and use it in GitHub Desktop.
Exception tips
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
# frozen_string_literal: true | |
module ErrorReporting | |
extend self | |
def assign_user(user) | |
return unless Rails.env.production? | |
Sentry.set_user( | |
id: user.id, | |
username: user.username, | |
admin: user.admin?, | |
) | |
end | |
def capture(error, context = {}) | |
raise error unless Rails.env.production? | |
context.each { |k, v| Sentry.set_context(k, v) } | |
if error.is_a?(String) | |
Sentry.capture_message(error) | |
else | |
Sentry.capture_exception(error) | |
end | |
end | |
def job_discarded(job, exception) | |
Rails.logger.error "Discarded #{job.class} due to #{exception.cause.inspect}." | |
capture(exception, job_name: job.class.name, job_arguments: job.arguments) | |
end | |
end |
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
# NOTE(rstankov): Browsers send params in wrong encoding, which causes `invalid byte sequence in UTF-8` | |
# More info: https://robots.thoughtbot.com/fight-back-utf-8-invalid-byte-sequences | |
module Handle::InvalidByteSequence | |
extend self | |
def call(string) | |
return nil if string.nil? | |
string.encode('UTF-8', invalid: :replace, undef: :replace, replace: '') | |
end | |
end |
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
module AngrySupport::Handle::Job::DeserializationError | |
def self.included(klass) | |
# NOTE(rstankov): Some time job is executed, before record is commit to database or record was deleted before backround jobs has been processed | |
klass.retry_on ActiveJob::DeserializationError, wait: 2.minutes, attempts: 3 do |job, exception| | |
ErrorReporting.job_discarded(job, exception) | |
end | |
end | |
end |
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
module AngrySupport::Handle::Job::NetworkErrors | |
extend ActiveSupport::Concern | |
included do | |
retry_on(*::AngrySupport::Handle::NetworkErrors::ERRORS, wait: 2.minutes, attempts: 5) do |job, exception| | |
ErrorReporting.job_discarded(job, exception) | |
end | |
end | |
end |
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
module Handle::NetworkErrors | |
extend self | |
ERRORS = [ | |
Addressable::URI::InvalidURIError, | |
EOFError, | |
Errno::EADDRNOTAVAIL, | |
Errno::ECONNREFUSED, | |
Errno::ECONNRESET, | |
Errno::EFAULT, | |
Errno::EHOSTUNREACH, | |
Errno::EINVAL, | |
Errno::EMFILE, | |
Errno::ENETUNREACH, | |
Errno::EPIPE, | |
Errno::ETIMEDOUT, | |
Faraday::ConnectionFailed, | |
Faraday::TimeoutError, | |
HTTP::ConnectionError, | |
HTTParty::Error, | |
IOError, | |
JSON::ParserError, | |
Net::HTTPBadResponse, | |
Net::HTTPHeaderSyntaxError, | |
Net::OpenTimeout, | |
Net::ProtocolError, | |
Net::ReadTimeout, | |
OpenSSL::SSL::SSLError, | |
OpenURI::HTTPError, | |
RestClient::BadGateway, | |
RestClient::BadRequest, | |
RestClient::Conflict, | |
RestClient::Exceptions::OpenTimeout, | |
RestClient::Exceptions::ReadTimeout, | |
RestClient::Forbidden, | |
RestClient::GatewayTimeout, | |
RestClient::InternalServerError, | |
RestClient::NotFound, | |
RestClient::RequestFailed, | |
RestClient::ServerBrokeConnection, | |
RestClient::ServiceUnavailable, | |
SocketError, | |
Timeout::Error, | |
Zlib::BufError, | |
Zlib::DataError, | |
].freeze | |
def ===(error) | |
ERRORS.any? { |error_class| error.is_a?(error_class) } | |
end | |
def call(fallback:) | |
yield | |
rescue *ERRORS => _e | |
fallback | |
end | |
end |
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
module Handle::RaceCondition | |
extend self | |
def call(max_retries: 2, transaction: false) | |
retries ||= max_retries | |
if transaction | |
ActiveRecord::Base.transaction do | |
yield | |
end | |
else | |
yield | |
end | |
rescue ActiveRecord::RecordNotUnique, PG::UniqueViolation, PG::InFailedSqlTransaction | |
retries -= 1 | |
raise unless retries.nonzero? | |
retry | |
rescue ActiveRecord::RecordInvalid => e | |
raise unless e.message.include? I18n.t('errors.messages.taken') | |
retries -= 1 | |
raise unless retries.nonzero? | |
retry | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment