Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
0dfbcd8f8b
commit
ac062237da
|
@ -7,6 +7,8 @@ module Noteable
|
||||||
# avoiding n+1 queries and improving performance.
|
# avoiding n+1 queries and improving performance.
|
||||||
NoteableMeta = Struct.new(:user_notes_count)
|
NoteableMeta = Struct.new(:user_notes_count)
|
||||||
|
|
||||||
|
MAX_NOTES_LIMIT = 5_000
|
||||||
|
|
||||||
class_methods do
|
class_methods do
|
||||||
# `Noteable` class names that support replying to individual notes.
|
# `Noteable` class names that support replying to individual notes.
|
||||||
def replyable_types
|
def replyable_types
|
||||||
|
|
|
@ -104,6 +104,8 @@ class Note < ApplicationRecord
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
validate :does_not_exceed_notes_limit?, on: :create, unless: [:system?, :importing?]
|
||||||
|
|
||||||
# @deprecated attachments are handler by the MarkdownUploader
|
# @deprecated attachments are handler by the MarkdownUploader
|
||||||
mount_uploader :attachment, AttachmentUploader
|
mount_uploader :attachment, AttachmentUploader
|
||||||
|
|
||||||
|
@ -525,6 +527,12 @@ class Note < ApplicationRecord
|
||||||
|
|
||||||
system_note_metadata&.cross_reference_types&.include?(system_note_metadata&.action)
|
system_note_metadata&.cross_reference_types&.include?(system_note_metadata&.action)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def does_not_exceed_notes_limit?
|
||||||
|
return unless noteable
|
||||||
|
|
||||||
|
errors.add(:base, _('Maximum number of comments exceeded')) if noteable.notes.count >= Noteable::MAX_NOTES_LIMIT
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
Note.prepend_if_ee('EE::Note')
|
Note.prepend_if_ee('EE::Note')
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
title: Limit the number of comments on an issue, MR, or commit
|
||||||
|
merge_request: 18111
|
||||||
|
author:
|
||||||
|
type: added
|
|
@ -211,7 +211,11 @@ environment that supports about 10,000 users. The specifications below are a
|
||||||
representation of the work so far. The specifications may be adjusted in the
|
representation of the work so far. The specifications may be adjusted in the
|
||||||
future based on additional testing and iteration.
|
future based on additional testing and iteration.
|
||||||
|
|
||||||
NOTE: **Note:** The specifications here were performance tested against a specific coded workload. Your exact needs may be more, depending on your workload. Your workload is influenced by factors such as - but not limited to - how active your users are, how much automation you use, mirroring, and repo/change size.
|
NOTE: **Note:** The specifications here were performance tested against a
|
||||||
|
specific coded workload. Your exact needs may be more, depending on your
|
||||||
|
workload. Your workload is influenced by factors such as - but not limited to -
|
||||||
|
how active your users are, how much automation you use, mirroring, and
|
||||||
|
repo/change size.
|
||||||
|
|
||||||
- 3 PostgreSQL - 4 CPU, 16GiB memory per node
|
- 3 PostgreSQL - 4 CPU, 16GiB memory per node
|
||||||
- 1 PgBouncer - 2 CPU, 4GiB memory
|
- 1 PgBouncer - 2 CPU, 4GiB memory
|
||||||
|
@ -229,13 +233,28 @@ NOTE: **Note:** The specifications here were performance tested against a specif
|
||||||
- **Status:** Work-in-progress
|
- **Status:** Work-in-progress
|
||||||
- **Related Issue:** See the [related issue](https://gitlab.com/gitlab-org/quality/performance/issues/57) for more information.
|
- **Related Issue:** See the [related issue](https://gitlab.com/gitlab-org/quality/performance/issues/57) for more information.
|
||||||
|
|
||||||
The Support and Quality teams are in the process of building and performance testing
|
The Support and Quality teams are in the process of building and performance
|
||||||
an environment that will support about 25,000 users. The specifications below
|
testing an environment that will support around 25,000 users. The specifications
|
||||||
are a work-in-progress representation of the work so far. The Quality team will be
|
below are a work-in-progress representation of the work so far. The Quality team
|
||||||
certifying this environment in late 2019. The specifications may be adjusted
|
will be certifying this environment in late 2019. The specifications may be
|
||||||
prior to certification based on performance testing.
|
adjusted prior to certification based on performance testing.
|
||||||
|
|
||||||
TBD: Add specs
|
| Service | Configuration | GCP type |
|
||||||
|
| ------------------------------|-------------------------|----------------|
|
||||||
|
| 7 GitLab Rails <br> - Puma workers on each node set to 90% of available CPUs with 16 threads | 32 vCPU, 28.8GB Memory | n1-highcpu-32 |
|
||||||
|
| 3 PostgreSQL | 8 vCPU, 30GB Memory | n1-standard-8 |
|
||||||
|
| 1 PgBouncer | 2 vCPU, 1.8GB Memory | n1-highcpu-2 |
|
||||||
|
| 2 Gitaly <br> - Gitaly Ruby workers on each node set to 90% of available CPUs with 16 threads | 32 vCPU, 120GB Memory | n1-standard-32 |
|
||||||
|
| 3 Redis Cache + Sentinel <br> - Cache maxmemory set to 90% of available memory | 4 vCPU, 15GB Memory | n1-standard-4 |
|
||||||
|
| 3 Redis Persistent + Sentinel | 4 vCPU, 15GB Memory | n1-standard-4 |
|
||||||
|
| 4 Sidekiq | 4 vCPU, 15GB Memory | n1-standard-4 |
|
||||||
|
| 3 Consul | 2 vCPU, 1.8GB Memory | n1-highcpu-2 |
|
||||||
|
| 1 NFS Server | 2 vCPU, 1.8GB Memory | n1-highcpu-2 |
|
||||||
|
| 1 Monitoring node | 4 CPU, 3.6GB Memory | n1-highcpu-4 |
|
||||||
|
| 1 Load Balancing node | 2 vCPU, 1.8GB Memory | n1-highcpu-2 |
|
||||||
|
|
||||||
|
NOTE: **Note:** At this time, HAProxy is the only tested and recommended load
|
||||||
|
balancer. We may test and add additional options to this list in time.
|
||||||
|
|
||||||
### 50,000 User Configuration
|
### 50,000 User Configuration
|
||||||
|
|
||||||
|
@ -244,10 +263,10 @@ TBD: Add specs
|
||||||
- **Status:** Work-in-progress
|
- **Status:** Work-in-progress
|
||||||
- **Related Issue:** See the [related issue](https://gitlab.com/gitlab-org/quality/performance/issues/66) for more information.
|
- **Related Issue:** See the [related issue](https://gitlab.com/gitlab-org/quality/performance/issues/66) for more information.
|
||||||
|
|
||||||
The Support and Quality teams are in the process of building and performance testing
|
The Support and Quality teams are in the process of building and performance
|
||||||
an environment that will support about 50,000 users. The specifications below
|
testing an environment that will support around 50,000 users. The specifications
|
||||||
are a work-in-progress representation of the work so far. The Quality team will be
|
below are a work-in-progress representation of the work so far. The Quality team
|
||||||
certifying this environment in late 2019. The specifications may be adjusted
|
will be certifying this environment in late 2019. The specifications may be
|
||||||
prior to certification based on performance testing.
|
adjusted prior to certification based on performance testing.
|
||||||
|
|
||||||
TBD: Add specs
|
TBD: Add specs
|
||||||
|
|
|
@ -106,13 +106,15 @@ end
|
||||||
Using `any_instance` to stub a method (elasticsearch_indexing) that has been defined on a prepended module (EE::ApplicationSetting) is not supported.
|
Using `any_instance` to stub a method (elasticsearch_indexing) that has been defined on a prepended module (EE::ApplicationSetting) is not supported.
|
||||||
```
|
```
|
||||||
|
|
||||||
### Alternative: `expect_next_instance_of`
|
### Alternative: `expect_next_instance_of` or `allow_next_instance_of`
|
||||||
|
|
||||||
Instead of writing:
|
Instead of writing:
|
||||||
|
|
||||||
```ruby
|
```ruby
|
||||||
# Don't do this:
|
# Don't do this:
|
||||||
expect_any_instance_of(Project).to receive(:add_import_job)
|
expect_any_instance_of(Project).to receive(:add_import_job)
|
||||||
|
|
||||||
|
allow_any_instance_of(Project).to receive(:add_import_job)
|
||||||
```
|
```
|
||||||
|
|
||||||
We could write:
|
We could write:
|
||||||
|
@ -122,10 +124,14 @@ We could write:
|
||||||
expect_next_instance_of(Project) do |project|
|
expect_next_instance_of(Project) do |project|
|
||||||
expect(project).to receive(:add_import_job)
|
expect(project).to receive(:add_import_job)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
allow_next_instance_of(Project) do |project|
|
||||||
|
allow(project).to receive(:add_import_job)
|
||||||
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
If we also want to expect the instance was initialized with some particular
|
If we also want to initialized the instance with some particular arguments, we
|
||||||
arguments, we could also pass it to `expect_next_instance_of` like:
|
could also pass it like:
|
||||||
|
|
||||||
```ruby
|
```ruby
|
||||||
# Do this:
|
# Do this:
|
||||||
|
|
|
@ -24,6 +24,9 @@ You can also reply to a comment notification email to reply to the comment if
|
||||||
creates another standard comment. Replying to a threaded comment creates a reply in the thread. Email replies support
|
creates another standard comment. Replying to a threaded comment creates a reply in the thread. Email replies support
|
||||||
[Markdown] and [quick actions], just as if you replied from the web.
|
[Markdown] and [quick actions], just as if you replied from the web.
|
||||||
|
|
||||||
|
NOTE: **Note:**
|
||||||
|
There is a limit of 5,000 comments for every object.
|
||||||
|
|
||||||
## Resolvable comments and threads
|
## Resolvable comments and threads
|
||||||
|
|
||||||
> **Notes:**
|
> **Notes:**
|
||||||
|
|
|
@ -9941,6 +9941,9 @@ msgstr ""
|
||||||
msgid "Maximum job timeout has a value which could not be accepted"
|
msgid "Maximum job timeout has a value which could not be accepted"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Maximum number of comments exceeded"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Maximum number of mirrors that can be synchronizing at the same time."
|
msgid "Maximum number of mirrors that can be synchronizing at the same time."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
|
@ -70,6 +70,37 @@ describe Note do
|
||||||
is_expected.to be_valid
|
is_expected.to be_valid
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe 'max notes limit' do
|
||||||
|
let_it_be(:noteable) { create(:issue) }
|
||||||
|
let_it_be(:existing_note) { create(:note, project: noteable.project, noteable: noteable) }
|
||||||
|
|
||||||
|
before do
|
||||||
|
stub_const('Noteable::MAX_NOTES_LIMIT', 1)
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when creating a system note' do
|
||||||
|
subject { build(:system_note, project: noteable.project, noteable: noteable) }
|
||||||
|
|
||||||
|
it { is_expected.to be_valid }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when creating a user note' do
|
||||||
|
subject { build(:note, project: noteable.project, noteable: noteable) }
|
||||||
|
|
||||||
|
it { is_expected.not_to be_valid }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when updating an existing note on a noteable that already exceeds the limit' do
|
||||||
|
subject { existing_note }
|
||||||
|
|
||||||
|
before do
|
||||||
|
create(:system_note, project: noteable.project, noteable: noteable)
|
||||||
|
end
|
||||||
|
|
||||||
|
it { is_expected.to be_valid }
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "Commit notes" do
|
describe "Commit notes" do
|
||||||
|
|
|
@ -90,7 +90,7 @@ RSpec.configure do |config|
|
||||||
config.include StubFeatureFlags
|
config.include StubFeatureFlags
|
||||||
config.include StubGitlabCalls
|
config.include StubGitlabCalls
|
||||||
config.include StubGitlabData
|
config.include StubGitlabData
|
||||||
config.include ExpectNextInstanceOf
|
config.include NextInstanceOf
|
||||||
config.include TestEnv
|
config.include TestEnv
|
||||||
config.include Devise::Test::ControllerHelpers, type: :controller
|
config.include Devise::Test::ControllerHelpers, type: :controller
|
||||||
config.include Devise::Test::IntegrationHelpers, type: :feature
|
config.include Devise::Test::IntegrationHelpers, type: :feature
|
||||||
|
|
|
@ -1,15 +0,0 @@
|
||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
module ExpectNextInstanceOf
|
|
||||||
def expect_next_instance_of(klass, *new_args)
|
|
||||||
receive_new = receive(:new)
|
|
||||||
receive_new.with(*new_args) if new_args.any?
|
|
||||||
|
|
||||||
expect(klass).to receive_new
|
|
||||||
.and_wrap_original do |method, *original_args|
|
|
||||||
method.call(*original_args).tap do |instance|
|
|
||||||
yield(instance)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module NextInstanceOf
|
||||||
|
def expect_next_instance_of(klass, *new_args)
|
||||||
|
stub_new(expect(klass), *new_args) do |expectation|
|
||||||
|
yield(expectation)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def allow_next_instance_of(klass, *new_args)
|
||||||
|
stub_new(allow(klass), *new_args) do |allowance|
|
||||||
|
yield(allowance)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def stub_new(target, *new_args)
|
||||||
|
receive_new = receive(:new)
|
||||||
|
receive_new.with(*new_args) if new_args.any?
|
||||||
|
|
||||||
|
target.to receive_new.and_wrap_original do |method, *original_args|
|
||||||
|
method.call(*original_args).tap do |instance|
|
||||||
|
yield(instance)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in New Issue