├── test ├── dummy │ ├── log │ │ ├── .keep │ │ └── development.log │ ├── tmp │ │ ├── .keep │ │ ├── pids │ │ │ └── .keep │ │ ├── storage │ │ │ └── .keep │ │ └── local_secret.txt │ ├── storage │ │ ├── .keep │ │ └── test.sqlite3 │ ├── app │ │ ├── controllers │ │ │ ├── application_controller.rb │ │ │ └── my_application_controller.rb │ │ ├── models │ │ │ └── application_record.rb │ │ └── views │ │ │ └── layouts │ │ │ └── application.html.erb │ ├── bin │ │ ├── rake │ │ ├── rails │ │ └── setup │ ├── config │ │ ├── environment.rb │ │ ├── boot.rb │ │ ├── routes.rb │ │ ├── litestream.yml │ │ ├── locales │ │ │ └── en.yml │ │ ├── database.yml │ │ ├── application.rb │ │ ├── puma.rb │ │ └── environments │ │ │ └── test.rb │ └── config.ru ├── test_helper.rb ├── litestream │ ├── test_base_application_controller.rb │ └── test_commands.rb ├── controllers │ └── test_processes_controller.rb ├── generators │ └── test_install.rb ├── test_litestream.rb └── tasks │ └── test_litestream_tasks.rb ├── lib ├── litestream │ ├── version.rb │ ├── upstream.rb │ ├── engine.rb │ ├── generators │ │ └── litestream │ │ │ ├── install_generator.rb │ │ │ └── templates │ │ │ ├── config.yml.erb │ │ │ └── initializer.rb │ └── commands.rb ├── puma │ └── plugin │ │ └── litestream.rb ├── tasks │ └── litestream_tasks.rake └── litestream.rb ├── images └── show-screenshot.png ├── .standard.yml ├── sig └── litestream.rbs ├── bin ├── setup ├── console └── release ├── config └── routes.rb ├── .gitignore ├── Gemfile ├── app ├── controllers │ └── litestream │ │ ├── processes_controller.rb │ │ ├── application_controller.rb │ │ └── restorations_controller.rb ├── jobs │ └── litestream │ │ └── verification_job.rb └── views │ ├── layouts │ └── litestream │ │ ├── application.html.erb │ │ └── _style.html │ └── litestream │ └── processes │ └── show.html.erb ├── Rakefile ├── exe └── litestream ├── .github └── workflows │ ├── main.yml │ └── gem-install.yml ├── LICENSE ├── litestream.gemspec ├── rakelib └── package.rake ├── CODE_OF_CONDUCT.md ├── CHANGELOG.md ├── Gemfile.lock ├── LICENSE-DEPENDENCIES └── README.md /test/dummy/log/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/dummy/tmp/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/dummy/storage/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/dummy/tmp/pids/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/dummy/tmp/storage/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /lib/litestream/version.rb: -------------------------------------------------------------------------------- 1 | module Litestream 2 | VERSION = "0.14.0" 3 | end 4 | -------------------------------------------------------------------------------- /images/show-screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fractaledmind/litestream-ruby/HEAD/images/show-screenshot.png -------------------------------------------------------------------------------- /test/dummy/app/controllers/application_controller.rb: -------------------------------------------------------------------------------- 1 | class ApplicationController < ActionController::Base 2 | end 3 | -------------------------------------------------------------------------------- /test/dummy/app/controllers/my_application_controller.rb: -------------------------------------------------------------------------------- 1 | class MyApplicationController < ApplicationController 2 | end 3 | -------------------------------------------------------------------------------- /test/dummy/bin/rake: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require_relative "../config/boot" 3 | require "rake" 4 | Rake.application.run 5 | -------------------------------------------------------------------------------- /test/dummy/storage/test.sqlite3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fractaledmind/litestream-ruby/HEAD/test/dummy/storage/test.sqlite3 -------------------------------------------------------------------------------- /.standard.yml: -------------------------------------------------------------------------------- 1 | # For available configuration options, see: 2 | # https://github.com/testdouble/standard 3 | ruby_version: 3.0 4 | -------------------------------------------------------------------------------- /test/dummy/app/models/application_record.rb: -------------------------------------------------------------------------------- 1 | class ApplicationRecord < ActiveRecord::Base 2 | primary_abstract_class 3 | end 4 | -------------------------------------------------------------------------------- /sig/litestream.rbs: -------------------------------------------------------------------------------- 1 | module Litestream 2 | VERSION: String 3 | # See the writing guide of rbs: https://github.com/ruby/rbs#guides 4 | end 5 | -------------------------------------------------------------------------------- /test/dummy/tmp/local_secret.txt: -------------------------------------------------------------------------------- 1 | 2e674226836fd5b8d265fbc2088757c026b86086afb1ea213271ec09b432cce56122da2e7ba0ab5e70ab06f5b1b07fdf386b0cea6b28efce5afaa11d5aa1e76f -------------------------------------------------------------------------------- /bin/setup: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euo pipefail 3 | IFS=$'\n\t' 4 | set -vx 5 | 6 | bundle install 7 | 8 | # Do any other automated setup that you need to do here 9 | -------------------------------------------------------------------------------- /test/dummy/bin/rails: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | APP_PATH = File.expand_path("../config/application", __dir__) 3 | require_relative "../config/boot" 4 | require "rails/commands" 5 | -------------------------------------------------------------------------------- /test/dummy/config/environment.rb: -------------------------------------------------------------------------------- 1 | # Load the Rails application. 2 | require_relative "application" 3 | 4 | # Initialize the Rails application. 5 | Rails.application.initialize! 6 | -------------------------------------------------------------------------------- /test/dummy/config.ru: -------------------------------------------------------------------------------- 1 | # This file is used by Rack-based servers to start the application. 2 | 3 | require_relative "config/environment" 4 | 5 | run Rails.application 6 | Rails.application.load_server 7 | -------------------------------------------------------------------------------- /config/routes.rb: -------------------------------------------------------------------------------- 1 | Litestream::Engine.routes.draw do 2 | get "/" => "processes#show", :as => :root 3 | 4 | resource :process, only: [:show], path: "" 5 | resources :restorations, only: [:create] 6 | end 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.bundle/ 2 | /.yardoc 3 | /_yardoc/ 4 | /coverage/ 5 | /doc/ 6 | /pkg/ 7 | /spec/reports/ 8 | /tmp/ 9 | /exe/*/litestream 10 | test/dummy/log/test.log 11 | .DS_Store 12 | /test/**/*.sqlite3 13 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | source "https://rubygems.org" 4 | 5 | # Specify your gem's dependencies in litestream.gemspec 6 | gemspec 7 | 8 | gem "rake", "~> 13.0" 9 | 10 | gem "minitest", "~> 5.0" 11 | 12 | gem "standard", "~> 1.3" 13 | -------------------------------------------------------------------------------- /test/dummy/config/boot.rb: -------------------------------------------------------------------------------- 1 | # Set up gems listed in the Gemfile. 2 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../../Gemfile", __dir__) 3 | 4 | require "bundler/setup" if File.exist?(ENV["BUNDLE_GEMFILE"]) 5 | $LOAD_PATH.unshift File.expand_path("../../../lib", __dir__) 6 | -------------------------------------------------------------------------------- /app/controllers/litestream/processes_controller.rb: -------------------------------------------------------------------------------- 1 | module Litestream 2 | class ProcessesController < ApplicationController 3 | # GET /process 4 | def show 5 | @process = Litestream.replicate_process 6 | @databases = Litestream.databases 7 | end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /test/dummy/log/development.log: -------------------------------------------------------------------------------- 1 | [ActionDispatch::HostAuthorization::DefaultResponseApp] Blocked hosts: www.example.com 2 | [ActionDispatch::HostAuthorization::DefaultResponseApp] Blocked hosts: www.example.com 3 | [ActionDispatch::HostAuthorization::DefaultResponseApp] Blocked hosts: www.example.com 4 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "bundler/gem_tasks" 4 | require "rake/testtask" 5 | 6 | Rake::TestTask.new(:test) do |t| 7 | t.libs << "test" 8 | t.libs << "lib" 9 | t.test_files = FileList["test/**/test_*.rb"] 10 | end 11 | 12 | require "standard/rake" 13 | 14 | task default: %i[test standard] 15 | -------------------------------------------------------------------------------- /test/dummy/app/views/layouts/application.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |#{backup}."
15 | end
16 | end
17 | end
18 |
--------------------------------------------------------------------------------
/lib/litestream/engine.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require "rails/engine"
4 |
5 | module Litestream
6 | class Engine < ::Rails::Engine
7 | isolate_namespace Litestream
8 |
9 | config.litestream = ActiveSupport::OrderedOptions.new
10 |
11 | # Load the `litestream:install` generator into the host Rails app
12 | generators do
13 | require_relative "generators/litestream/install_generator"
14 | end
15 |
16 | initializer "litestream.config" do
17 | config.litestream.each do |name, value|
18 | Litestream.public_send(:"#{name}=", value)
19 | end
20 | end
21 |
22 | initializer "deprecator" do |app|
23 | app.deprecators[:litestream] = Litestream.deprecator
24 | end
25 | end
26 | end
27 |
--------------------------------------------------------------------------------
/test/dummy/config/litestream.yml:
--------------------------------------------------------------------------------
1 | # This is the actual configuration file for litestream.
2 | #
3 | # You can either use the generated `config/initializers/litestream.rb`
4 | # file to configure the litestream-ruby gem, which will populate these
5 | # ENV variables when using the `rails litestream:replicate` command.
6 | #
7 | # Or, if you prefer, manually manage ENV variables and this configuration file.
8 | # In that case, simply ensure that the ENV variables are set before running the
9 | # `replicate` command.
10 | #
11 | # For more details, see: https://litestream.io/reference/config/
12 | dbs:
13 | - path: storage/test.sqlite3
14 | replicas:
15 | - type: s3
16 | bucket: $LITESTREAM_REPLICA_BUCKET
17 | path: test
18 | endpoint: http://localhost:9000
19 | access-key-id: $LITESTREAM_ACCESS_KEY_ID
20 | secret-access-key: $LITESTREAM_SECRET_ACCESS_KEY
21 |
--------------------------------------------------------------------------------
/lib/litestream/generators/litestream/install_generator.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require "rails/generators/base"
4 |
5 | module Litestream
6 | module Generators
7 | class InstallGenerator < ::Rails::Generators::Base
8 | source_root File.expand_path("templates", __dir__)
9 |
10 | def copy_config_file
11 | template "config.yml.erb", "config/litestream.yml"
12 | end
13 |
14 | def copy_initializer_file
15 | template "initializer.rb", "config/initializers/litestream.rb"
16 | end
17 |
18 | private
19 |
20 | def production_sqlite_databases
21 | ActiveRecord::Base
22 | .configurations
23 | .configs_for(env_name: "production", include_hidden: true)
24 | .select { |config| ["sqlite3", "litedb"].include? config.adapter }
25 | .map(&:database)
26 | end
27 | end
28 | end
29 | end
30 |
--------------------------------------------------------------------------------
/lib/litestream/generators/litestream/templates/config.yml.erb:
--------------------------------------------------------------------------------
1 | # This is the actual configuration file for litestream.
2 | #
3 | # You can either use the generated `config/initializers/litestream.rb`
4 | # file to configure the litestream-ruby gem, which will populate these
5 | # ENV variables when using the `rails litestream:replicate` command.
6 | #
7 | # Or, if you prefer, manually manage ENV variables and this configuration file.
8 | # In that case, simply ensure that the ENV variables are set before running the
9 | # `replicate` command.
10 | #
11 | # For more details, see: https://litestream.io/reference/config/
12 | dbs:
13 | <%- production_sqlite_databases.each do |database| -%>
14 | - path: <%= database %>
15 | replicas:
16 | - type: s3
17 | bucket: $LITESTREAM_REPLICA_BUCKET
18 | path: <%= database %>
19 | access-key-id: $LITESTREAM_ACCESS_KEY_ID
20 | secret-access-key: $LITESTREAM_SECRET_ACCESS_KEY
21 | <%- end -%>
22 |
--------------------------------------------------------------------------------
/test/dummy/config/locales/en.yml:
--------------------------------------------------------------------------------
1 | # Files in the config/locales directory are used for internationalization and
2 | # are automatically loaded by Rails. If you want to use locales other than
3 | # English, add the necessary files in this directory.
4 | #
5 | # To use the locales, use `I18n.t`:
6 | #
7 | # I18n.t "hello"
8 | #
9 | # In views, this is aliased to just `t`:
10 | #
11 | # <%= t("hello") %>
12 | #
13 | # To use a different locale, set it with `I18n.locale`:
14 | #
15 | # I18n.locale = :es
16 | #
17 | # This would use the information in config/locales/es.yml.
18 | #
19 | # To learn more about the API, please read the Rails Internationalization guide
20 | # at https://guides.rubyonrails.org/i18n.html.
21 | #
22 | # Be aware that YAML interprets the following case-insensitive strings as
23 | # booleans: `true`, `false`, `on`, `off`, `yes`, `no`. Therefore, these strings
24 | # must be quoted to be interpreted as strings. For example:
25 | #
26 | # en:
27 | # "yes": yup
28 | # enabled: "ON"
29 |
30 | en:
31 | hello: "Hello world"
32 |
--------------------------------------------------------------------------------
/test/dummy/bin/setup:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | require "fileutils"
3 |
4 | # path to your application root.
5 | APP_ROOT = File.expand_path("..", __dir__)
6 |
7 | def system!(*args)
8 | system(*args, exception: true)
9 | end
10 |
11 | FileUtils.chdir APP_ROOT do
12 | # This script is a way to set up or update your development environment automatically.
13 | # This script is idempotent, so that you can run it at any time and get an expectable outcome.
14 | # Add necessary setup steps to this file.
15 |
16 | puts "== Installing dependencies =="
17 | system! "gem install bundler --conservative"
18 | system("bundle check") || system!("bundle install")
19 |
20 | # puts "\n== Copying sample files =="
21 | # unless File.exist?("config/database.yml")
22 | # FileUtils.cp "config/database.yml.sample", "config/database.yml"
23 | # end
24 |
25 | puts "\n== Preparing database =="
26 | system! "bin/rails db:prepare"
27 |
28 | puts "\n== Removing old logs and tempfiles =="
29 | system! "bin/rails log:clear tmp:clear"
30 |
31 | puts "\n== Restarting application server =="
32 | system! "bin/rails restart"
33 | end
34 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2023 Stephen Margheim
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/test/dummy/config/database.yml:
--------------------------------------------------------------------------------
1 | # SQLite. Versions 3.8.0 and up are supported.
2 | # gem install sqlite3
3 | #
4 | # Ensure the SQLite 3 gem is defined in your Gemfile
5 | # gem "sqlite3"
6 | #
7 | default: &default
8 | adapter: sqlite3
9 | pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
10 | timeout: 5000
11 |
12 | primary: &primary
13 | <<: *default
14 | database: storage/<%= ENV.fetch("RAILS_ENV", "development") %>.sqlite3
15 |
16 | queue: &queue
17 | <<: *default
18 | migrations_paths: db/queue_migrate
19 | database: storage/queue.sqlite3
20 |
21 | errors: &errors
22 | <<: *default
23 | migrations_paths: db/errors_migrate
24 | database: storage/errors.sqlite3
25 |
26 | development:
27 | primary:
28 | <<: *primary
29 | database: storage/<%= `git branch --show-current`.chomp || 'development' %>.sqlite3
30 | queue: *queue
31 | errors: *errors
32 |
33 | # Warning: The database defined as "test" will be erased and
34 | # re-generated from your development database when you run "rake".
35 | # Do not set this db to the same as development or production.
36 | test:
37 | primary:
38 | <<: *primary
39 | database: db/test.sqlite3
40 | queue:
41 | <<: *queue
42 | database: db/queue.sqlite3
43 | errors:
44 | <<: *errors
45 | database: db/errors.sqlite3
46 |
47 | production:
48 | primary: *primary
49 | queue: *queue
50 | errors: *errors
51 |
--------------------------------------------------------------------------------
/test/controllers/test_processes_controller.rb:
--------------------------------------------------------------------------------
1 | require "test_helper"
2 |
3 | class Litestream::TestProcessesController < ActionDispatch::IntegrationTest
4 | test "should show the process" do
5 | stubbed_process = {pid: "12345", status: "sleeping", started: DateTime.now}
6 | stubbed_databases = [
7 | {"path" => "[ROOT]/storage/test.sqlite3",
8 | "replicas" => "s3",
9 | "generations" => [
10 | {"generation" => SecureRandom.hex,
11 | "name" => "s3",
12 | "lag" => "23h59m59s",
13 | "start" => "2024-05-02T11:32:16Z",
14 | "end" => "2024-05-02T11:33:10Z",
15 | "snapshots" => [
16 | {"index" => "0", "size" => "4145735", "created" => "2024-05-02T11:32:16Z"}
17 | ]}
18 | ]}
19 | ]
20 | Litestream.stub :replicate_process, stubbed_process do
21 | Litestream.stub :databases, stubbed_databases do
22 | get litestream.process_url
23 | assert_response :success
24 |
25 | assert_select "#process_12345", 1 do
26 | assert_select "small", "sleeping"
27 | assert_select "code", "12345"
28 | assert_select "time", stubbed_process[:started].to_formatted_s(:db)
29 | end
30 |
31 | assert_select "#databases li", 1 do
32 | assert_select "h2 code", stubbed_databases[0]["path"]
33 | assert_select "details##{stubbed_databases[0]["generations"][0]["generation"]}"
34 | end
35 | end
36 | end
37 | end
38 | end
39 |
--------------------------------------------------------------------------------
/test/generators/test_install.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require "test_helper"
4 | require "rails/generators"
5 | require "litestream/generators/litestream/install_generator"
6 |
7 | class LitestreamGeneratorTest < Rails::Generators::TestCase
8 | tests Litestream::Generators::InstallGenerator
9 | destination File.expand_path("../tmp", __dir__)
10 |
11 | setup :prepare_destination
12 |
13 | def after_teardown
14 | FileUtils.rm_rf destination_root
15 | super
16 | end
17 |
18 | test "should generate a Litestream configuration file" do
19 | run_generator
20 |
21 | assert_file "config/litestream.yml" do |content|
22 | assert_match "- path: storage/test.sqlite3", content
23 | assert_match "- path: storage/queue.sqlite3", content
24 | assert_match "- path: storage/errors.sqlite3", content
25 | assert_match "bucket: $LITESTREAM_REPLICA_BUCKET", content
26 | assert_match "access-key-id: $LITESTREAM_ACCESS_KEY_ID", content
27 | assert_match "secret-access-key: $LITESTREAM_SECRET_ACCESS_KEY", content
28 | end
29 |
30 | assert_file "config/initializers/litestream.rb" do |content|
31 | assert_match "config.litestream.replica_bucket = litestream_credentials&.replica_bucket", content
32 | assert_match "config.litestream.replica_key_id = litestream_credentials&.replica_key_id", content
33 | assert_match "config.litestream.replica_access_key = litestream_credentials&.replica_access_key", content
34 | end
35 | end
36 | end
37 |
--------------------------------------------------------------------------------
/litestream.gemspec:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative "lib/litestream/version"
4 |
5 | Gem::Specification.new do |spec|
6 | spec.name = "litestream"
7 | spec.version = Litestream::VERSION
8 | spec.authors = ["Stephen Margheim"]
9 | spec.email = ["stephen.margheim@gmail.com"]
10 |
11 | spec.summary = "Integrate Litestream with the RubyGems infrastructure."
12 | spec.homepage = "https://github.com/fractaledmind/litestream-ruby"
13 | spec.license = "MIT"
14 | spec.required_ruby_version = ">= 3.0.0"
15 |
16 | spec.metadata = {
17 | "homepage_uri" => spec.homepage,
18 | "rubygems_mfa_required" => "true",
19 | "source_code_uri" => spec.homepage,
20 | "changelog_uri" => "https://github.com/fractaledmind/litestream-ruby/CHANGELOG.md"
21 | }
22 |
23 | spec.files = Dir["{app,config,lib}/**/*", "LICENSE", "Rakefile", "README.md"]
24 | spec.bindir = "exe"
25 | spec.executables << "litestream"
26 |
27 | # Uncomment to register a new dependency of your gem
28 | spec.add_dependency "sqlite3"
29 | ">= 7.0".tap do |rails_version|
30 | spec.add_dependency "actionpack", rails_version
31 | spec.add_dependency "actionview", rails_version
32 | spec.add_dependency "activejob", rails_version
33 | spec.add_dependency "activesupport", rails_version
34 | spec.add_dependency "railties", rails_version
35 | end
36 | spec.add_development_dependency "rails"
37 | spec.add_development_dependency "rubyzip"
38 |
39 | # For more information and examples about making a new gem, check out our
40 | # guide at: https://bundler.io/guides/creating_gem.html
41 | end
42 |
--------------------------------------------------------------------------------
/test/dummy/config/application.rb:
--------------------------------------------------------------------------------
1 | require_relative "boot"
2 |
3 | require "rails"
4 | # Pick the frameworks you want:
5 | require "active_model/railtie"
6 | # require "active_job/railtie"
7 | require "active_record/railtie"
8 | # require "active_storage/engine"
9 | require "action_controller/railtie"
10 | # require "action_mailer/railtie"
11 | # require "action_mailbox/engine"
12 | # require "action_text/engine"
13 | require "action_view/railtie"
14 | # require "action_cable/engine"
15 | require "rails/test_unit/railtie"
16 |
17 | # Require the gems listed in Gemfile, including any gems
18 | # you've limited to :test, :development, or :production.
19 | Bundler.require(*Rails.groups)
20 |
21 | module Dummy
22 | class Application < Rails::Application
23 | config.load_defaults Rails::VERSION::STRING.to_f
24 |
25 | # For compatibility with applications that use this config
26 | config.action_controller.include_all_helpers = false
27 |
28 | # Please, add to the `ignore` list any other `lib` subdirectories that do
29 | # not contain `.rb` files, or that should not be reloaded or eager loaded.
30 | # Common ones are `templates`, `generators`, or `middleware`, for example.
31 | config.autoload_lib(ignore: %w[assets tasks])
32 |
33 | # Configuration for the application, engines, and railties goes here.
34 | #
35 | # These settings can be overridden in specific environments using the files
36 | # in config/environments, which are processed later.
37 | #
38 | # config.time_zone = "Central Time (US & Canada)"
39 | # config.eager_load_paths << Rails.root.join("extras")
40 | end
41 | end
42 |
--------------------------------------------------------------------------------
/test/dummy/config/puma.rb:
--------------------------------------------------------------------------------
1 | # This configuration file will be evaluated by Puma. The top-level methods that
2 | # are invoked here are part of Puma's configuration DSL. For more information
3 | # about methods provided by the DSL, see https://puma.io/puma/Puma/DSL.html.
4 |
5 | # Puma can serve each request in a thread from an internal thread pool.
6 | # The `threads` method setting takes two numbers: a minimum and maximum.
7 | # Any libraries that use thread pools should be configured to match
8 | # the maximum value specified for Puma. Default is set to 5 threads for minimum
9 | # and maximum; this matches the default thread size of Active Record.
10 | max_threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 }
11 | min_threads_count = ENV.fetch("RAILS_MIN_THREADS") { max_threads_count }
12 | threads min_threads_count, max_threads_count
13 |
14 | # Specifies that the worker count should equal the number of processors in production.
15 | if ENV["RAILS_ENV"] == "production"
16 | require "concurrent-ruby"
17 | worker_count = Integer(ENV.fetch("WEB_CONCURRENCY") { Concurrent.physical_processor_count })
18 | workers worker_count if worker_count > 1
19 | end
20 |
21 | # Specifies the `worker_timeout` threshold that Puma will use to wait before
22 | # terminating a worker in development environments.
23 | worker_timeout 3600 if ENV.fetch("RAILS_ENV", "development") == "development"
24 |
25 | # Specifies the `port` that Puma will listen on to receive requests; default is 3000.
26 | port ENV.fetch("PORT") { 3000 }
27 |
28 | # Specifies the `environment` that Puma will run in.
29 | environment ENV.fetch("RAILS_ENV") { "development" }
30 |
31 | # Specifies the `pidfile` that Puma will use.
32 | pidfile ENV.fetch("PIDFILE") { "tmp/pids/server.pid" }
33 |
34 | # Allow puma to be restarted by `bin/rails restart` command.
35 | plugin :tmp_restart
36 |
--------------------------------------------------------------------------------
/lib/puma/plugin/litestream.rb:
--------------------------------------------------------------------------------
1 | require "puma/plugin"
2 |
3 | # Copied from https://github.com/rails/solid_queue/blob/15408647f1780033dad223d3198761ea2e1e983e/lib/puma/plugin/solid_queue.rb
4 | Puma::Plugin.create do
5 | attr_reader :puma_pid, :litestream_pid, :log_writer
6 |
7 | def start(launcher)
8 | @log_writer = launcher.log_writer
9 | @puma_pid = $$
10 |
11 | launcher.events.on_booted do
12 | @litestream_pid = fork do
13 | Thread.new { monitor_puma }
14 | Litestream::Commands.replicate(async: true)
15 | end
16 |
17 | in_background do
18 | monitor_litestream
19 | end
20 | end
21 |
22 | launcher.events.on_stopped { stop_litestream }
23 | launcher.events.on_restart { stop_litestream }
24 | end
25 |
26 | private
27 |
28 | def stop_litestream
29 | Process.waitpid(litestream_pid, Process::WNOHANG)
30 | log_writer.log "Stopping Litestream..."
31 | Process.kill(:INT, litestream_pid) if litestream_pid
32 | Process.wait(litestream_pid)
33 | rescue Errno::ECHILD, Errno::ESRCH
34 | end
35 |
36 | def monitor_puma
37 | monitor(:puma_dead?, "Detected Puma has gone away, stopping Litestream...")
38 | end
39 |
40 | def monitor_litestream
41 | monitor(:litestream_dead?, "Detected Litestream has gone away, stopping Puma...")
42 | end
43 |
44 | def monitor(process_dead, message)
45 | loop do
46 | if send(process_dead)
47 | log message
48 | Process.kill(:INT, $$)
49 | break
50 | end
51 | sleep 2
52 | end
53 | end
54 |
55 | def litestream_dead?
56 | Process.waitpid(litestream_pid, Process::WNOHANG)
57 | false
58 | rescue Errno::ECHILD, Errno::ESRCH
59 | true
60 | end
61 |
62 | def puma_dead?
63 | Process.ppid != puma_pid
64 | end
65 |
66 | def log(...)
67 | log_writer.log(...)
68 | end
69 | end
70 |
--------------------------------------------------------------------------------
/app/views/layouts/litestream/application.html.erb:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 27 | <%= notice.html_safe %> 28 |
29 | <% end %> 30 | 31 | <% if alert.present? %> 32 |35 | <%= alert.html_safe %> 36 |
37 | <% end %> 38 |<%= @process[:pid] %>
24 |
25 | <% end %>
26 | Total: <%= @databases.size %>
46 |<%= database['path'] %>
54 | <%= generation['generation'] %>
64 | (<%= generation['lag'] %> lag)
65 | | Created at | 89 |Index | 90 |Size | 91 |
|---|---|---|
| 98 | 99 | 100 | 101 | | 102 |103 | <%= snapshot['index'] %> 104 | | 105 |106 | <%= number_to_human_size snapshot['size'] %> 107 | | 108 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
365 | <%= notice %> 366 |
367 | <% end %> 368 | 369 | <% if alert.present? %> 370 |371 | <%= alert %> 372 |
373 | <% end %> 374 |