-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Work on adding custom error handling * Add error handling to middleware stack * Work on dynamic error definition * fix error generation * Work on ci using middleware * try different path to get to load in gh ci * Try adding require to rails helper * move pre loading * revert addition to require middleware in rails helper * Add debuggin steps * fix typo in debugger action * try loading manually in application.rb * try loading in different dir * fix typo * fix rubocop errors * remove debugger actions * Add spec for different error * update test title * Add script to start redis in background and start rails server * fix rubocop
- Loading branch information
Showing
14 changed files
with
237 additions
and
15 deletions.
There are no files selected for viewing
This file contains 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
This file contains 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
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
# frozen_string_literal: true | ||
|
||
class ApiExceptionSerializer | ||
include JSONAPI::Serializer | ||
set_type :error | ||
set_id do |error, _params| | ||
error.status | ||
end | ||
|
||
attributes :status, :code, :message | ||
end |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
#!/bin/bash | ||
|
||
port=3000 # Default port | ||
|
||
# Parse command line options | ||
while getopts ":p:" opt; do | ||
case ${opt} in | ||
p) | ||
port=${OPTARG} | ||
;; | ||
\?) | ||
echo "Invalid option: -$OPTARG" >&2 | ||
exit 1 | ||
;; | ||
:) | ||
echo "Option -$OPTARG requires an argument." >&2 | ||
exit 1 | ||
;; | ||
esac | ||
done | ||
|
||
# Start Redis in daemon mode | ||
redis-server --daemonize yes | ||
|
||
# Start Rails server on specified port | ||
echo "Starting Rails server on port $port" | ||
bundle exec rails server -p $port |
This file contains 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
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
# frozen_string_literal: true | ||
|
||
module ApiException | ||
class BaseException < StandardError | ||
include ActiveModel::Serialization | ||
attr_reader :status, :code, :message | ||
|
||
def initialize(message, code = 500, status = :internal_error) | ||
super(message) | ||
@status = status | ||
@code = code | ||
@message = message | ||
end | ||
end | ||
|
||
class HTTPRequestError < BaseException; end | ||
class JSONParserError < BaseException; end | ||
class NoBlockGivenError < BaseException; end | ||
class RecordNotFound < BaseException; end | ||
class RetryError < BaseException; end | ||
class RideCountMismatchError < BaseException; end | ||
end |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
# frozen_string_literal: true | ||
|
||
module ApiException | ||
module ErrorMapper | ||
def map_error(exception) | ||
custom_error_class_name = "ApiException::#{exception.class.name.split('::').last}" | ||
if Object.const_defined?(custom_error_class_name) | ||
custom_error_class_name.constantize | ||
else | ||
define_error_class(custom_error_class_name) | ||
end | ||
end | ||
|
||
private def define_error_class(class_name) | ||
clean_class_name = class_name.split("::").last.gsub(/[^\w]/, "") # Clean up class name | ||
|
||
# Define the error class if it doesn't exist | ||
unless Object.const_defined?(clean_class_name) | ||
error_class = Class.new(ApiException::BaseException) do | ||
def initialize(msg = nil, code = 500, status = :internal_error) | ||
super(msg, code, status) | ||
end | ||
end | ||
|
||
ApiException.const_set(clean_class_name, error_class) | ||
end | ||
|
||
ApiException.const_get(clean_class_name) | ||
end | ||
end | ||
end |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
# frozen_string_literal: true | ||
|
||
module Client | ||
module Helpers | ||
def with_retries(max_retries: 10, &blk) | ||
raise ApiException::NoBlockGivenError, "Must provide a block" if blk.blank? | ||
|
||
retries = 0 | ||
begin | ||
yield | ||
rescue StandardError => _e | ||
raise ApiException::RetryError unless retries <= max_retries | ||
|
||
retries += 1 | ||
max_sleep_seconds = Float(2**retries) | ||
sleep rand(0..max_sleep_seconds) | ||
retry | ||
end | ||
end | ||
end | ||
end |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
# frozen_string_literal: true | ||
|
||
require "./lib/api_exception/error_mapper" | ||
|
||
module Middleware | ||
class ErrorHandler | ||
include ApiException::ErrorMapper # Include the module where map_error and define_error_class are defined | ||
|
||
def initialize(app) | ||
@app = app | ||
end | ||
|
||
def call(env) | ||
@app.call(env) | ||
rescue StandardError => e | ||
handle_exception(e) | ||
end | ||
|
||
private def handle_exception(exception) | ||
error_class = map_error(exception) | ||
raise error_class, exception.message | ||
rescue ApiException::RecordNotFound => e | ||
render_error_response(e, 404, :not_found) | ||
rescue StandardError => e | ||
render_error_response(e, 500, e.status || :internal_error) | ||
end | ||
|
||
private def render_error_response(error, status, code) | ||
[status, { "Content-Type" => "application/json" }, | ||
[{ error: { status:, code:, message: error.message } }.to_json]] | ||
end | ||
end | ||
end |
This file contains 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
This file contains 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
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
# frozen_string_literal: true | ||
|
||
require "rails_helper" | ||
|
||
RSpec.describe "Errors", :skip_geocode, type: :request do | ||
it "raises JSONParserError and responds with correct error shape" do | ||
expect(Rides::Commands::GetRoutesData).to receive(:call).and_raise( | ||
ApiException::JSONParserError.new("Attemped to parse invalid JSON:"), 500 | ||
) | ||
driver = create(:driver) | ||
get "/drivers/#{driver.id}/selectable_rides" | ||
|
||
expect(response).to have_http_status(500) | ||
result = JSON.parse(response.body, symbolize_names: true) | ||
|
||
expect(result[:error].keys).to include(:status, :code, :message) | ||
expect(result.dig(:error, :message)).to eq("Attemped to parse invalid JSON:") | ||
expect(result.dig(:error, :code)).to eq("internal_error") | ||
end | ||
end |
This file contains 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
This file contains 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