Update project statistics when some snippet events happens

In this update with update the snippet and project statistics
after a git operation is performed on the snippet repository
or when the snippet is deleted.
parent 1b0feb52
...@@ -27,6 +27,11 @@ module Snippets ...@@ -27,6 +27,11 @@ module Snippets
attempt_destroy! attempt_destroy!
# Update project statistics if the snippet is a Project one
if snippet.project_id
ProjectCacheWorker.perform_async(snippet.project_id, [], [:snippets_size])
end
ServiceResponse.success(message: 'Snippet was deleted.') ServiceResponse.success(message: 'Snippet was deleted.')
rescue DestroyError rescue DestroyError
service_response_error('Failed to remove snippet repository.', 400) service_response_error('Failed to remove snippet repository.', 400)
......
# frozen_string_literal: true
module Snippets
class UpdateStatisticsService
attr_reader :snippet
def initialize(snippet)
@snippet = snippet
end
def execute
unless snippet.repository_exists?
return ServiceResponse.error(message: 'Invalid snippet repository', http_status: 400)
end
snippet.repository.expire_statistics_caches
statistics.refresh!
# Update project statistics if the snippet is a Project one
if snippet.project_id
ProjectCacheWorker.perform_async(snippet.project_id, [], [:snippets_size])
end
ServiceResponse.success(message: 'Snippet statistics successfully updated.')
end
private
def statistics
@statistics ||= snippet.statistics || snippet.build_statistics
end
end
end
...@@ -79,7 +79,7 @@ class PostReceive # rubocop:disable Scalability/IdempotentWorker ...@@ -79,7 +79,7 @@ class PostReceive # rubocop:disable Scalability/IdempotentWorker
return false unless user return false unless user
expire_caches(post_received, snippet.repository) expire_caches(post_received, snippet.repository)
snippet.repository.expire_statistics_caches Snippets::UpdateStatisticsService.new(snippet).execute
end end
# Expire the repository status, branch, and tag cache once per push. # Expire the repository status, branch, and tag cache once per push.
......
---
title: Update snippet and project statistics after certain events
merge_request: 35340
author:
type: changed
...@@ -105,6 +105,13 @@ RSpec.describe Snippets::DestroyService do ...@@ -105,6 +105,13 @@ RSpec.describe Snippets::DestroyService do
it_behaves_like 'a successful destroy' it_behaves_like 'a successful destroy'
it_behaves_like 'deletes the snippet repository' it_behaves_like 'deletes the snippet repository'
it 'schedules a project cache update for snippet_size' do
expect(ProjectCacheWorker).to receive(:perform_async)
.with(snippet.project_id, [], [:snippets_size])
subject
end
end end
context 'when user is not able to admin_project_snippet' do context 'when user is not able to admin_project_snippet' do
...@@ -122,6 +129,12 @@ RSpec.describe Snippets::DestroyService do ...@@ -122,6 +129,12 @@ RSpec.describe Snippets::DestroyService do
it_behaves_like 'a successful destroy' it_behaves_like 'a successful destroy'
it_behaves_like 'deletes the snippet repository' it_behaves_like 'deletes the snippet repository'
it 'does not schedule a project cache update' do
expect(ProjectCacheWorker).not_to receive(:perform_async)
subject
end
end end
context 'when user is not able to admin_personal_snippet' do context 'when user is not able to admin_personal_snippet' do
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Snippets::UpdateStatisticsService do
describe '#execute' do
subject { described_class.new(snippet).execute }
shared_examples 'updates statistics' do
it 'returns a successful response' do
expect(subject).to be_success
end
it 'expires statistics cache' do
expect(snippet.repository).to receive(:expire_statistics_caches)
subject
end
it 'schedules project cache worker based on type' do
if snippet.project_id
expect(ProjectCacheWorker).to receive(:perform_async)
.with(snippet.project_id, [], [:snippets_size])
else
expect(ProjectCacheWorker).not_to receive(:perform_async)
end
subject
end
context 'when snippet statistics does not exist' do
it 'creates snippet statistics' do
snippet.statistics.delete
snippet.reload
expect do
subject
end.to change(SnippetStatistics, :count).by(1)
expect(snippet.statistics.commit_count).not_to be_zero
expect(snippet.statistics.file_count).not_to be_zero
expect(snippet.statistics.repository_size).not_to be_zero
end
end
context 'when snippet statistics exists' do
it 'updates snippet statistics' do
expect(snippet.statistics.commit_count).to be_zero
expect(snippet.statistics.file_count).to be_zero
expect(snippet.statistics.repository_size).to be_zero
subject
expect(snippet.statistics.commit_count).not_to be_zero
expect(snippet.statistics.file_count).not_to be_zero
expect(snippet.statistics.repository_size).not_to be_zero
end
end
context 'when snippet does not have a repository' do
it 'returns an error response' do
expect(snippet).to receive(:repository_exists?).and_return(false)
expect(subject).to be_error
end
end
end
context 'with PersonalSnippet' do
let!(:snippet) { create(:personal_snippet, :repository) }
it_behaves_like 'updates statistics'
end
context 'with ProjectSnippet' do
let!(:snippet) { create(:project_snippet, :repository) }
it_behaves_like 'updates statistics'
end
end
end
...@@ -428,7 +428,12 @@ RSpec.describe PostReceive do ...@@ -428,7 +428,12 @@ RSpec.describe PostReceive do
it 'expires the status cache' do it 'expires the status cache' do
expect(snippet.repository).to receive(:empty?).and_return(true) expect(snippet.repository).to receive(:empty?).and_return(true)
expect(snippet.repository).to receive(:expire_status_cache) expect(snippet.repository).to receive(:expire_status_cache)
expect(snippet.repository).to receive(:expire_statistics_caches)
perform
end
it 'updates snippet statistics' do
expect(Snippets::UpdateStatisticsService).to receive(:new).with(snippet).and_call_original
perform perform
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