Commit 5d7ee7a1 authored by Kamil Trzcinski's avatar Kamil Trzcinski

Use optimistic locking

parent 198ae21e
...@@ -30,23 +30,23 @@ module Ci ...@@ -30,23 +30,23 @@ module Ci
end end
event :run do event :run do
transition any => :running transition any - [:running] => :running
end end
event :skip do event :skip do
transition any => :skipped transition any - [:skipped] => :skipped
end end
event :drop do event :drop do
transition any => :failed transition any - [:failed] => :failed
end end
event :succeed do event :succeed do
transition any => :success transition any - [:success] => :success
end end
event :cancel do event :cancel do
transition any => :canceled transition any - [:canceled] => :canceled
end end
# IMPORTANT # IMPORTANT
...@@ -260,7 +260,7 @@ module Ci ...@@ -260,7 +260,7 @@ module Ci
end end
def update_status def update_status
with_lock do Gitlab::OptimisticLocking.retry_lock(build) do
case latest_builds_status case latest_builds_status
when 'pending' then enqueue when 'pending' then enqueue
when 'running' then run when 'running' then run
......
...@@ -10,7 +10,6 @@ module Ci ...@@ -10,7 +10,6 @@ module Ci
create_builds! create_builds!
end end
@pipeline.with_lock do
new_builds = new_builds =
stage_indexes_of_created_builds.map do |index| stage_indexes_of_created_builds.map do |index|
process_stage(index) process_stage(index)
...@@ -18,10 +17,8 @@ module Ci ...@@ -18,10 +17,8 @@ module Ci
@pipeline.update_status @pipeline.update_status
# Return a flag if a when builds got enqueued
new_builds.flatten.any? new_builds.flatten.any?
end end
end
private private
...@@ -32,12 +29,14 @@ module Ci ...@@ -32,12 +29,14 @@ module Ci
def process_stage(index) def process_stage(index)
current_status = status_for_prior_stages(index) current_status = status_for_prior_stages(index)
created_builds_in_stage(index).select do |build|
if HasStatus::COMPLETED_STATUSES.include?(current_status) if HasStatus::COMPLETED_STATUSES.include?(current_status)
created_builds_in_stage(index).select do |build|
Gitlab::OptimisticLocking.retry_lock(build) do |build|
process_build(build, current_status) process_build(build, current_status)
end end
end end
end end
end
def process_build(build, current_status) def process_build(build, current_status)
if valid_statuses_for_when(build.when).include?(current_status) if valid_statuses_for_when(build.when).include?(current_status)
......
...@@ -28,17 +28,14 @@ module Ci ...@@ -28,17 +28,14 @@ module Ci
if build if build
# In case when 2 runners try to assign the same build, second runner will be declined # In case when 2 runners try to assign the same build, second runner will be declined
# with StateMachines::InvalidTransition in run! method. # with StateMachines::InvalidTransition or StaleObjectError when doing run! or save method.
build.with_lock do
build.runner_id = current_runner.id build.runner_id = current_runner.id
build.save!
build.run! build.run!
end end
end
build build
rescue StateMachines::InvalidTransition rescue StateMachines::InvalidTransition, StaleObjectError
nil nil
end end
......
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
class AddLockVersionToBuildAndPipelines < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
DOWNTIME = false
def change
add_column :ci_builds, :lock_version, :integer
add_column :ci_commits, :lock_version, :integer
end
end
...@@ -189,6 +189,7 @@ ActiveRecord::Schema.define(version: 20161024042317) do ...@@ -189,6 +189,7 @@ ActiveRecord::Schema.define(version: 20161024042317) do
t.text "yaml_variables" t.text "yaml_variables"
t.datetime "queued_at" t.datetime "queued_at"
t.string "token" t.string "token"
t.integer "lock_version"
end end
add_index "ci_builds", ["commit_id", "stage_idx", "created_at"], name: "index_ci_builds_on_commit_id_and_stage_idx_and_created_at", using: :btree add_index "ci_builds", ["commit_id", "stage_idx", "created_at"], name: "index_ci_builds_on_commit_id_and_stage_idx_and_created_at", using: :btree
...@@ -219,6 +220,7 @@ ActiveRecord::Schema.define(version: 20161024042317) do ...@@ -219,6 +220,7 @@ ActiveRecord::Schema.define(version: 20161024042317) do
t.datetime "finished_at" t.datetime "finished_at"
t.integer "duration" t.integer "duration"
t.integer "user_id" t.integer "user_id"
t.integer "lock_version"
end end
add_index "ci_commits", ["gl_project_id", "sha"], name: "index_ci_commits_on_gl_project_id_and_sha", using: :btree add_index "ci_commits", ["gl_project_id", "sha"], name: "index_ci_commits_on_gl_project_id_and_sha", using: :btree
......
module Gitlab
module OptimisticLocking
def retry_lock(subject, &block)
while true do
begin
return yield subject
rescue StaleObjectError
subject.reload
end
end
end
end
end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment