summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZ.J. van de Weg <git@zjvandeweg.nl>2017-05-12 15:19:27 +0200
committerZ.J. van de Weg <git@zjvandeweg.nl>2017-05-22 21:55:43 +0200
commitebede2b3ff1c2b089529c4f9d6268641580e280b (patch)
tree08d0463762501180bf45444cd88cacf085e9bcd4
parent50a00442285973a390fa448d189ee43cd700d668 (diff)
downloadgitlab-ce-ebede2b3ff1c2b089529c4f9d6268641580e280b.tar.gz
Use etag caching for environments JSON
For the index view, the environments can now be requested every 15 seconds. Any transition state of a projects environments will trigger a cache invalidation action. Fixes gitlab-org/gitlab-ce#31701
-rw-r--r--app/controllers/projects/environments_controller.rb2
-rw-r--r--app/models/environment.rb11
-rw-r--r--changelogs/unreleased/zj-realtime-env-list.yml4
-rw-r--r--lib/gitlab/etag_caching/router.rb9
-rw-r--r--spec/lib/gitlab/etag_caching/router_spec.rb10
-rw-r--r--spec/models/environment_spec.rb10
6 files changed, 43 insertions, 3 deletions
diff --git a/app/controllers/projects/environments_controller.rb b/app/controllers/projects/environments_controller.rb
index fd57afbd05f..537c74d5231 100644
--- a/app/controllers/projects/environments_controller.rb
+++ b/app/controllers/projects/environments_controller.rb
@@ -15,6 +15,8 @@ class Projects::EnvironmentsController < Projects::ApplicationController
respond_to do |format|
format.html
format.json do
+ Gitlab::PollingInterval.set_header(response, interval: 15_000)
+
render json: {
environments: EnvironmentSerializer
.new(project: @project, current_user: @current_user)
diff --git a/app/models/environment.rb b/app/models/environment.rb
index 61572d8d69a..07722d9a59e 100644
--- a/app/models/environment.rb
+++ b/app/models/environment.rb
@@ -57,6 +57,10 @@ class Environment < ActiveRecord::Base
state :available
state :stopped
+
+ after_transition do |environment|
+ environment.expire_etag_cache
+ end
end
def predefined_variables
@@ -196,6 +200,13 @@ class Environment < ActiveRecord::Base
[external_url, public_path].join('/')
end
+ def expire_etag_cache
+ Gitlab::EtagCaching::Store.new.tap do |store|
+ store.touch(Gitlab::Routing.url_helpers
+ .namespace_project_environments_path(project.namespace, project))
+ end
+ end
+
private
# Slugifying a name may remove the uniqueness guarantee afforded by it being
diff --git a/changelogs/unreleased/zj-realtime-env-list.yml b/changelogs/unreleased/zj-realtime-env-list.yml
new file mode 100644
index 00000000000..6460d17edc9
--- /dev/null
+++ b/changelogs/unreleased/zj-realtime-env-list.yml
@@ -0,0 +1,4 @@
+---
+title: Make environment table realtime
+merge_request: 11333
+author:
diff --git a/lib/gitlab/etag_caching/router.rb b/lib/gitlab/etag_caching/router.rb
index ba31041d0c1..01bf578c570 100644
--- a/lib/gitlab/etag_caching/router.rb
+++ b/lib/gitlab/etag_caching/router.rb
@@ -7,9 +7,10 @@ module Gitlab
# - Don't contain a reserved word (expect for the words used in the
# regex itself)
# - Ending in `noteable/issue/<id>/notes` for the `issue_notes` route
- # - Ending in `issues/id`/realtime_changes` for the `issue_title` route
+ # - Ending in `issues/id`/rendered_title` for the `issue_title` route
USED_IN_ROUTES = %w[noteable issue notes issues realtime_changes
- commit pipelines merge_requests new].freeze
+ commit pipelines merge_requests new
+ environments].freeze
RESERVED_WORDS = DynamicPathValidator::WILDCARD_ROUTES - USED_IN_ROUTES
RESERVED_WORDS_REGEX = Regexp.union(*RESERVED_WORDS)
ROUTES = [
@@ -40,6 +41,10 @@ module Gitlab
Gitlab::EtagCaching::Router::Route.new(
%r(^(?!.*(#{RESERVED_WORDS})).*/pipelines/\d+\.json\z),
'project_pipeline'
+ ),
+ Gitlab::EtagCaching::Router::Route.new(
+ %r(^(?!.*(#{RESERVED_WORDS_REGEX})).*/environments\.json\z),
+ 'environments'
)
].freeze
diff --git a/spec/lib/gitlab/etag_caching/router_spec.rb b/spec/lib/gitlab/etag_caching/router_spec.rb
index 5ae4a19263c..456bd9898ea 100644
--- a/spec/lib/gitlab/etag_caching/router_spec.rb
+++ b/spec/lib/gitlab/etag_caching/router_spec.rb
@@ -77,6 +77,16 @@ describe Gitlab::EtagCaching::Router do
expect(result).to be_blank
end
+ it 'matches the environments path' do
+ env = build_env(
+ '/my-group/my-project/environments.json'
+ )
+
+ result = described_class.match(env)
+
+ expect(result).to be_blank
+ end
+
def build_env(path)
{ 'PATH_INFO' => path }
end
diff --git a/spec/models/environment_spec.rb b/spec/models/environment_spec.rb
index 12519de8636..768f557bb9f 100644
--- a/spec/models/environment_spec.rb
+++ b/spec/models/environment_spec.rb
@@ -1,7 +1,7 @@
require 'spec_helper'
describe Environment, models: true do
- let(:project) { create(:empty_project) }
+ set(:project) { create(:empty_project) }
subject(:environment) { create(:environment, project: project) }
it { is_expected.to belong_to(:project) }
@@ -34,6 +34,14 @@ describe Environment, models: true do
end
end
+ describe 'state machine' do
+ it 'invalidates the cache after a change' do
+ expect(environment).to receive(:expire_etag_cache)
+
+ environment.stop
+ end
+ end
+
describe '#nullify_external_url' do
it 'replaces a blank url with nil' do
env = build(:environment, external_url: "")