Build a Cloud in Thirteen Years

 Infrastructure Control Planes in Ruby, 2011 to 2024

https://slides.com/fdrfdr

Hello

Daniel Farina, a founder of Ubicloud

  • A new IaaS, compare AWS, Azure, GCP
  • Focused on core services (vm, lb, db)
  • A better value: ~30% the price
  • An open source Ruby program

What is it?

Practice Makes Perfect...ish

Ubicloud's code is the latest in a progression:

 Crunchy Data

 Citus Data

 Heroku Department of Data

Acknowledgements Will Leinweber and Craig Kerstiens of {Heroku,Citus,Crunchy} without whom this would have been impossible.

    ...and to Peter van Hardenberg, who stands at the beginning.

The Talk

  1. Excellent Gems: roda, sequel, rodauth
  2. Reinterpreting Ruby

Key Libraries

2007, Sequel: database access, ORM

2014, Roda: HTTP Routing

2015, Rodauth: Authentication

Why care about how a library is developed?

Jeremy Evans

Maintains all of:

Not only an acknowledgement.

The three programs are cohesive.

  Roda: request routing

  Rodauth: authentication

  Sequel: database access

Jeremy's Humility

Blink and you'll miss something important in his talks.

...it gives me a sense of accomplishment to be able to fix bugs in Ruby that have been known but unfixed for many years. That's a situation that doesn't happen in my other open source projects.

—From one tiny corner of an interview

Fact Check: TRUE

Monthly(?!) Releases

Adaption for Services

  • Everyone deploys their own PR
  • Supervises outcomes/does checks
  • No batching

Plugins

class MailProcessor < Roda
  plugin :mail_processor

  route do |r|
    # Match based on the To header, extracting the ticket_id
    r.to /ticket\+(\d+)@example.com/ do |ticket_id|
      if ticket = Ticket[ticket_id.to_i]
        # Mark the mail as handled if there is a valid ticket associated
        r.handle do
          ticket.add_note(text: mail_text, from: from)
        end
      end
    end

    # Match based on the To or CC header
    r.rcpt "post@example.com" do
      # Match based on the body, capturing the post id and tag
      r.body(/^Post: (\d+)-(\w+)/) do |post_id, tag|
        unhandled_mail("no matching post") unless post = Post[post_id.to_i]
        unhandled_mail("tag doesn't match for post") unless post.tag == tag

        # Match based on APPROVE somewhere in the mail text,
        # marking the mail as handled
        r.handle_text /\bAPPROVE\b/i do
          post.approve!(from)
        end

        # Match based on DENY somewhere in the mail text,
        # marking the mail as handled
        r.handle_text /\bDENY\b/i do
          post.deny!(from)
        end
      end
    end
  end
end

Omissions?

  • Opinions on JavaScript
    • Bundling
    • Serving
    • State synchronization
    • Testing
  • Mobile Application

Useful Plugins for Rails

Performance

commit f6e72e6386247e3ace3e2a85de3cb3fe04cbe239
Author: Jeremy Evans <jeremy@ubicloud.com>
Date:   Sun Oct 20 01:35:07 2024 -0700

    Avoid 4 allocations for every request
    
    Instead of splitting the host, just check it starts with `api.`.
    The four allocations come from:
    
    * 1 array allocation
    * 3 string allocations (potentially more or less depending on the
      number of `.` in the Host header)

100% Branch Coverage

Quick Tips on Adopting 100%

  • You should do it
  • It's about inexpensive gap identification
    • Much better to be at 100% than 99%
  • Enforce one file at a time
  • Handful of :nocov: is okay
  • Works well for one person
  • Works very well for larger teams

Isn't this all web stuff?

───────────────────────────────────────────────────────────────
Part        Files       Lines     Blanks    Comments     Code
───────────────────────────────────────────────────────────────
Whole        602       49709       7274        2139     40296

Specs        160       23448       3343         407     19698
Background    62        7024       1167         365      5492
Models        61        3304        613         265      2426
Host Program  53        5005        699         328      3978

~50% specs, 20KLOC application

Implements:

VM, DNS, Load Balancer, Hosted Postgres,

MinIO Blob Store, Rich Authorization, Web Console, Block Device Key management, ...

Ubicloud code counts

Check out

roda-sequel-stack

Reinterpreting Ruby

Common Interpretations

inspired, artistic, beautiful
"productive"

"developer happiness"
slow

wild or unprincipled

hard to maintain
good for prototyping, but

Reinterpretation

Stable

Rigorous

Prudent

Restrained

Economical
...slowish

Language Stability and Restraint

  • 2011: Start writing Ruby: Sequel, Sinatra
  • 2013: Ruby 2.0 adds keyword arguments
  • 2016: Ruby 3x3 initiative begins
  • 2021: YJIT in Ruby

Are tests a crutch for lack of

static typing?

no...

if you seek the highest standards of a rigorous program

Is static typing interesting?

Probably, for cross referencing

 

ruby-lsp

 

Improve economy of elimination of simple defects

REPL is Key

Ad hoc Reporting in REPL

2011

Ruby 🔥
Sequel 💧

Sinatra 💧

Postgres 💧

2024

Ruby 💧

Sequel 💧

 

Postgres 🔥

Roda ❄️

Rodauth ❄️

On Popularity

Legend: "normalness" in descending order 🔥💧❄️

Can you help?

The End

Build a Cloud in Thirteen Years v2

By fdrfdr

Build a Cloud in Thirteen Years v2

  • 79