Last active
May 22, 2024 05:08
-
-
Save thiagoa/3d09fa38455273b4b885533bd3de1390 to your computer and use it in GitHub Desktop.
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
require "json" | |
require "faraday" | |
# Configure before using or execute this code as-is | |
# and get a 401 | |
module Configuration | |
class << self | |
attr_accessor :organization_id, :api_key | |
end | |
end | |
module ResultChainable | |
attr_reader :next_result | |
def initialize(next_result: nil, **attrs) | |
super(**attrs) | |
@next_result = next_result | |
end | |
def chain_result(next_result) | |
attrs = { | |
status: next_result.status, | |
next_result: next_result | |
} | |
self.class.new(**to_h, **attrs) | |
end | |
end | |
Result = Struct.new(:status, :error_code, :id, keyword_init: true) do | |
include ResultChainable | |
def success? | |
status == :ok | |
end | |
def error? | |
!success? | |
end | |
end | |
class LineItemRequest | |
BASE_URL = "https://app.moderntreasury.com/api/" | |
HEADERS = {"Content-Type" => "application/json"}.freeze | |
def self.execute(params) | |
response = client.post("ledger_transactions", JSON.dump(params)) | |
if response.status == 200 | |
Result.new(status: :ok, id: response.body["id"]) | |
else | |
Result.new(status: :error, error_code: response.status) | |
end | |
end | |
def self.rollback(result, _params) | |
return if result.nil? | |
patch_params = {status: "archived"} | |
client.patch "ledger_transactions/#{result.id}", JSON.dump(patch_params) | |
end | |
private_class_method def self.client | |
Faraday.new(url: BASE_URL, headers: HEADERS) do |client| | |
org_id = Configuration.organization_id | |
api_key = Configuration.api_key | |
client.response :json | |
client.request :authorization, :basic, org_id, api_key | |
end | |
end | |
end | |
class RequestRunner | |
def self.execute(request, params) | |
result = request.execute(params) | |
if block_given? && result.success? | |
begin | |
next_result = yield(result) | |
rescue => e | |
request.rollback(result, params) | |
raise e | |
end | |
if next_result.respond_to?(:chain_result) | |
result = result.chain_result(next_result) | |
if next_result.error? | |
request.rollback(result, params) | |
end | |
end | |
end | |
result | |
end | |
end | |
class TransactionalRequestRunner | |
def self.execute(array_of_arguments) | |
request, params, on_success = array_of_arguments.shift | |
request.execute(params) do |result| | |
on_success.call result if on_success | |
unless array_of_arguments.empty? | |
execute array_of_arguments | |
end | |
end | |
end | |
end | |
def main | |
# Fake params here. Replace with real ones. | |
params_1 = {id: "request-one"} | |
params_2 = {id: "request-two"} | |
params_3 = {id: "request-three"} | |
# Different types of requests can be used here | |
RequestRunner.execute LineItemRequest, params_1 do |_result_1| | |
RequestRunner.execute LineItemRequest, params_2 do |_result_2| | |
RequestRunner.execute LineItemRequest, params_3 do |_result_3| | |
puts "All successful!" | |
end | |
end | |
end | |
end | |
def main_with_transactional_request_runner | |
# Fake params here. Replace with real ones. | |
params_1 = {id: "request-one"} | |
params_2 = {id: "request-two"} | |
params_3 = {id: "request-three"} | |
array_of_arguments = [ | |
[LineItemRequest, params_1], | |
[LineItemRequest, params_2], | |
[LineItemRequest, params_3, ->(_result_3) { puts "All successful!" }] | |
] | |
TransactionalRequestRunner.execute(array_of_arguments) | |
end | |
# Choose "main" or "main_with_transactional_request_runner" | |
result = main | |
p result |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment