Middleware all the things

At Trainline, we sell train tickets, across EU and UK.

How does it work? Frontends Rails API Connections API aka connection with carriers APIs

A bunch of middlewares Requests are processed by generated apps on the fly, which are stacks of middlewares.

Request (an environment Hash) Connections API env[:params][:action] Base::Builder.app do use DoSomething use AnotherThing # insert a bunch of cool stuff here end

Connections API An action (an app) Middleware 1 ① down ↓ ↑ ④ up Middleware 2 ② down ↓ ↑ ③ up Middleware 3 ⃔ → ⑤ env[:callback] ⃔

% tree lib/pacon/actions -L 1 lib/pacon/actions ├── book.rb ├── book_subscription.rb ├── cancel.rb ├── emit.rb ├── emit_subscription.rb ├── estimate_exchange.rb ├── estimate_refund.rb ├── exchange.rb ├── exchange_pay.rb ├── exchange_search.rb ├── fetch_pnr.rb ├── fetch_subscription.rb ├── fetch_travel_document.rb ├── immediate_cancel.rb ├── load_timetable.rb ├── pay.rb ├── refund.rb └── search.rb

def self.search Base::Builder.app do use Base::LogAction use Base::VolatileStations use Base::InitResultCache use Base::LogSearchFruitfulness use Base::AvoidFruitlessSearch use Base::ReportAndBlockCombinations use Base::TryAgain use Base::SearchWindow use Base::FilterUnsellableFolderMix use Base::FilterTimetableResults use Base::TooManyPassengers use Base::WarnDifferentStation use Base::Parallel end end

def self.search Base::Builder.app do use Base::LogAction use Base::VolatileStations use Base::InitResultCache use Base::LogSearchFruitfulness use Base::AvoidFruitlessSearch use Base::ReportAndBlockCombinations use Base::TryAgain use Base::SearchWindow use Base::FilterUnsellableFolderMix use Base::FilterTimetableResults use Base::TooManyPassengers use Base::WarnDifferentStation use Base::Parallel end end Will call SNCF.search, DB.search…

module SNCF class << self def search Base::Builder.app do use SNCF::Stations use SNCF::ExtractFoldersFromJourneys # tons of very secret sauce use SNCF::HttpRequest end end end end

Event Machine FTW The whole is based on Event Machine to coordinate all the parallel requests made to carriers APIs.