Commit f3eacf88 authored by Douglas Barbosa Alexandre's avatar Douglas Barbosa Alexandre Committed by Nick Thomas

Geo - Log a repository created event when a project is created

parent 8382156c
...@@ -2,6 +2,10 @@ module Geo ...@@ -2,6 +2,10 @@ module Geo
class EventLog < ActiveRecord::Base class EventLog < ActiveRecord::Base
include Geo::Model include Geo::Model
belongs_to :repository_created_event,
class_name: 'Geo::RepositoryCreatedEvent',
foreign_key: :repository_created_event_id
belongs_to :repository_updated_event, belongs_to :repository_updated_event,
class_name: 'Geo::RepositoryUpdatedEvent', class_name: 'Geo::RepositoryUpdatedEvent',
foreign_key: :repository_updated_event_id foreign_key: :repository_updated_event_id
...@@ -19,7 +23,8 @@ module Geo ...@@ -19,7 +23,8 @@ module Geo
foreign_key: :repositories_changed_event_id foreign_key: :repositories_changed_event_id
def event def event
repository_updated_event || repository_created_event ||
repository_updated_event ||
repository_deleted_event || repository_deleted_event ||
repository_renamed_event || repository_renamed_event ||
repositories_changed_event repositories_changed_event
......
module Geo
class RepositoryCreatedEvent < ActiveRecord::Base
include Geo::Model
belongs_to :project
validates :project, :project_name, :repo_path, :repository_storage_name,
:repository_storage_path, presence: true
end
end
module Geo
class RepositoryCreatedEventStore < EventStore
self.event_type = :repository_created_event
private
def build_event
Geo::RepositoryCreatedEvent.new(
project: project,
repository_storage_name: project.repository.storage,
repository_storage_path: project.repository_storage_path,
repo_path: project.disk_path,
wiki_path: "#{project.disk_path}.wiki",
project_name: project.name
)
end
end
end
---
title: Geo - Log a repository created event when a project is created
merge_request: 2807
author:
type: added
class CreateGeoRepositoryCreatedEvents < ActiveRecord::Migration
DOWNTIME = false
def change
create_table :geo_repository_created_events, id: :bigserial do |t|
t.references :project, index: true, foreign_key: { on_delete: :cascade }, null: false
t.text :repository_storage_name, null: false
t.text :repository_storage_path, null: false
t.text :repo_path, null: false
t.text :wiki_path
t.text :project_name, null: false
end
add_column :geo_event_log, :repository_created_event_id, :integer, limit: 8
end
end
class AddIndexToGeoEventLogRepositoryCreatedEventId < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
disable_ddl_transaction!
def up
add_concurrent_index :geo_event_log, :repository_created_event_id
end
def down
if index_exists? :geo_event_log, :repository_created_event_id
remove_concurrent_index :geo_event_log, :repository_created_event_id
end
end
end
class AddGeoRepositoryCreatedEventsFkOnGeoEventLog < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
disable_ddl_transaction!
def up
add_concurrent_foreign_key :geo_event_log, :geo_repository_created_events,
column: :repository_created_event_id, on_delete: :cascade
end
def down
remove_foreign_key :geo_event_log, column: :repository_created_event_id
end
end
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
# #
# It's strongly recommended that you check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20170905202320) do ActiveRecord::Schema.define(version: 20170906160132) do
# These are extensions that must be enabled in order to support this database # These are extensions that must be enabled in order to support this database
enable_extension "plpgsql" enable_extension "plpgsql"
...@@ -669,9 +669,11 @@ ActiveRecord::Schema.define(version: 20170905202320) do ...@@ -669,9 +669,11 @@ ActiveRecord::Schema.define(version: 20170905202320) do
t.integer "repository_deleted_event_id", limit: 8 t.integer "repository_deleted_event_id", limit: 8
t.integer "repository_renamed_event_id", limit: 8 t.integer "repository_renamed_event_id", limit: 8
t.integer "repositories_changed_event_id", limit: 8 t.integer "repositories_changed_event_id", limit: 8
t.integer "repository_created_event_id", limit: 8
end end
add_index "geo_event_log", ["repositories_changed_event_id"], name: "index_geo_event_log_on_repositories_changed_event_id", using: :btree add_index "geo_event_log", ["repositories_changed_event_id"], name: "index_geo_event_log_on_repositories_changed_event_id", using: :btree
add_index "geo_event_log", ["repository_created_event_id"], name: "index_geo_event_log_on_repository_created_event_id", using: :btree
add_index "geo_event_log", ["repository_deleted_event_id"], name: "index_geo_event_log_on_repository_deleted_event_id", using: :btree add_index "geo_event_log", ["repository_deleted_event_id"], name: "index_geo_event_log_on_repository_deleted_event_id", using: :btree
add_index "geo_event_log", ["repository_renamed_event_id"], name: "index_geo_event_log_on_repository_renamed_event_id", using: :btree add_index "geo_event_log", ["repository_renamed_event_id"], name: "index_geo_event_log_on_repository_renamed_event_id", using: :btree
add_index "geo_event_log", ["repository_updated_event_id"], name: "index_geo_event_log_on_repository_updated_event_id", using: :btree add_index "geo_event_log", ["repository_updated_event_id"], name: "index_geo_event_log_on_repository_updated_event_id", using: :btree
...@@ -711,6 +713,17 @@ ActiveRecord::Schema.define(version: 20170905202320) do ...@@ -711,6 +713,17 @@ ActiveRecord::Schema.define(version: 20170905202320) do
add_index "geo_repositories_changed_events", ["geo_node_id"], name: "index_geo_repositories_changed_events_on_geo_node_id", using: :btree add_index "geo_repositories_changed_events", ["geo_node_id"], name: "index_geo_repositories_changed_events_on_geo_node_id", using: :btree
create_table "geo_repository_created_events", id: :bigserial, force: :cascade do |t|
t.integer "project_id", null: false
t.text "repository_storage_name", null: false
t.text "repository_storage_path", null: false
t.text "repo_path", null: false
t.text "wiki_path"
t.text "project_name", null: false
end
add_index "geo_repository_created_events", ["project_id"], name: "index_geo_repository_created_events_on_project_id", using: :btree
create_table "geo_repository_deleted_events", id: :bigserial, force: :cascade do |t| create_table "geo_repository_deleted_events", id: :bigserial, force: :cascade do |t|
t.integer "project_id", null: false t.integer "project_id", null: false
t.text "repository_storage_name", null: false t.text "repository_storage_name", null: false
...@@ -2057,12 +2070,14 @@ ActiveRecord::Schema.define(version: 20170905202320) do ...@@ -2057,12 +2070,14 @@ ActiveRecord::Schema.define(version: 20170905202320) do
add_foreign_key "events_for_migration", "users", column: "author_id", name: "fk_edfd187b6f", on_delete: :cascade add_foreign_key "events_for_migration", "users", column: "author_id", name: "fk_edfd187b6f", on_delete: :cascade
add_foreign_key "forked_project_links", "projects", column: "forked_to_project_id", name: "fk_434510edb0", on_delete: :cascade add_foreign_key "forked_project_links", "projects", column: "forked_to_project_id", name: "fk_434510edb0", on_delete: :cascade
add_foreign_key "geo_event_log", "geo_repositories_changed_events", column: "repositories_changed_event_id", name: "fk_4a99ebfd60", on_delete: :cascade add_foreign_key "geo_event_log", "geo_repositories_changed_events", column: "repositories_changed_event_id", name: "fk_4a99ebfd60", on_delete: :cascade
add_foreign_key "geo_event_log", "geo_repository_created_events", column: "repository_created_event_id", name: "fk_9b9afb1916", on_delete: :cascade
add_foreign_key "geo_event_log", "geo_repository_deleted_events", column: "repository_deleted_event_id", name: "fk_c4b1c1f66e", on_delete: :cascade add_foreign_key "geo_event_log", "geo_repository_deleted_events", column: "repository_deleted_event_id", name: "fk_c4b1c1f66e", on_delete: :cascade
add_foreign_key "geo_event_log", "geo_repository_renamed_events", column: "repository_renamed_event_id", name: "fk_86c84214ec", on_delete: :cascade add_foreign_key "geo_event_log", "geo_repository_renamed_events", column: "repository_renamed_event_id", name: "fk_86c84214ec", on_delete: :cascade
add_foreign_key "geo_event_log", "geo_repository_updated_events", column: "repository_updated_event_id", on_delete: :cascade add_foreign_key "geo_event_log", "geo_repository_updated_events", column: "repository_updated_event_id", on_delete: :cascade
add_foreign_key "geo_node_namespace_links", "geo_nodes", on_delete: :cascade add_foreign_key "geo_node_namespace_links", "geo_nodes", on_delete: :cascade
add_foreign_key "geo_node_namespace_links", "namespaces", on_delete: :cascade add_foreign_key "geo_node_namespace_links", "namespaces", on_delete: :cascade
add_foreign_key "geo_repositories_changed_events", "geo_nodes", on_delete: :cascade add_foreign_key "geo_repositories_changed_events", "geo_nodes", on_delete: :cascade
add_foreign_key "geo_repository_created_events", "projects", on_delete: :cascade
add_foreign_key "geo_repository_renamed_events", "projects", on_delete: :cascade add_foreign_key "geo_repository_renamed_events", "projects", on_delete: :cascade
add_foreign_key "geo_repository_updated_events", "projects", on_delete: :cascade add_foreign_key "geo_repository_updated_events", "projects", on_delete: :cascade
add_foreign_key "index_statuses", "projects", name: "fk_74b2492545", on_delete: :cascade add_foreign_key "index_statuses", "projects", name: "fk_74b2492545", on_delete: :cascade
......
...@@ -9,7 +9,7 @@ module EE ...@@ -9,7 +9,7 @@ module EE
mirror_user_id = params.delete(:mirror_user_id) mirror_user_id = params.delete(:mirror_user_id)
mirror_trigger_builds = params.delete(:mirror_trigger_builds) mirror_trigger_builds = params.delete(:mirror_trigger_builds)
super do |project| project = super do |project|
# Repository size limit comes as MB from the view # Repository size limit comes as MB from the view
project.repository_size_limit = ::Gitlab::Utils.try_megabytes_to_bytes(limit) if limit project.repository_size_limit = ::Gitlab::Utils.try_megabytes_to_bytes(limit) if limit
...@@ -19,10 +19,18 @@ module EE ...@@ -19,10 +19,18 @@ module EE
project.mirror_user_id = mirror_user_id project.mirror_user_id = mirror_user_id
end end
end end
log_geo_event(project) if project&.persisted?
project
end end
private private
def log_geo_event(project)
::Geo::RepositoryCreatedEventStore.new(project).create
end
def after_create_actions def after_create_actions
raise NotImplementedError unless defined?(super) raise NotImplementedError unless defined?(super)
......
...@@ -66,6 +66,8 @@ module Gitlab ...@@ -66,6 +66,8 @@ module Gitlab
if event_log.repository_updated_event if event_log.repository_updated_event
handle_repository_update(event_log) handle_repository_update(event_log)
elsif event_log.repository_created_event
handle_repository_created(event_log)
elsif event_log.repository_deleted_event elsif event_log.repository_deleted_event
handle_repository_delete(event_log) handle_repository_delete(event_log)
elsif event_log.repositories_changed_event elsif event_log.repositories_changed_event
...@@ -104,6 +106,24 @@ module Gitlab ...@@ -104,6 +106,24 @@ module Gitlab
Gitlab::Geo.current_node&.projects_include?(event_log.project_id) Gitlab::Geo.current_node&.projects_include?(event_log.project_id)
end end
def handle_repository_created(event_log)
created_event = event_log.repository_created_event
registry = ::Geo::ProjectRegistry.find_or_initialize_by(project_id: created_event.project_id)
registry.resync_repository = true
registry.resync_wiki = created_event.wiki_path.present?
log_event_info(
event_log.created_at,
message: 'Repository created',
project_id: created_event.project_id,
repo_path: created_event.repo_path,
wiki_path: created_event.wiki_path,
resync_repository: registry.resync_repository,
resync_wiki: registry.resync_wiki)
registry.save!
end
def handle_repository_update(event) def handle_repository_update(event)
updated_event = event.repository_updated_event updated_event = event.repository_updated_event
registry = ::Geo::ProjectRegistry.find_or_initialize_by(project_id: updated_event.project_id) registry = ::Geo::ProjectRegistry.find_or_initialize_by(project_id: updated_event.project_id)
......
...@@ -134,7 +134,24 @@ describe Projects::CreateService, '#execute' do ...@@ -134,7 +134,24 @@ describe Projects::CreateService, '#execute' do
end end
end end
context 'when running on a primary node' do
let!(:geo_node) { create(:geo_node, :primary, :current) }
it 'logs an event to the Geo event log' do
expect { create_project(user, opts) }.to change(Geo::RepositoryCreatedEvent, :count).by(1)
end
it 'does not log event to the Geo log if project creation fails' do
failing_opts = {
name: nil,
namespace: user.namespace
}
expect { create_project(user, failing_opts) }.not_to change(Geo::RepositoryCreatedEvent, :count)
end
end
def create_project(user, opts) def create_project(user, opts)
Projects::CreateService.new(user, opts).execute described_class.new(user, opts).execute
end end
end end
FactoryGirl.define do FactoryGirl.define do
factory :geo_event_log, class: Geo::EventLog do factory :geo_event_log, class: Geo::EventLog do
trait :created_event do
repository_created_event factory: :geo_repository_created_event
end
trait :updated_event do trait :updated_event do
repository_updated_event factory: :geo_repository_updated_event repository_updated_event factory: :geo_repository_updated_event
end end
...@@ -13,11 +17,22 @@ FactoryGirl.define do ...@@ -13,11 +17,22 @@ FactoryGirl.define do
end end
end end
factory :geo_repository_created_event, class: Geo::RepositoryCreatedEvent do
project
repository_storage_name { project.repository_storage }
repository_storage_path { project.repository_storage_path }
add_attribute(:repo_path) { project.disk_path }
project_name { project.name }
wiki_path { "{project.disk_path}.wiki" }
end
factory :geo_repository_updated_event, class: Geo::RepositoryUpdatedEvent do factory :geo_repository_updated_event, class: Geo::RepositoryUpdatedEvent do
project
source 0 source 0
branches_affected 0 branches_affected 0
tags_affected 0 tags_affected 0
project
end end
factory :geo_repository_deleted_event, class: Geo::RepositoryDeletedEvent do factory :geo_repository_deleted_event, class: Geo::RepositoryDeletedEvent do
......
...@@ -23,6 +23,38 @@ describe Gitlab::Geo::LogCursor::Daemon, :postgresql do ...@@ -23,6 +23,38 @@ describe Gitlab::Geo::LogCursor::Daemon, :postgresql do
end end
end end
context 'when replaying a repository created event' do
let(:repository_created_event) { create(:geo_repository_created_event) }
let(:event_log) { create(:geo_event_log, repository_created_event: repository_created_event) }
let!(:event_log_state) { create(:geo_event_log_state, event_id: event_log.id - 1) }
before do
allow(subject).to receive(:exit?).and_return(false, true)
end
it 'creates a new project registry' do
expect { subject.run! }.to change(Geo::ProjectRegistry, :count).by(1)
end
it 'sets resync attributes to true' do
subject.run!
registry = Geo::ProjectRegistry.last
expect(registry).to have_attributes(resync_repository: true, resync_wiki: true)
end
it 'sets resync_wiki to false if wiki_path is nil' do
repository_created_event.update_attribute(:wiki_path, nil)
subject.run!
registry = Geo::ProjectRegistry.last
expect(registry).to have_attributes(resync_repository: true, resync_wiki: false)
end
end
context 'when replaying a repository updated event' do context 'when replaying a repository updated event' do
let(:event_log) { create(:geo_event_log, :updated_event) } let(:event_log) { create(:geo_event_log, :updated_event) }
let!(:event_log_state) { create(:geo_event_log_state, event_id: event_log.id - 1) } let!(:event_log_state) { create(:geo_event_log_state, event_id: event_log.id - 1) }
......
...@@ -2,10 +2,11 @@ require 'spec_helper' ...@@ -2,10 +2,11 @@ require 'spec_helper'
RSpec.describe Geo::EventLog, type: :model do RSpec.describe Geo::EventLog, type: :model do
describe 'relationships' do describe 'relationships' do
it { is_expected.to belong_to(:repository_updated_event).class_name('Geo::RepositoryUpdatedEvent').with_foreign_key('repository_updated_event_id') } it { is_expected.to belong_to(:repositories_changed_event).class_name('Geo::RepositoriesChangedEvent').with_foreign_key('repositories_changed_event_id') }
it { is_expected.to belong_to(:repository_created_event).class_name('Geo::RepositoryCreatedEvent').with_foreign_key('repository_created_event_id') }
it { is_expected.to belong_to(:repository_deleted_event).class_name('Geo::RepositoryDeletedEvent').with_foreign_key('repository_deleted_event_id') } it { is_expected.to belong_to(:repository_deleted_event).class_name('Geo::RepositoryDeletedEvent').with_foreign_key('repository_deleted_event_id') }
it { is_expected.to belong_to(:repository_renamed_event).class_name('Geo::RepositoryRenamedEvent').with_foreign_key('repository_renamed_event_id') } it { is_expected.to belong_to(:repository_renamed_event).class_name('Geo::RepositoryRenamedEvent').with_foreign_key('repository_renamed_event_id') }
it { is_expected.to belong_to(:repositories_changed_event).class_name('Geo::RepositoriesChangedEvent').with_foreign_key('repositories_changed_event_id') } it { is_expected.to belong_to(:repository_updated_event).class_name('Geo::RepositoryUpdatedEvent').with_foreign_key('repository_updated_event_id') }
end end
describe '#event' do describe '#event' do
...@@ -13,6 +14,13 @@ RSpec.describe Geo::EventLog, type: :model do ...@@ -13,6 +14,13 @@ RSpec.describe Geo::EventLog, type: :model do
expect(subject.event).to be_nil expect(subject.event).to be_nil
end end
it 'returns repository_created_event when set' do
repository_created_event = build(:geo_repository_created_event)
subject.repository_created_event = repository_created_event
expect(subject.event).to eq repository_created_event
end
it 'returns repository_updated_event when set' do it 'returns repository_updated_event when set' do
repository_updated_event = build(:geo_repository_updated_event) repository_updated_event = build(:geo_repository_updated_event)
subject.repository_updated_event = repository_updated_event subject.repository_updated_event = repository_updated_event
......
require 'spec_helper'
describe Geo::RepositoryCreatedEvent, type: :model do
describe 'relationships' do
it { is_expected.to belong_to(:project) }
end
describe 'validations' do
it { is_expected.to validate_presence_of(:project) }
it { is_expected.to validate_presence_of(:project_name) }
it { is_expected.to validate_presence_of(:repo_path) }
it { is_expected.to validate_presence_of(:repository_storage_name) }
it { is_expected.to validate_presence_of(:repository_storage_path) }
end
end
require 'spec_helper'
describe Geo::RepositoryCreatedEventStore do
let(:project) { create(:project) }
subject(:event) { described_class.new(project) }
describe '#create' do
it 'does not create an event when not running on a primary node' do
allow(Gitlab::Geo).to receive(:primary?) { false }
expect { event.create }.not_to change(Geo::RepositoryCreatedEvent, :count)
end
context 'when running on a primary node' do
before do
allow(Gitlab::Geo).to receive(:primary?) { true }
end
it 'creates a created event' do
expect { event.create }.to change(Geo::RepositoryCreatedEvent, :count).by(1)
end
it 'tracks information for the created project' do
event.create
event = Geo::RepositoryCreatedEvent.last
expect(event).to have_attributes(
project_id: project.id,
repo_path: project.disk_path,
wiki_path: "#{project.disk_path}.wiki",
project_name: project.name,
repository_storage_name: project.repository_storage,
repository_storage_path: project.repository_storage_path
)
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