Last active
April 6, 2023 16:56
-
-
Save kaspth/b13a4116bdd9e8f9735ea4abcec7acd0 to your computer and use it in GitHub Desktop.
Let secondary services deliver expositions to a primary service intake which it may process, everything happens on a private network.
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
class Invoice | |
delivers_exposition # only: :create ? | |
# ^ shorthand for this: | |
after_create_commit -> { Exposition.deliver_later "invoice.create", self } | |
after_update_commit -> { Exposition.deliver_later "invoice.update", self } | |
after_destroy_commit -> { Exposition.deliver_later "invoice.destroy", self } | |
end | |
class Exposition < Data.define(:service, :event, :gid) | |
def initialize(service: "invoices", **) = super | |
class DeliveryJob < ApplicationJob | |
def perform(**) = Exposition.new(**).deliver | |
end | |
def self.deliver_later(event, model) | |
DeliveryJob.perform_later(event:, gid: model.to_gid) | |
end | |
def deliver | |
Net::HTTP.post("https://localhost:4444/internal/intakes", service:, event:, gid:) | |
end | |
end | |
class Internal::ExpositionsController < ApplicationController | |
def show | |
render json: GlobalID.find(params[:gid]) # calls as_json, override on Invoice to tweak logic, could also use Jbuilder or whatever here | |
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
class Internal::IntakesController < ApplicationController | |
def create | |
Event::Job.perform_later params.permit! # Ensure job enqueue, that would fail on perform, to replay after fixing app-code. | |
end | |
end | |
class Event < Data.define(:service, :event, :gid) | |
class Job < ApplicationJob | |
def perform(**) = Event.new(**).perform | |
end | |
def perform | |
case service | |
when "invoices" then invoice_service_perform | |
else | |
raise "unknown service" # Fail job so it can be retried | |
end | |
end | |
private | |
def invoice_service_perform | |
case event | |
when "invoice.update" | |
Invoice.update! data.slice(:id, :customer_name) | |
end | |
end | |
def data = @data ||= client.fetch(gid) | |
def client = @client ||= Service.client(service) | |
end | |
class Service | |
mattr_accessor :endpoint | |
def self.client(name) | |
{ invoices: Invoice }.fetch(name.to_sym).new | |
end | |
def fetch(gid) | |
# However, Net::HTTP get works or another HTTP client gem. | |
Net::HTTP.get(endpoint, body: { gid: gid }).then { JSON.parse _1, symbolize_names: true } | |
end | |
class Invoice < Service | |
self.endpoint = "https://localhost:5555/internal/expositions" # Or some other routing | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment