Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Baltic Ruby 2024 - Solid SQLite Apps on Rails

Baltic Ruby 2024 - Solid SQLite Apps on Rails

Join me to learn how to pair the enhancements to Rails’ SQLite adapter with the suite of Solid libraries to create resilient, high-performance production apps.

Avatar for Stephen

Stephen

June 13, 2024
Tweet

More Decks by Stephen

Other Decks in Programming

Transcript

  1. Who am I? • Head of Engineering at Test IO

    • Open source developer rails/rails sparklemotion/sqlite3-ruby oldmoe/litestack joeldrapper/phlex joeldrapper/literal fractaledmind/activerecord-enhancedsqlite3-adapter fractaledmind/litestream-ruby fractaledmind/acidic_job • Writer: https://fractaledmind.github.io Stephen Margheim · @fractaledmind 🇺🇸 🛫 🇩🇪 💒 🇩🇰 📍 🇯🇲 💕 🐶🐕
  2. 1. Write-Ahead-Logging journal mode 2. IMMEDIATE transactions 3. non-GVL-blocking timeout

    mechanism 4. fair retry interval 5. isolated connection pools for reading and writing
  3. # config/database.yml queue: &queue <<: *default migrations_paths: db/queue_migrate database: storage/<%=

    Rails.env %>-queue.sqlite3 primary: &primary <<: *default database: storage/<%= Rails.env %>.sqlite3 development: primary: *primary queue: *queue
  4. # config/solid_queue.yml default: &default dispatchers: - polling_interval: 1 batch_size: 500

    recurring_tasks: periodic_litestream_backup_verfication_job: class: Litestream::VerificationJob args: [] schedule: every day at 1am EST # …
  5. # config/database.yml cache: &cache <<: *default migrations_paths: db/cache_migrate database: storage/<%=

    Rails.env %>-cache.sqlite3 # … development: primary: *primary queue: *queue cache: *cache
  6. # config/solid_cache.yml default: &default database: cache store_options: max_age: <%= 1.week.to_i

    %> max_size: <%= 256.megabytes %> namespace: <%= Rails.env %> # …
  7. # config/database.yml errors: &errors <<: *default migrations_paths: db/error_migrate database: storage/<%=

    Rails.env %>-errors.sqlite3 # … development: primary: *primary queue: *queue cache: *cache errors: *errors
  8. # config/application.rb config.solid_errors.connects_to = { database: { writing: :errors }

    } config.solid_errors.send_emails = true config.solid_errors.email_from = "[email protected]" config.solid_errors.email_to = “[email protected]"
  9. • Active Record (e.g. PostgreSQL, MySQL) • Solid Cache (e.g.

    Redis, Memcached) • Solid Queue (e.g. Sidekiq, Goodjob) • Solid Errors (e.g. Honeybadger, App Signal) • Solid Cable* (e.g. Redis, PostgreSQL)
  10. # config/litestream.yml dbs: - path: storage/production.sqlite3 replicas: - type: s3

    bucket: $LITESTREAM_REPLICA_BUCKET path: storage/production.sqlite3 access-key-id: $LITESTREAM_ACCESS_KEY_ID secret-access-key: $LITESTREAM_SECRET_ACCESS_KEY
  11. # config/initializers/litestream.rb Litestream.configure do |config| creds = Rails.application.credentials.litestream config.replica_bucket =

    creds.replica_bucket config.replica_key_id = creds.replica_key_id config.replica_access_key = creds.replica_access_key end
  12. • deferred foreign keys, • generated columns, • returning values

    from inserts, • PRAGMA tuning, • extension loading, and • improved concurrency support $ bundle add activerecord-enhancedsqlite3-adapter
  13. create_table :virtual_columns, force: true do |t| t.string :name t.virtual :upper_name,

    type: :string, as: "UPPER(name)", stored: true t.virtual :lower_name, type: :string, as: "LOWER(name)", stored: false t.virtual :octet_name, type: :integer, as: "LENGTH(name)" end
  14. $ bundle add sqlite-vss # /config/database.yml default: &default adapter: sqlite3

    pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> timeout: 5000 extensions: - sqlite_vss
  15. $ bundle config set build.sqlite3 \ "--with-sqlite-cflags=' -DSQLITE_DQS=0 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_MEMSTATUS=0

    -DSQLITE_LIKE_DOESNT_MATCH_BLOBS -DSQLITE_MAX_EXPR_DEPTH=0 -DSQLITE_OMIT_SHARED_CACHE -DSQLITE_USE_ALLOCA'"
  16. # config/database.yml development: <<: *default database: storage/<%= `git branch --show-current`.chomp

    || 'development' %>.sqlite3 # config/environments/development.rb config.after_initialize do ActiveRecord::Tasks::DatabaseTasks.prepare_all end
OSZAR »