Commit 09a68a2e authored by Sean McGivern's avatar Sean McGivern

Merge branch 'ee-introduce-base-polling-interval' into 'master'

EE port of Introduce "polling_interval_multiplier" as application setting

See merge request !1539
parents b35ca926 2d52f2ab
......@@ -142,6 +142,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
:unique_ips_limit_enabled,
:version_check_enabled,
:terminal_max_session_time,
:polling_interval_multiplier,
disabled_oauth_sign_in_sources: [],
import_sources: [],
......
......@@ -144,6 +144,10 @@ class ApplicationSetting < ActiveRecord::Base
presence: true,
numericality: { only_integer: true, greater_than_or_equal_to: 0 }
validates :polling_interval_multiplier,
presence: true,
numericality: { greater_than_or_equal_to: 0 }
validates :minimum_mirror_sync_time,
presence: true,
inclusion: { in: Gitlab::Mirror::SYNC_TIME_OPTIONS.values }
......@@ -252,7 +256,8 @@ class ApplicationSetting < ActiveRecord::Base
signup_enabled: Settings.gitlab['signup_enabled'],
terminal_max_session_time: 0,
two_factor_grace_period: 48,
user_default_external: false
user_default_external: false,
polling_interval_multiplier: 1
}
end
......
......@@ -642,6 +642,20 @@
Maximum time for web terminal websocket connection (in seconds).
0 for unlimited.
%fieldset
%legend Real-time features
.form-group
= f.label :polling_interval_multiplier, 'Polling interval multiplier', class: 'control-label col-sm-2'
.col-sm-10
= f.text_field :polling_interval_multiplier, class: 'form-control'
.help-block
Change this value to influence how frequently the GitLab UI polls for updates.
If you set the value to 2 all polling intervals are multiplied
by 2, which means that polling happens half as frequently.
The multiplier can also have a decimal value.
The default value (1) is a reasonable choice for the majority of GitLab
installations. Set to 0 to completely disable polling.
- if Gitlab::Geo.license_allows?
%fieldset
%legend GitLab Geo
......
---
title: Introduce "polling_interval_multiplier" as application setting
merge_request: 10280
author:
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
class AddPollingIntervalMultiplierToApplicationSettings < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
DOWNTIME = false
# When a migration requires downtime you **must** uncomment the following
# constant and define a short and easy to understand explanation as to why the
# migration requires downtime.
# DOWNTIME_REASON = ''
# When using the methods "add_concurrent_index" or "add_column_with_default"
# you must disable the use of transactions as these methods can not run in an
# existing transaction. When using "add_concurrent_index" make sure that this
# method is the _only_ method called in the migration, any other changes
# should go in a separate migration. This ensures that upon failure _only_ the
# index creation fails and can be retried or reverted easily.
#
# To disable transactions uncomment the following line and remove these
# comments:
disable_ddl_transaction!
def up
add_column_with_default :application_settings, :polling_interval_multiplier, :decimal, default: 1, allow_null: false
end
def down
remove_column :application_settings, :polling_interval_multiplier
end
end
......@@ -11,7 +11,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20170328010804) do
ActiveRecord::Schema.define(version: 20170329124448) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
......@@ -118,6 +118,7 @@ ActiveRecord::Schema.define(version: 20170328010804) do
t.integer "shared_runners_minutes", default: 0, null: false
t.integer "repository_size_limit", limit: 8, default: 0
t.integer "terminal_max_session_time", default: 0, null: false
t.decimal "polling_interval_multiplier", default: 1.0, null: false
t.integer "unique_ips_limit_per_user"
t.integer "unique_ips_limit_time_window"
t.boolean "unique_ips_limit_enabled", default: false, null: false
......
......@@ -47,7 +47,8 @@ Example response:
"koding_url": null,
"plantuml_enabled": false,
"plantuml_url": null,
"terminal_max_session_time": 0
"terminal_max_session_time": 0,
"polling_interval_multiplier": 1.0
}
```
......@@ -96,6 +97,7 @@ PUT /application/settings
| `plantuml_enabled` | boolean | no | Enable PlantUML integration. Default is `false`. |
| `plantuml_url` | string | yes (if `plantuml_enabled` is `true`) | The PlantUML instance URL for integration. |
| `terminal_max_session_time` | integer | no | Maximum time for web terminal websocket connection (in seconds). Set to 0 for unlimited time. |
| `polling_interval_multiplier` | decimal | no | Interval multiplier used by endpoints that perform polling. Set to 0 to disable polling. |
```bash
curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/application/settings?signup_enabled=false&default_project_visibility=internal
......@@ -132,6 +134,7 @@ Example response:
"koding_url": null,
"plantuml_enabled": false,
"plantuml_url": null,
"terminal_max_session_time": 0
"terminal_max_session_time": 0,
"polling_interval_multiplier": 1.0
}
```
......@@ -636,6 +636,7 @@ module API
expose :plantuml_enabled
expose :plantuml_url
expose :terminal_max_session_time
expose :polling_interval_multiplier
end
class Release < Grape::Entity
......
......@@ -109,7 +109,7 @@ module API
requires :housekeeping_full_repack_period, type: Integer, desc: "Number of Git pushes after which a full 'git repack' is run."
requires :housekeeping_gc_period, type: Integer, desc: "Number of Git pushes after which 'git gc' is run."
end
optional :terminal_max_session_time, type: Integer, desc: 'Maximum time for web terminal websocket connection (in seconds). Set to 0 for unlimited time.'
optional :polling_interval_multiplier, type: BigDecimal, desc: 'Interval multiplier used by endpoints that perform polling. Set to 0 to disable polling.'
# GitLab-EE specific settings
optional :help_text, type: String, desc: 'GitLab server administrator information'
optional :elasticsearch_indexing, type: Boolean, desc: 'Enable Elasticsearch indexing'
......@@ -141,6 +141,7 @@ module API
:akismet_enabled, :admin_notification_email, :sentry_enabled,
:repository_checks_enabled, :koding_enabled, :housekeeping_enabled, :terminal_max_session_time, :plantuml_enabled,
:version_check_enabled, :email_author_in_body, :html_emails_enabled,
:polling_interval_multiplier,
# GitLab-EE specific settings
:help_text, :elasticsearch_indexing, :usage_ping_enabled,
:repository_storages, :repository_size_limit
......
......@@ -18,8 +18,7 @@ module Gitlab
if_none_match = env['HTTP_IF_NONE_MATCH']
if if_none_match == etag
Gitlab::Metrics.add_event(:etag_caching_cache_hit)
[304, { 'ETag' => etag }, ['']]
handle_cache_hit(etag)
else
track_cache_miss(if_none_match, cached_value_present)
......@@ -52,6 +51,14 @@ module Gitlab
%Q{W/"#{value}"}
end
def handle_cache_hit(etag)
Gitlab::Metrics.add_event(:etag_caching_cache_hit)
status_code = Gitlab::PollingInterval.polling_enabled? ? 304 : 429
[status_code, { 'ETag' => etag }, ['']]
end
def track_cache_miss(if_none_match, cached_value_present)
if if_none_match.blank?
Gitlab::Metrics.add_event(:etag_caching_header_missing)
......
module Gitlab
class PollingInterval
include Gitlab::CurrentSettings
HEADER_NAME = 'Poll-Interval'.freeze
def self.set_header(response, interval:)
if polling_enabled?
multiplier = current_application_settings.polling_interval_multiplier
value = (interval * multiplier).to_i
else
value = -1
end
response.headers[HEADER_NAME] = value
end
def self.polling_enabled?
!current_application_settings.polling_interval_multiplier.zero?
end
end
end
......@@ -99,6 +99,19 @@ describe Gitlab::EtagCaching::Middleware do
middleware.call(build_env(path, if_none_match))
end
context 'when polling is disabled' do
before do
allow(Gitlab::PollingInterval).to receive(:polling_enabled?).
and_return(false)
end
it 'returns status code 429' do
status, _, _ = middleware.call(build_env(path, if_none_match))
expect(status).to eq 429
end
end
end
context 'when If-None-Match header does not match ETag in store' do
......
require 'spec_helper'
describe Gitlab::PollingInterval, lib: true do
let(:polling_interval) { described_class }
describe '.set_header' do
let(:headers) { {} }
let(:response) { double(headers: headers) }
context 'when polling is disabled' do
before do
stub_application_setting(polling_interval_multiplier: 0)
end
it 'sets value to -1' do
polling_interval.set_header(response, interval: 10_000)
expect(headers['Poll-Interval']).to eq(-1)
end
end
context 'when polling is enabled' do
before do
stub_application_setting(polling_interval_multiplier: 0.33333)
end
it 'applies modifier to base interval' do
polling_interval.set_header(response, interval: 10_000)
expect(headers['Poll-Interval']).to eq(3333)
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