Prior to this update, the deploy button on the deploy confirmation form allowed multiple deploy requests to be sent to the server. Any subsequent requests would encounter the ForemanTask lock.
Consequently, any subsequent deploy requests would fail with the exception "ForemanTask::Lock::Conflict".
This fix disables the deploy button after the first click. In addition, the route has been changed to use HTTP POST rather than GET, in order to avoid occurrences resulting from navigating to the /deploy url.
The result is that the "ForemanTask::Lock::Conflict" exception no longer occurs when the deploy button is clicked multiple times.
commit 17e152bc3cd22e5fda88a996a47d7dfcd6d99593
Author: Martyn Taylor <mtaylor>
Date: Wed May 14 13:16:54 2014 +0100
Disable multiple deploy submissions on deploy form
This patch disables the deploy button on the deploy form after it has
been clicked once. This prevents multiple submits being sent by the
same form. The patch also changes the deploy route to POST to avoid the
user accidently submitting deploy when navigating to /deploy.
[Rubygem-Staypuft]: Clicking twice on 'Deploy' button produces Error page. (Warning! required lock conflicts wiht #<ForemanTasks) Environment (puddle : OpenStack/Foreman/2014-05-06.6/) ------------------------------------------------------- ruby193-rubygem-staypuft-0.0.12-1.el6ost.noarch foreman-installer-staypuft-0.0.10-1.el6ost.noarch openstack-puppet-modules-2013.2-9.1.el6ost.noarch puppet-server-3.3.2-2.el6.noarch puppet-3.3.2-2.el6.noarch foreman-1.5.0.22-1.el6sat.noarch Steps: ------- (1) Associate Discovered hosts with Host-Groups. (2) Click on the Deploy button --> will transfer to window with "This action will initiate the deployment of <deployment-name>. (3) On that page click on the 'Deploy' button Twice. * Sometimes it's takes some process-time after the first click on 'deploy', in that case the user might click again on deploy and get the error page. Results: --------- - Error page Displaying the following: Warning! required lock: #<ForemanTasks::Lock:0x007f2558c36f98> conflicts wiht [#<ForemanTasks::Lock id: 8, task_id: "3fc09e69-e60f-4168-bd38-edf625bb7c0f", name: "deploy", resource_type: "Staypuft::Deployment", resource_id: 6, exclusive: true>] production.log (Attached) : ----------------------------- Started GET "/deployments/6/deploy" for 10.36.5.212 at 2014-05-12 23:42:51 +0300 Processing by Staypuft::DeploymentsController#deploy as HTML Parameters: {"id"=>"6"} required lock: #<ForemanTasks::Lock:0x007f2558c36f98> conflicts wiht [#<ForemanTasks::Lock id: 8, task_id: "3fc09e69-e60f-4168-bd38-edf625bb7c0f", name: "deploy", resource_type: "Staypuft::Deployment", resource_id: 6, exclusive: true>] (ForemanTasks::Lock::LockConflict) /opt/rh/ruby193/root/usr/share/gems/gems/foreman-tasks-0.5.3/app/models/foreman_tasks/lock.rb:34:in `block in <class:Lock>' /opt/rh/ruby193/root/usr/share/gems/gems/activesupport-3.2.8/lib/active_support/callbacks.rb:418:in `_run__1763986150783268744__validate__28801698837441719__callbacks' /opt/rh/ruby193/root/usr/share/gems/gems/activesupport-3.2.8/lib/active_support/callbacks.rb:405:in `__run_callback' /opt/rh/ruby193/root/usr/share/gems/gems/activesupport-3.2.8/lib/active_support/callbacks.rb:385:in `_run_validate_callbacks' /opt/rh/ruby193/root/usr/share/gems/gems/activesupport-3.2.8/lib/active_support/callbacks.rb:81:in `run_callbacks' /opt/rh/ruby193/root/usr/share/gems/gems/activemodel-3.2.8/lib/active_model/validations.rb:227:in `run_validations!' /opt/rh/ruby193/root/usr/share/gems/gems/activemodel-3.2.8/lib/active_model/validations/callbacks.rb:53:in `block in run_validations!' /opt/rh/ruby193/root/usr/share/gems/gems/activesupport-3.2.8/lib/active_support/callbacks.rb:414:in `_run__1763986150783268744__validation__28801698837441719__callbacks' /opt/rh/ruby193/root/usr/share/gems/gems/activesupport-3.2.8/lib/active_support/callbacks.rb:405:in `__run_callback' /opt/rh/ruby193/root/usr/share/gems/gems/activesupport-3.2.8/lib/active_support/callbacks.rb:385:in `_run_validation_callbacks' /opt/rh/ruby193/root/usr/share/gems/gems/activesupport-3.2.8/lib/active_support/callbacks.rb:81:in `run_callbacks' /opt/rh/ruby193/root/usr/share/gems/gems/activemodel-3.2.8/lib/active_model/validations/callbacks.rb:53:in `run_validations!' /opt/rh/ruby193/root/usr/share/gems/gems/activemodel-3.2.8/lib/active_model/validations.rb:194:in `valid?' /opt/rh/ruby193/root/usr/share/gems/gems/activerecord-3.2.8/lib/active_record/validations.rb:69:in `valid?' /opt/rh/ruby193/root/usr/share/gems/gems/activerecord-3.2.8/lib/active_record/validations.rb:77:in `perform_validations' /opt/rh/ruby193/root/usr/share/gems/gems/activerecord-3.2.8/lib/active_record/validations.rb:56:in `save!' /opt/rh/ruby193/root/usr/share/gems/gems/activerecord-3.2.8/lib/active_record/attribute_methods/dirty.rb:33:in `save!' /opt/rh/ruby193/root/usr/share/gems/gems/activerecord-3.2.8/lib/active_record/transactions.rb:246:in `block in save!' /opt/rh/ruby193/root/usr/share/gems/gems/activerecord-3.2.8/lib/active_record/transactions.rb:295:in `block in with_transaction_returning_status' /opt/rh/ruby193/root/usr/share/gems/gems/activerecord-3.2.8/lib/active_record/connection_adapters/abstract/database_statements.rb:192:in `transaction' /opt/rh/ruby193/root/usr/share/gems/gems/activerecord-3.2.8/lib/active_record/transactions.rb:208:in `transaction' /opt/rh/ruby193/root/usr/share/gems/gems/activerecord-3.2.8/lib/active_record/transactions.rb:293:in `with_transaction_returning_status' /opt/rh/ruby193/root/usr/share/gems/gems/activerecord-3.2.8/lib/active_record/transactions.rb:246:in `save!' /opt/rh/ruby193/root/usr/share/gems/gems/foreman-tasks-0.5.3/app/models/foreman_tasks/lock.rb:82:in `each' /opt/rh/ruby193/root/usr/share/gems/gems/foreman-tasks-0.5.3/app/models/foreman_tasks/lock.rb:82:in `lock!' /opt/rh/ruby193/root/usr/share/gems/gems/foreman-tasks-0.5.3/app/lib/actions/helpers/lock.rb:17:in `lock!' /opt/rh/ruby193/root/usr/share/gems/gems/staypuft-0.0.12/app/lib/actions/staypuft/deployment/deploy.rb:26:in `plan' /opt/rh/ruby193/root/usr/share/gems/gems/dynflow-0.6.1/lib/dynflow/action.rb:384:in `block (3 levels) in execute_plan' /opt/rh/ruby193/root/usr/share/gems/gems/dynflow-0.6.1/lib/dynflow/middleware/stack.rb:26:in `call' /opt/rh/ruby193/root/usr/share/gems/gems/dynflow-0.6.1/lib/dynflow/middleware/stack.rb:26:in `pass' /opt/rh/ruby193/root/usr/share/gems/gems/dynflow-0.6.1/lib/dynflow/middleware.rb:16:in `pass' /opt/rh/ruby193/root/usr/share/gems/gems/staypuft-0.0.12/app/lib/actions/staypuft/middleware/as_current_user.rb:7:in `plan' /opt/rh/ruby193/root/usr/share/gems/gems/dynflow-0.6.1/lib/dynflow/middleware/stack.rb:22:in `call' /opt/rh/ruby193/root/usr/share/gems/gems/dynflow-0.6.1/lib/dynflow/middleware/stack.rb:26:in `pass' /opt/rh/ruby193/root/usr/share/gems/gems/dynflow-0.6.1/lib/dynflow/middleware.rb:16:in `pass' /opt/rh/ruby193/root/usr/share/gems/gems/dynflow-0.6.1/lib/dynflow/middleware.rb:29:in `plan' /opt/rh/ruby193/root/usr/share/gems/gems/dynflow-0.6.1/lib/dynflow/middleware/stack.rb:22:in `call' /opt/rh/ruby193/root/usr/share/gems/gems/dynflow-0.6.1/lib/dynflow/middleware/world.rb:30:in `execute' /opt/rh/ruby193/root/usr/share/gems/gems/dynflow-0.6.1/lib/dynflow/action.rb:383:in `block (2 levels) in execute_plan' /opt/rh/ruby193/root/usr/share/gems/gems/dynflow-0.6.1/lib/dynflow/execution_plan.rb:193:in `call' /opt/rh/ruby193/root/usr/share/gems/gems/dynflow-0.6.1/lib/dynflow/execution_plan.rb:193:in `switch_flow' /opt/rh/ruby193/root/usr/share/gems/gems/dynflow-0.6.1/lib/dynflow/action.rb:303:in `concurrence' /opt/rh/ruby193/root/usr/share/gems/gems/dynflow-0.6.1/lib/dynflow/action.rb:382:in `block in execute_plan' /opt/rh/ruby193/root/usr/share/gems/gems/dynflow-0.6.1/lib/dynflow/action.rb:353:in `call' /opt/rh/ruby193/root/usr/share/gems/gems/dynflow-0.6.1/lib/dynflow/action.rb:353:in `block in with_error_handling' /opt/rh/ruby193/root/usr/share/gems/gems/activesupport-3.2.8/lib/active_support/callbacks.rb:414:in `_run__1763986150783268744__validation__28801698837441719__callbacks' /opt/rh/ruby193/root/usr/share/gems/gems/activesupport-3.2.8/lib/active_support/callbacks.rb:405:in `__run_callback' /opt/rh/ruby193/root/usr/share/gems/gems/activesupport-3.2.8/lib/active_support/callbacks.rb:385:in `_run_validation_callbacks' /opt/rh/ruby193/root/usr/share/gems/gems/activesupport-3.2.8/lib/active_support/callbacks.rb:81:in `run_callbacks' /opt/rh/ruby193/root/usr/share/gems/gems/activemodel-3.2.8/lib/active_model/validations/callbacks.rb:53:in `run_validations!' /opt/rh/ruby193/root/usr/share/gems/gems/activemodel-3.2.8/lib/active_model/validations.rb:194:in `valid?' /opt/rh/ruby193/root/usr/share/gems/gems/activerecord-3.2.8/lib/active_record/validations.rb:69:in `valid?' /opt/rh/ruby193/root/usr/share/gems/gems/activerecord-3.2.8/lib/active_record/validations.rb:77:in `perform_validations' /opt/rh/ruby193/root/usr/share/gems/gems/activerecord-3.2.8/lib/active_record/validations.rb:56:in `save!' /opt/rh/ruby193/root/usr/share/gems/gems/activerecord-3.2.8/lib/active_record/attribute_methods/dirty.rb:33:in `save!' /opt/rh/ruby193/root/usr/share/gems/gems/activerecord-3.2.8/lib/active_record/transactions.rb:246:in `block in save!' /opt/rh/ruby193/root/usr/share/gems/gems/activerecord-3.2.8/lib/active_record/transactions.rb:295:in `block in with_transaction_returning_status' /opt/rh/ruby193/root/usr/share/gems/gems/activerecord-3.2.8/lib/active_record/connection_adapters/abstract/database_statements.rb:192:in `transaction' /opt/rh/ruby193/root/usr/share/gems/gems/activerecord-3.2.8/lib/active_record/transactions.rb:208:in `transaction' /opt/rh/ruby193/root/usr/share/gems/gems/activerecord-3.2.8/lib/active_record/transactions.rb:293:in `with_transaction_returning_status' /opt/rh/ruby193/root/usr/share/gems/gems/activerecord-3.2.8/lib/active_record/transactions.rb:246:in `save!' /opt/rh/ruby193/root/usr/share/gems/gems/foreman-tasks-0.5.3/app/models/foreman_tasks/lock.rb:82:in `each' /opt/rh/ruby193/root/usr/share/gems/gems/foreman-tasks-0.5.3/app/models/foreman_tasks/lock.rb:82:in `lock!' /opt/rh/ruby193/root/usr/share/gems/gems/foreman-tasks-0.5.3/app/lib/actions/helpers/lock.rb:17:in `lock!' /opt/rh/ruby193/root/usr/share/gems/gems/staypuft-0.0.12/app/lib/actions/staypuft/deployment/deploy.rb:26:in `plan' /opt/rh/ruby193/root/usr/share/gems/gems/dynflow-0.6.1/lib/dynflow/action.rb:384:in `block (3 levels) in execute_plan' /opt/rh/ruby193/root/usr/share/gems/gems/dynflow-0.6.1/lib/dynflow/middleware/stack.rb:26:in `call' /opt/rh/ruby193/root/usr/share/gems/gems/dynflow-0.6.1/lib/dynflow/middleware/stack.rb:26:in `pass' /opt/rh/ruby193/root/usr/share/gems/gems/dynflow-0.6.1/lib/dynflow/middleware.rb:16:in `pass' /opt/rh/ruby193/root/usr/share/gems/gems/staypuft-0.0.12/app/lib/actions/staypuft/middleware/as_current_user.rb:7:in `plan' /opt/rh/ruby193/root/usr/share/gems/gems/dynflow-0.6.1/lib/dynflow/middleware/stack.rb:22:in `call' /opt/rh/ruby193/root/usr/share/gems/gems/dynflow-0.6.1/lib/dynflow/middleware/stack.rb:26:in `pass' /opt/rh/ruby193/root/usr/share/gems/gems/dynflow-0.6.1/lib/dynflow/middleware.rb:16:in `pass' /opt/rh/ruby193/root/usr/share/gems/gems/dynflow-0.6.1/lib/dynflow/middleware.rb:29:in `plan' /opt/rh/ruby193/root/usr/share/gems/gems/dynflow-0.6.1/lib/dynflow/middleware/stack.rb:22:in `call' /opt/rh/ruby193/root/usr/share/gems/gems/dynflow-0.6.1/lib/dynflow/middleware/world.rb:30:in `execute' /opt/rh/ruby193/root/usr/share/gems/gems/dynflow-0.6.1/lib/dynflow/action.rb:383:in `block (2 levels) in execute_plan' /opt/rh/ruby193/root/usr/share/gems/gems/dynflow-0.6.1/lib/dynflow/execution_plan.rb:193:in `call' /opt/rh/ruby193/root/usr/share/gems/gems/dynflow-0.6.1/lib/dynflow/execution_plan.rb:193:in `switch_flow' /opt/rh/ruby193/root/usr/share/gems/gems/dynflow-0.6.1/lib/dynflow/action.rb:303:in `concurrence' /opt/rh/ruby193/root/usr/share/gems/gems/dynflow-0.6.1/lib/dynflow/action.rb:382:in `block in execute_plan' /opt/rh/ruby193/root/usr/share/gems/gems/dynflow-0.6.1/lib/dynflow/action.rb:353:in `call' /opt/rh/ruby193/root/usr/share/gems/gems/dynflow-0.6.1/lib/dynflow/action.rb:353:in `block in with_error_handling' /opt/rh/ruby193/root/usr/share/gems/gems/dynflow-0.6.1/lib/dynflow/action.rb:353:in `catch' /opt/rh/ruby193/root/usr/share/gems/gems/dynflow-0.6.1/lib/dynflow/action.rb:353:in `with_error_handling' /opt/rh/ruby193/root/usr/share/gems/gems/dynflow-0.6.1/lib/dynflow/action.rb:381:in `execute_plan' /opt/rh/ruby193/root/usr/share/gems/gems/dynflow-0.6.1/lib/dynflow/action.rb:222:in `execute' /opt/rh/ruby193/root/usr/share/gems/gems/dynflow-0.6.1/lib/dynflow/execution_plan/steps/plan_step.rb:54:in `block in execute' /opt/rh/ruby193/root/usr/share/gems/gems/dynflow-0.6.1/lib/dynflow/execution_plan/steps/abstract.rb:141:in `call' .. .. .. .. .. .. /opt/rh/ruby193/root/usr/share/gems/gems/actionpack-3.2.8/lib/action_dispatch/middleware/static.rb:62:in `call' /opt/rh/ruby193/root/usr/share/gems/gems/rack-cache-1.2/lib/rack/cache/context.rb:136:in `forward' /opt/rh/ruby193/root/usr/share/gems/gems/rack-cache-1.2/lib/rack/cache/context.rb:245:in `fetch' /opt/rh/ruby193/root/usr/share/gems/gems/rack-cache-1.2/lib/rack/cache/context.rb:185:in `lookup' /opt/rh/ruby193/root/usr/share/gems/gems/rack-cache-1.2/lib/rack/cache/context.rb:66:in `call!' /opt/rh/ruby193/root/usr/share/gems/gems/rack-cache-1.2/lib/rack/cache/context.rb:51:in `call' /opt/rh/ruby193/root/usr/share/gems/gems/railties-3.2.8/lib/rails/engine.rb:479:in `call' /opt/rh/ruby193/root/usr/share/gems/gems/railties-3.2.8/lib/rails/application.rb:223:in `call' /opt/rh/ruby193/root/usr/share/gems/gems/railties-3.2.8/lib/rails/railtie/configurable.rb:30:in `method_missing' /opt/rh/ruby193/root/usr/share/gems/gems/rack-1.4.1/lib/rack/builder.rb:134:in `call' /opt/rh/ruby193/root/usr/share/gems/gems/rack-1.4.1/lib/rack/urlmap.rb:64:in `block in call' /opt/rh/ruby193/root/usr/share/gems/gems/rack-1.4.1/lib/rack/urlmap.rb:49:in `each' /opt/rh/ruby193/root/usr/share/gems/gems/rack-1.4.1/lib/rack/urlmap.rb:49:in `call' /usr/lib/ruby/gems/1.8/gems/passenger-4.0.5/lib/phusion_passenger/rack/thread_handler_extension.rb:77:in `process_request' /usr/lib/ruby/gems/1.8/gems/passenger-4.0.5/lib/phusion_passenger/request_handler/thread_handler.rb:140:in `accept_and_process_next_request' /usr/lib/ruby/gems/1.8/gems/passenger-4.0.5/lib/phusion_passenger/request_handler/thread_handler.rb:108:in `main_loop' /usr/lib/ruby/gems/1.8/gems/passenger-4.0.5/lib/phusion_passenger/request_handler.rb:441:in `block (3 levels) in start_threads' Operation FAILED: required lock: #<ForemanTasks::Lock:0x007f2558c36f98> conflicts wiht [#<ForemanTasks::Lock id: 8, task_id: "3fc09e69-e60f-4168-bd38-edf625bb7c0f", name: "deploy", resource_type: "Staypuft::Deployment", resource_id: 6, exclusive: true>] Rendered common/500.html.erb within staypuft/layouts/staypuft (9.9ms) Rendered layouts/base.html.erb (1.8ms) Rendered layouts/application.html.erb (2.5ms) Completed 500 Internal Server Error in 1042ms (Views: 16.2ms | ActiveRecord: 16.5ms)