Railtie not loading
I've added Falcon to the Rails TechEmpower benchmark: https://github.com/TechEmpower/FrameworkBenchmarks/pull/9339
I had to set the isolation_level to :fiber by hand to make it work.
https://github.com/p8/FrameworkBenchmarks/blob/f7822a3d79689164e372fba05be4ee744b1f42a4/frameworks/Ruby/rails/config/application.rb#L55
Otherwise the following error would occur:
$ ./tfb --test rails-falcon --mode verify
...
rails-falcon: {"time":"2024-10-23T08:13:36+00:00","severity":"error","oid":3416,"pid":18,"subject":"Protocol::Rack::Adapter::Rack3","annotation":"Reading HTTP/1.1 requests for Async::HTTP::Protocol::HTTP1::Server.","event":{"type":"failure","root":"/rails","class":"NoMethodError","message":"\u001b[1mundefined method 'map_types!' for nil (\u001b[1;4mNoMethodError\u001b[m\u001b[1m)\u001b[m\n\n\u001b[1m result = conn.async_exec(sql).map_types!(@type_map_for_results).values\u001b[m\n\u001b[1m ^^^^^^^^^^^\u001b[m","backtrace":
["/usr/local/bundle/gems/activerecord-7.2.1.1/lib/active_record/connection_adapters/postgresql/database_statements.rb:19:in 'block (2 levels) in ActiveRecord::ConnectionAdapters::PostgreSQL::DatabaseStatements#query'",
"/usr/local/bundle/gems/activerecord-7.2.1.1/lib/active_record/connection_adapters/abstract_adapter.rb:1004:in 'block in ActiveRecord::ConnectionAdapters::AbstractAdapter#with_raw_connection'",
"/usr/local/bundle/gems/activesupport-7.2.1.1/lib/active_support/concurrency/null_lock.rb:9:in 'ActiveSupport::Concurrency::NullLock#synchronize'",
"/usr/local/bundle/gems/activerecord-7.2.1.1/lib/active_record/connection_adapters/abstract_adapter.rb:976:in 'ActiveRecord::ConnectionAdapters::AbstractAdapter#with_raw_connection'",
"/usr/local/bundle/gems/activerecord-7.2.1.1/lib/active_record/connection_adapters/postgresql/database_statements.rb:18:in 'block in ActiveRecord::ConnectionAdapters::PostgreSQL::DatabaseStatements#query'",
"/usr/local/bundle/gems/activesupport-7.2.1.1/lib/active_support/notifications/instrumenter.rb:58:in 'ActiveSupport::Notifications::Instrumenter#instrument'",
"/usr/local/bundle/gems/activerecord-7.2.1.1/lib/active_record/connection_adapters/abstract_adapter.rb:1119:in 'ActiveRecord::ConnectionAdapters::AbstractAdapter#log'",
"/usr/local/bundle/gems/activerecord-7.2.1.1/lib/active_record/connection_adapters/postgresql/database_statements.rb:17:in 'ActiveRecord::ConnectionAdapters::PostgreSQL::DatabaseStatements#query'",
"/usr/local/bundle/gems/activerecord-7.2.1.1/lib/active_record/connection_adapters/abstract/database_statements.rb:110:in 'ActiveRecord::ConnectionAdapters::DatabaseStatements#query_values'",
"/usr/local/bundle/gems/activerecord-7.2.1.1/lib/active_record/connection_adapters/abstract/schema_statements.rb:35:in 'ActiveRecord::ConnectionAdapters::SchemaStatements#data_sources'"
I wonder if it's load order dependent?
https://github.com/socketry/falcon/blob/main/lib/falcon.rb#L10
Yes, it could be that Rails isn't loaded there yet.
I wonder what the best strategy would be, e.g.
begin
require 'railtie'
...
rescue LoadError
# Ignore
end
I just hit this issue trying falcon in a new rails app:
$ bundle remove puma
$ bundle add falcon falcon-rails
$ rails s
Bundler::Runtime#require': There was an error while trying to load the gem 'falcon'. (Bundler::GemRequireError)
Gem Load Error is: uninitialized constant Falcon::Rails::Railtie
bundle exec falcon serve -b http://localhost:3000 seem to work ok, I guess I'll use that 😅
This worked for me:
samuel@Sakura ~/D/tmp> rails new myproject
create
create README.md
create Rakefile
create .ruby-version
create config.ru
create .gitignore
create .gitattributes
create Gemfile
run git init from "."
Initialized empty Git repository in /Users/samuel/Developer/tmp/myproject/.git/
create app
create app/assets/stylesheets/application.css
create app/controllers/application_controller.rb
create app/helpers/application_helper.rb
create app/jobs/application_job.rb
create app/mailers/application_mailer.rb
create app/models/application_record.rb
create app/views/layouts/application.html.erb
create app/views/layouts/mailer.html.erb
create app/views/layouts/mailer.text.erb
create app/views/pwa/manifest.json.erb
create app/views/pwa/service-worker.js
create app/assets/images
create app/assets/images/.keep
create app/controllers/concerns/.keep
create app/models/concerns/.keep
create bin
create bin/brakeman
create bin/dev
create bin/rails
create bin/rake
create bin/rubocop
create bin/setup
create bin/thrust
create Dockerfile
create .dockerignore
create bin/docker-entrypoint
create .rubocop.yml
create .github/workflows
create .github/workflows/ci.yml
create .github/dependabot.yml
create config
create config/routes.rb
create config/application.rb
create config/environment.rb
create config/cable.yml
create config/puma.rb
create config/storage.yml
create config/environments
create config/environments/development.rb
create config/environments/production.rb
create config/environments/test.rb
create config/initializers
create config/initializers/assets.rb
create config/initializers/content_security_policy.rb
create config/initializers/cors.rb
create config/initializers/filter_parameter_logging.rb
create config/initializers/inflections.rb
create config/initializers/new_framework_defaults_8_0.rb
create config/locales
create config/locales/en.yml
create config/master.key
append .gitignore
create config/boot.rb
create config/database.yml
create db
create db/seeds.rb
create lib
create lib/tasks
create lib/tasks/.keep
create log
create log/.keep
create public
create public/400.html
create public/404.html
create public/406-unsupported-browser.html
create public/422.html
create public/500.html
create public/icon.png
create public/icon.svg
create public/robots.txt
create script
create script/.keep
create tmp
create tmp/.keep
create tmp/pids
create tmp/pids/.keep
create vendor
create vendor/.keep
create test/fixtures/files
create test/fixtures/files/.keep
create test/controllers
create test/controllers/.keep
create test/mailers
create test/mailers/.keep
create test/models
create test/models/.keep
create test/helpers
create test/helpers/.keep
create test/integration
create test/integration/.keep
create test/test_helper.rb
create test/system
create test/system/.keep
create test/application_system_test_case.rb
create storage
create storage/.keep
create tmp/storage
create tmp/storage/.keep
remove config/initializers/cors.rb
remove config/initializers/new_framework_defaults_8_0.rb
run bundle install --quiet
run bundle lock --add-platform=x86_64-linux
Writing lockfile to /Users/samuel/Developer/tmp/myproject/Gemfile.lock
run bundle lock --add-platform=aarch64-linux
Writing lockfile to /Users/samuel/Developer/tmp/myproject/Gemfile.lock
run bundle binstubs bundler
rails importmap:install
apply /Users/samuel/.gem/ruby/3.4.5/gems/importmap-rails-2.2.2/lib/install/install.rb
Add Importmap include tags in application layout
insert app/views/layouts/application.html.erb
Create application.js module as entrypoint
create app/javascript/application.js
Use vendor/javascript for downloaded pins
create vendor/javascript
create vendor/javascript/.keep
Configure importmap paths in config/importmap.rb
create config/importmap.rb
Copying binstub
create bin/importmap
run bundle install --quiet
rails turbo:install stimulus:install
apply /Users/samuel/.gem/ruby/3.4.5/gems/turbo-rails-2.0.17/lib/install/turbo_with_importmap.rb
Import Turbo
append app/javascript/application.js
Pin Turbo
append config/importmap.rb
run bundle install --quiet
apply /Users/samuel/.gem/ruby/3.4.5/gems/stimulus-rails-1.3.4/lib/install/stimulus_with_importmap.rb
Create controllers directory
create app/javascript/controllers
create app/javascript/controllers/index.js
create app/javascript/controllers/application.js
create app/javascript/controllers/hello_controller.js
Import Stimulus controllers
append app/javascript/application.js
Pin Stimulus
Appending: pin "@hotwired/stimulus", to: "stimulus.min.js"
append config/importmap.rb
Appending: pin "@hotwired/stimulus-loading", to: "stimulus-loading.js"
append config/importmap.rb
Pin all controllers
Appending: pin_all_from "app/javascript/controllers", under: "controllers"
append config/importmap.rb
run bundle install --quiet
run bundle binstubs kamal
run bundle exec kamal init
Created configuration file in config/deploy.yml
Created .kamal/secrets file
Created sample hooks in .kamal/hooks
force .kamal/secrets
force config/deploy.yml
rails solid_cache:install solid_queue:install solid_cable:install
create config/cache.yml
create db/cache_schema.rb
gsub config/environments/production.rb
create config/queue.yml
create config/recurring.yml
create db/queue_schema.rb
create bin/jobs
gsub config/environments/production.rb
create db/cable_schema.rb
force config/cable.yml
samuel@Sakura ~/D/tmp> cd myproject/
samuel@Sakura ~/D/t/myproject (main)> bundle remove puma
Removing gems from /Users/samuel/Developer/tmp/myproject/Gemfile
puma (>= 5.0) was removed.
samuel@Sakura ~/D/t/myproject (main)> bundle add falcon falcon-rails
Fetching gem metadata from https://rubygems.org/.........
Resolving dependencies...
Fetching gem metadata from https://rubygems.org/.........
Fetching async 2.34.0
Installing async 2.34.0
samuel@Sakura ~/D/t/myproject (main)> rails s
=> Booting Falcon v0.52.3
=> Rails 8.0.3 application starting in development http://localhost:3000
=> Run `bin/rails server --help` for more startup options
0.72s info: process_action.action_controller: Reading HTTP/1.1 requests for Async::HTTP::Protocol::HTTP1::Server. [ec=0x1c90] [pid=14409] [2025-10-09 10:37:49 +1300]
| {
| "controller": "Rails::WelcomeController",
| "action": "index",
| "format": "html",
| "method": "GET",
| "path": "/",
| "status": 200,
| "view_runtime": 7.287999987602234,
| "db_runtime": 0.0,
| "queries_count": 0,
| "cached_queries_count": 0,
| "source_address": "::1",
| "allocations": 26150,
| "duration": 56.728999972343445
| }
Are you able to try that and let me know if there is something different between our systems?
Huh! It works... and now I can't replicate it in my other project either. Sorry for the false alarm, looks like it was some kind of gem-loading gremlins on my end. Don't feed them after midnight! 😅