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

Wrap possible autoloaded models in interlock loading #730

Merged

Conversation

jrafanie
Copy link
Member

Since we don't eager load the models that could be loaded here, we need to wrap
these calls in the interlock loading to ensure rails' interlock knows we're
loading code in this block, so two threads don't try to autoload at the same
time.

Fixes timing issues resulting in errors of the variety:

LoadError (Unable to autoload constant ManageIQ::Providers::Openstack::StorageManager::CinderManager, expected /home/mmarosi/.rbenv/versions/2.5.3/lib/ruby/gems/2.5.0/bundler/gems/manageiq-providers-openstack-4481f21d2ebe/app/models/manageiq/providers/openstack/storage_manager/cinder_manager.rb to define it)

Fixes ManageIQ/manageiq#19772

In that issue, we had 3 requests happen in 3 threads at the same time:

[----] I, [2020-01-28T16:39:43.358817 #6310:3fd8bc363880]  INFO -- : Started GET "/ems_cloud/ems_cloud_form_fields/new" for ::1 at 2020-01-28 16:39:43 -0500
[----] I, [2020-01-28T16:39:43.394484 #6310:3fd8bc363754]  INFO -- : Started OPTIONS "/api/providers" for ::1 at 2020-01-28 16:39:43 -0500
[----] I, [2020-01-28T16:39:43.690661 #6310:3fd8bc3633a8]  INFO -- : Started OPTIONS "/api/providers" for ::1 at 2020-01-28 16:39:43 -0500

We were able to reduce that issue to this recreation script run locally against rails server:

threads = []
threads << Thread.new do
  `curl -k -L -u admin:smartvm -i -X GET http://localhost:3000/ems_cloud/ems_cloud_form_fields/new`
end

2.times do
  threads << Thread.new do
    `curl -k -L -u admin:smartvm -i -X OPTIONS http://localhost:3000/api/providers`
  end
end

threads.join

Since we don't eager load the models that could be loaded here, we need to wrap
these calls in the interlock loading to ensure rails' interlock knows we're
loading code in this block, so two threads don't try to autoload at the same
time.

Fixes timing issues resulting in errors of the variety:

```
LoadError (Unable to autoload constant ManageIQ::Providers::Openstack::StorageManager::CinderManager, expected /home/mmarosi/.rbenv/versions/2.5.3/lib/ruby/gems/2.5.0/bundler/gems/manageiq-providers-openstack-4481f21d2ebe/app/models/manageiq/providers/openstack/storage_manager/cinder_manager.rb to define it)
```

Fixes ManageIQ/manageiq#19772

In that issue, we had 3 requests happen in 3 threads at the same time:
```
[----] I, [2020-01-28T16:39:43.358817 #6310:3fd8bc363880]  INFO -- : Started GET "/ems_cloud/ems_cloud_form_fields/new" for ::1 at 2020-01-28 16:39:43 -0500
[----] I, [2020-01-28T16:39:43.394484 #6310:3fd8bc363754]  INFO -- : Started OPTIONS "/api/providers" for ::1 at 2020-01-28 16:39:43 -0500
[----] I, [2020-01-28T16:39:43.690661 #6310:3fd8bc3633a8]  INFO -- : Started OPTIONS "/api/providers" for ::1 at 2020-01-28 16:39:43 -0500
```

We were able to reduce that issue to this recreation script run locally against `rails
server`:

```ruby
threads = []
threads << Thread.new do
  `curl -k -L -u admin:smartvm -i -X GET http://localhost:3000/ems_cloud/ems_cloud_form_fields/new`
end

2.times do
  threads << Thread.new do
    `curl -k -L -u admin:smartvm -i -X OPTIONS http://localhost:3000/api/providers`
  end
end

threads.join
```
@jrafanie jrafanie added the bug label Jan 29, 2020
@jrafanie
Copy link
Member Author

Note, I don't know how to test this. The method is already tested and testing race conditions leaves me in the pits. 🏎

@miq-bot
Copy link
Member

miq-bot commented Jan 29, 2020

Checked commit jrafanie@6f602dc with ruby 2.5.5, rubocop 0.69.0, haml-lint 0.20.0, and yamllint 1.10.0
1 file checked, 0 offenses detected
Everything looks fine. 🍪

@agrare
Copy link
Member

agrare commented Jan 30, 2020

It feels like we could be playing whack-a-mole with any code that could possibly load a model and could possibly be run from a thread :/ I guess that is relatively rare but I'd be surprised if this didn't also happen somewhere in ui-classic?

Copy link
Member

@agrare agrare left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 this fixes a definite known issue, we might want to look at more general solutions in the future

agrare added a commit that referenced this pull request Jan 30, 2020
…_loading

Wrap possible autoloaded models in interlock loading
@agrare agrare merged commit 6f602dc into ManageIQ:master Jan 30, 2020
@agrare agrare self-assigned this Jan 30, 2020
@agrare agrare added this to the Sprint 129 Ending Feb 3, 2020 milestone Jan 30, 2020
@agrare
Copy link
Member

agrare commented Jan 30, 2020

@miq-bot add-label constant problem

@miq-bot
Copy link
Member

miq-bot commented Jan 30, 2020

@agrare Cannot apply the following label because they are not recognized: constant problem

@jrafanie jrafanie deleted the wrap_autoloading_with_interlock_loading branch January 30, 2020 15:25
@Fryguy
Copy link
Member

Fryguy commented Jan 30, 2020

@agrare These constant problems will probably go away with Rails 6 and zeitwerk

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

LoadError Unable to autoload constant ManageIQ::Providers::Openstack
4 participants