Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NameError: uninitialized constant ApplicationRecord if having two subtask for DB query #157

Closed
zhongxiao37 opened this issue Mar 15, 2022 · 7 comments
Assignees

Comments

@zhongxiao37
Copy link

Given that ged/ruby-pg#397 is merged, I'm trying to use the async gem with latest ruby-pg in Rails 7. However, it seems that I could not use a database connection to two separated subtasks.

Here is the example:

Error log

Started GET "/async_db" for ::1 at 2022-03-15 23:37:05 +0800
  ActiveRecord::SchemaMigration Pluck (0.7ms)  SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC
Processing by ApplicationController#async_db as HTML
  0.0s    error: Async::Task [oid=0x5ac8] [ec=0x5adc] [pid=45853] [2022-03-15 23:37:05 +0800]
               |   NameError: uninitialized constant ApplicationRecord
               |   Did you mean?  ApplicationJob
               |                  ApplicationHelper
               |   → app/models/user.rb:1 in `<main>'
               |     /Users/pzhong/.rbenv/versions/3.0.3/lib/ruby/gems/3.0.0/gems/bootsnap-1.11.1/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:30 in `require'
               |     /Users/pzhong/.rbenv/versions/3.0.3/lib/ruby/gems/3.0.0/gems/bootsnap-1.11.1/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:30 in `require'
               |     /Users/pzhong/.rbenv/versions/3.0.3/lib/ruby/gems/3.0.0/gems/zeitwerk-2.5.4/lib/zeitwerk/kernel.rb:27 in `require'
               |     app/controllers/application_controller.rb:30 in `block (2 levels) in async_db'
               |     /Users/pzhong/.rbenv/versions/3.0.3/lib/ruby/gems/3.0.0/gems/async-1.30.1/lib/async/task.rb:260 in `block in make_fiber'
["DEBUGGER Exception: /Users/pzhong/.rbenv/versions/3.0.3/lib/ruby/gems/3.0.0/gems/debug-1.4.0/lib/debug/thread_client.rb:986",
 #<RuntimeError: running is given, but running>,
 ["/Users/pzhong/.rbenv/versions/3.0.3/lib/ruby/gems/3.0.0/gems/debug-1.4.0/lib/debug/thread_client.rb:115:in `set_mode'",
  "/Users/pzhong/.rbenv/versions/3.0.3/lib/ruby/gems/3.0.0/gems/debug-1.4.0/lib/debug/thread_client.rb:698:in `wait_next_action_'",
  "/Users/pzhong/.rbenv/versions/3.0.3/lib/ruby/gems/3.0.0/gems/debug-1.4.0/lib/debug/thread_client.rb:676:in `wait_next_action'",
  "/Users/pzhong/.rbenv/versions/3.0.3/lib/ruby/gems/3.0.0/gems/debug-1.4.0/lib/debug/thread_client.rb:201:in `wait_reply'",
  "/Users/pzhong/.rbenv/versions/3.0.3/lib/ruby/gems/3.0.0/gems/debug-1.4.0/lib/debug/thread_client.rb:205:in `on_load'",
  "/Users/pzhong/.rbenv/versions/3.0.3/lib/ruby/gems/3.0.0/gems/debug-1.4.0/lib/debug/session.rb:118:in `block in initialize'",
  "/Users/pzhong/.rbenv/versions/3.0.3/lib/ruby/gems/3.0.0/gems/bootsnap-1.11.1/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:30:in `require'",
  "/Users/pzhong/.rbenv/versions/3.0.3/lib/ruby/gems/3.0.0/gems/bootsnap-1.11.1/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:30:in `require'",
  "/Users/pzhong/.rbenv/versions/3.0.3/lib/ruby/gems/3.0.0/gems/zeitwerk-2.5.4/lib/zeitwerk/kernel.rb:27:in `require'",
  "/Users/pzhong/Documents/github/rails7/app/models/post.rb:1:in `<main>'",
  "/Users/pzhong/.rbenv/versions/3.0.3/lib/ruby/gems/3.0.0/gems/bootsnap-1.11.1/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:30:in `require'",
  "/Users/pzhong/.rbenv/versions/3.0.3/lib/ruby/gems/3.0.0/gems/bootsnap-1.11.1/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:30:in `require'",
  "/Users/pzhong/.rbenv/versions/3.0.3/lib/ruby/gems/3.0.0/gems/zeitwerk-2.5.4/lib/zeitwerk/kernel.rb:27:in `require'",
  "/Users/pzhong/Documents/github/rails7/app/controllers/application_controller.rb:26:in `block (2 levels) in async_db'",
  "/Users/pzhong/.rbenv/versions/3.0.3/lib/ruby/gems/3.0.0/gems/async-1.30.1/lib/async/task.rb:260:in `block in make_fiber'"]]
 0.02s    error: Async::Task [oid=0x5af0] [ec=0x5b04] [pid=45853] [2022-03-15 23:37:05 +0800]
               |   RuntimeError: running is given, but running
               |   → /Users/pzhong/.rbenv/versions/3.0.3/lib/ruby/gems/3.0.0/gems/debug-1.4.0/lib/debug/thread_client.rb:115 in `set_mode'
               |     /Users/pzhong/.rbenv/versions/3.0.3/lib/ruby/gems/3.0.0/gems/debug-1.4.0/lib/debug/thread_client.rb:698 in `wait_next_action_'
               |     /Users/pzhong/.rbenv/versions/3.0.3/lib/ruby/gems/3.0.0/gems/debug-1.4.0/lib/debug/thread_client.rb:676 in `wait_next_action'
               |     /Users/pzhong/.rbenv/versions/3.0.3/lib/ruby/gems/3.0.0/gems/debug-1.4.0/lib/debug/thread_client.rb:201 in `wait_reply'
               |     /Users/pzhong/.rbenv/versions/3.0.3/lib/ruby/gems/3.0.0/gems/debug-1.4.0/lib/debug/thread_client.rb:205 in `on_load'
               |     /Users/pzhong/.rbenv/versions/3.0.3/lib/ruby/gems/3.0.0/gems/debug-1.4.0/lib/debug/session.rb:118 in `block in initialize'
               |     /Users/pzhong/.rbenv/versions/3.0.3/lib/ruby/gems/3.0.0/gems/bootsnap-1.11.1/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:30 in `require'
               |     /Users/pzhong/.rbenv/versions/3.0.3/lib/ruby/gems/3.0.0/gems/bootsnap-1.11.1/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:30 in `require'
               |     /Users/pzhong/.rbenv/versions/3.0.3/lib/ruby/gems/3.0.0/gems/zeitwerk-2.5.4/lib/zeitwerk/kernel.rb:27 in `require'
               |     app/models/post.rb:1 in `<main>'
               |     /Users/pzhong/.rbenv/versions/3.0.3/lib/ruby/gems/3.0.0/gems/bootsnap-1.11.1/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:30 in `require'
               |     /Users/pzhong/.rbenv/versions/3.0.3/lib/ruby/gems/3.0.0/gems/bootsnap-1.11.1/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:30 in `require'
               |     /Users/pzhong/.rbenv/versions/3.0.3/lib/ruby/gems/3.0.0/gems/zeitwerk-2.5.4/lib/zeitwerk/kernel.rb:27 in `require'
               |     app/controllers/application_controller.rb:26 in `block (2 levels) in async_db'
               |     /Users/pzhong/.rbenv/versions/3.0.3/lib/ruby/gems/3.0.0/gems/async-1.30.1/lib/async/task.rb:260 in `block in make_fiber'
Completed 200 OK in 514ms (Views: 0.6ms | ActiveRecord: 0.0ms | Allocations: 6158)

app/models/post.rb

class Post < ApplicationRecord
end

app/models/user.rb

class User < ApplicationRecord
end

app/controllers/application_controller.rb

class ApplicationController < ActionController::Base
  def async_db
    users = []
    posts = []
    task = Async do |t|
      t.async do
        sleep(0.5)
      end

      t.async do
        posts << Post.find_by(user_id: rand(1..1000000))
      end

      t.async do
        users << User.find_by(id: rand(1..1000000))
      end
    end

    task.wait
    render json: { users: users.map(&:name), posts: posts.map(&:title) }
  end
end

Gemfile

source "https://rubygems.org"
git_source(:github) { |repo| "https://github.com/#{repo}.git" }

ruby "3.0.3"

# Bundle edge Rails instead: gem "rails", github: "rails/rails", branch: "main"
gem "rails", "~> 7.0.2.2"

# The original asset pipeline for Rails [https://github.com/rails/sprockets-rails]
gem "sprockets-rails", ">= 3.4.1"

# Use sqlite3 as the database for Active Record
gem "pg"

# Use the Puma web server [https://github.com/puma/puma]
gem "puma", "~> 5.0"

# Use JavaScript with ESM import maps [https://github.com/rails/importmap-rails]
gem "importmap-rails", ">= 0.9.2"

# Hotwire's SPA-like page accelerator [https://turbo.hotwired.dev]
gem "turbo-rails", ">= 0.9.0"

# Hotwire's modest JavaScript framework [https://stimulus.hotwired.dev]
gem "stimulus-rails", ">= 0.7.3"

# Build JSON APIs with ease [https://github.com/rails/jbuilder]
gem "jbuilder", "~> 2.11"

# Use Redis adapter to run Action Cable in production
gem "redis", "~> 4.0"

# Use Kredis to get higher-level data types in Redis [https://github.com/rails/kredis]
# gem "kredis"

# Use Active Model has_secure_password [https://guides.rubyonrails.org/active_model_basics.html#securepassword]
# gem "bcrypt", "~> 3.1.7"

# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
gem "tzinfo-data", platforms: %i[ mingw mswin x64_mingw jruby ]

# Reduces boot times through caching; required in config/boot.rb
gem "bootsnap", ">= 1.4.4", require: false
gem 'slim'
gem "async", "~> 1.30"

# Use Sass to process CSS
# gem "sassc-rails", "~> 2.1"

# Use Active Storage variants [https://guides.rubyonrails.org/active_storage_overview.html#transforming-images]
# gem "image_processing", "~> 1.2"

group :development, :test do
  # See https://edgeguides.rubyonrails.org/debugging_rails_applications.html#debugging-with-the-debug-gem
  gem "debug", ">= 1.0.0", platforms: %i[ mri mingw x64_mingw ]
  gem 'debase'
  gem 'rubocop-rails'
  gem 'ruby-debug-ide'
end

group :development do
  # Use console on exceptions pages [https://github.com/rails/web-console]
  gem "web-console", ">= 4.1.0"

  # Add speed badges [https://github.com/MiniProfiler/rack-mini-profiler]
  # gem "rack-mini-profiler", ">= 2.3.3"

  # Speed up commands on slow machines / big apps [https://github.com/rails/spring]
  # gem "spring"
end

group :test do
  # Use system testing [https://guides.rubyonrails.org/testing.html#system-testing]
  gem "capybara", ">= 3.26"
  gem "selenium-webdriver", ">= 4.0.0"
  gem "webdrivers"
end

Gemfile.lock

GEM
  remote: https://rubygems.org/
  specs:
    actioncable (7.0.2.2)
      actionpack (= 7.0.2.2)
      activesupport (= 7.0.2.2)
      nio4r (~> 2.0)
      websocket-driver (>= 0.6.1)
    actionmailbox (7.0.2.2)
      actionpack (= 7.0.2.2)
      activejob (= 7.0.2.2)
      activerecord (= 7.0.2.2)
      activestorage (= 7.0.2.2)
      activesupport (= 7.0.2.2)
      mail (>= 2.7.1)
      net-imap
      net-pop
      net-smtp
    actionmailer (7.0.2.2)
      actionpack (= 7.0.2.2)
      actionview (= 7.0.2.2)
      activejob (= 7.0.2.2)
      activesupport (= 7.0.2.2)
      mail (~> 2.5, >= 2.5.4)
      net-imap
      net-pop
      net-smtp
      rails-dom-testing (~> 2.0)
    actionpack (7.0.2.2)
      actionview (= 7.0.2.2)
      activesupport (= 7.0.2.2)
      rack (~> 2.0, >= 2.2.0)
      rack-test (>= 0.6.3)
      rails-dom-testing (~> 2.0)
      rails-html-sanitizer (~> 1.0, >= 1.2.0)
    actiontext (7.0.2.2)
      actionpack (= 7.0.2.2)
      activerecord (= 7.0.2.2)
      activestorage (= 7.0.2.2)
      activesupport (= 7.0.2.2)
      globalid (>= 0.6.0)
      nokogiri (>= 1.8.5)
    actionview (7.0.2.2)
      activesupport (= 7.0.2.2)
      builder (~> 3.1)
      erubi (~> 1.4)
      rails-dom-testing (~> 2.0)
      rails-html-sanitizer (~> 1.1, >= 1.2.0)
    activejob (7.0.2.2)
      activesupport (= 7.0.2.2)
      globalid (>= 0.3.6)
    activemodel (7.0.2.2)
      activesupport (= 7.0.2.2)
    activerecord (7.0.2.2)
      activemodel (= 7.0.2.2)
      activesupport (= 7.0.2.2)
    activestorage (7.0.2.2)
      actionpack (= 7.0.2.2)
      activejob (= 7.0.2.2)
      activerecord (= 7.0.2.2)
      activesupport (= 7.0.2.2)
      marcel (~> 1.0)
      mini_mime (>= 1.1.0)
    activesupport (7.0.2.2)
      concurrent-ruby (~> 1.0, >= 1.0.2)
      i18n (>= 1.6, < 2)
      minitest (>= 5.1)
      tzinfo (~> 2.0)
    addressable (2.8.0)
      public_suffix (>= 2.0.2, < 5.0)
    ast (2.4.2)
    async (1.30.1)
      console (~> 1.10)
      nio4r (~> 2.3)
      timers (~> 4.1)
    bindex (0.8.1)
    bootsnap (1.11.1)
      msgpack (~> 1.2)
    builder (3.2.4)
    capybara (3.36.0)
      addressable
      matrix
      mini_mime (>= 0.1.3)
      nokogiri (~> 1.8)
      rack (>= 1.6.0)
      rack-test (>= 0.6.3)
      regexp_parser (>= 1.5, < 3.0)
      xpath (~> 3.2)
    childprocess (4.1.0)
    concurrent-ruby (1.1.9)
    console (1.14.0)
      fiber-local
    crass (1.0.6)
    debase (0.2.4.1)
      debase-ruby_core_source (>= 0.10.2)
    debase-ruby_core_source (0.10.14)
    debug (1.4.0)
      irb (>= 1.3.6)
      reline (>= 0.2.7)
    digest (3.1.0)
    erubi (1.10.0)
    fiber-local (1.0.0)
    globalid (1.0.0)
      activesupport (>= 5.0)
    i18n (1.10.0)
      concurrent-ruby (~> 1.0)
    importmap-rails (1.0.3)
      actionpack (>= 6.0.0)
      railties (>= 6.0.0)
    io-console (0.5.11)
    io-wait (0.2.1)
    irb (1.4.1)
      reline (>= 0.3.0)
    jbuilder (2.11.5)
      actionview (>= 5.0.0)
      activesupport (>= 5.0.0)
    loofah (2.14.0)
      crass (~> 1.0.2)
      nokogiri (>= 1.5.9)
    mail (2.7.1)
      mini_mime (>= 0.1.1)
    marcel (1.0.2)
    matrix (0.4.2)
    method_source (1.0.0)
    mini_mime (1.1.2)
    minitest (5.15.0)
    msgpack (1.4.5)
    net-imap (0.2.3)
      digest
      net-protocol
      strscan
    net-pop (0.1.1)
      digest
      net-protocol
      timeout
    net-protocol (0.1.2)
      io-wait
      timeout
    net-smtp (0.3.1)
      digest
      net-protocol
      timeout
    nio4r (2.5.8)
    nokogiri (1.13.3-x86_64-darwin)
      racc (~> 1.4)
    parallel (1.21.0)
    parser (3.1.1.0)
      ast (~> 2.4.1)
    pg (1.3.4)
    public_suffix (4.0.6)
    puma (5.6.2)
      nio4r (~> 2.0)
    racc (1.6.0)
    rack (2.2.3)
    rack-test (1.1.0)
      rack (>= 1.0, < 3)
    rails (7.0.2.2)
      actioncable (= 7.0.2.2)
      actionmailbox (= 7.0.2.2)
      actionmailer (= 7.0.2.2)
      actionpack (= 7.0.2.2)
      actiontext (= 7.0.2.2)
      actionview (= 7.0.2.2)
      activejob (= 7.0.2.2)
      activemodel (= 7.0.2.2)
      activerecord (= 7.0.2.2)
      activestorage (= 7.0.2.2)
      activesupport (= 7.0.2.2)
      bundler (>= 1.15.0)
      railties (= 7.0.2.2)
    rails-dom-testing (2.0.3)
      activesupport (>= 4.2.0)
      nokogiri (>= 1.6)
    rails-html-sanitizer (1.4.2)
      loofah (~> 2.3)
    railties (7.0.2.2)
      actionpack (= 7.0.2.2)
      activesupport (= 7.0.2.2)
      method_source
      rake (>= 12.2)
      thor (~> 1.0)
      zeitwerk (~> 2.5)
    rainbow (3.1.1)
    rake (13.0.6)
    redis (4.6.0)
    regexp_parser (2.2.1)
    reline (0.3.1)
      io-console (~> 0.5)
    rexml (3.2.5)
    rubocop (1.26.0)
      parallel (~> 1.10)
      parser (>= 3.1.0.0)
      rainbow (>= 2.2.2, < 4.0)
      regexp_parser (>= 1.8, < 3.0)
      rexml
      rubocop-ast (>= 1.16.0, < 2.0)
      ruby-progressbar (~> 1.7)
      unicode-display_width (>= 1.4.0, < 3.0)
    rubocop-ast (1.16.0)
      parser (>= 3.1.1.0)
    rubocop-rails (2.14.0)
      activesupport (>= 4.2.0)
      rack (>= 1.1)
      rubocop (>= 1.7.0, < 2.0)
    ruby-debug-ide (0.7.3)
      rake (>= 0.8.1)
    ruby-progressbar (1.11.0)
    rubyzip (2.3.2)
    selenium-webdriver (4.1.0)
      childprocess (>= 0.5, < 5.0)
      rexml (~> 3.2, >= 3.2.5)
      rubyzip (>= 1.2.2)
    slim (4.1.0)
      temple (>= 0.7.6, < 0.9)
      tilt (>= 2.0.6, < 2.1)
    sprockets (4.0.3)
      concurrent-ruby (~> 1.0)
      rack (> 1, < 3)
    sprockets-rails (3.4.2)
      actionpack (>= 5.2)
      activesupport (>= 5.2)
      sprockets (>= 3.0.0)
    stimulus-rails (1.0.4)
      railties (>= 6.0.0)
    strscan (3.0.1)
    temple (0.8.2)
    thor (1.2.1)
    tilt (2.0.10)
    timeout (0.2.0)
    timers (4.3.3)
    turbo-rails (1.0.1)
      actionpack (>= 6.0.0)
      railties (>= 6.0.0)
    tzinfo (2.0.4)
      concurrent-ruby (~> 1.0)
    unicode-display_width (2.1.0)
    web-console (4.2.0)
      actionview (>= 6.0.0)
      activemodel (>= 6.0.0)
      bindex (>= 0.4.0)
      railties (>= 6.0.0)
    webdrivers (5.0.0)
      nokogiri (~> 1.6)
      rubyzip (>= 1.3.0)
      selenium-webdriver (~> 4.0)
    websocket-driver (0.7.5)
      websocket-extensions (>= 0.1.0)
    websocket-extensions (0.1.5)
    xpath (3.2.0)
      nokogiri (~> 1.8)
    zeitwerk (2.5.4)

PLATFORMS
  x86_64-darwin-20

DEPENDENCIES
  async (~> 1.30)
  bootsnap (>= 1.4.4)
  capybara (>= 3.26)
  debase
  debug (>= 1.0.0)
  importmap-rails (>= 0.9.2)
  jbuilder (~> 2.11)
  pg
  puma (~> 5.0)
  rails (~> 7.0.2.2)
  redis (~> 4.0)
  rubocop-rails
  ruby-debug-ide
  selenium-webdriver (>= 4.0.0)
  slim
  sprockets-rails (>= 3.4.1)
  stimulus-rails (>= 0.7.3)
  turbo-rails (>= 0.9.0)
  tzinfo-data
  web-console (>= 4.1.0)
  webdrivers

RUBY VERSION
   ruby 3.0.3p157

BUNDLED WITH
   2.2.32

Notes

If I change them in one subtask, it will work well.

app/controllers/application_controller.rb

class ApplicationController < ActionController::Base

  def async_db
    users = []
    posts = []
    task = Async do |t|
      t.async do
        sleep(0.5)
      end

      t.async do
        posts << Post.find_by(user_id: rand(1..1000000))
        users << User.find_by(id: rand(1..1000000))
      end
    end

    task.wait
    render json: { users: users.map(&:name), posts: posts.map(&:title) }
  end
end
@ioquatix
Copy link
Member

Do you think it's load issue? make something wrong with Zeitwerk. Can you try adding require 'application_record' or some variation of that before the db model uses it?

@fxn
Copy link

fxn commented Mar 24, 2022

Can you reproduce with the debug gem commented out?

@pbstriker38
Copy link

We also run across this issue with any class that we use in subtasks. Only on the first request, the second request will have the class loaded.

@pbstriker38
Copy link

Commenting out the debug gem does appear to have solved it 👍

@ioquatix
Copy link
Member

ioquatix commented Apr 7, 2022

We have some issues with autoloading in Ruby 3.1.1 and I will try to back port a fix for Ruby 3.1.2 if possible. A solution is to disable autoloading where possible.

@ioquatix ioquatix self-assigned this Apr 7, 2022
@ioquatix
Copy link
Member

ioquatix commented Apr 11, 2022

I'm proposing a fix here ruby/ruby#5788

@ioquatix
Copy link
Member

ioquatix commented Oct 31, 2022

This bug is fixed and will be released in Ruby 3.2. Sorry about that and thanks for your patience. If you want to help further, please retry your test case with the latest async on Ruby head.

jeromepl added a commit to jeromepl/rails-react-server-components-demo that referenced this issue Nov 26, 2023
Causes an issue in Ruby < 3.2: socketry/async#157
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants