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
This commit is contained in:
Z.J. van de Weg 2017-05-12 15:19:27 +02:00
parent 50a0044228
commit ebede2b3ff
6 changed files with 43 additions and 3 deletions

View file

@ -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)

View file

@ -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

View file

@ -0,0 +1,4 @@
---
title: Make environment table realtime
merge_request: 11333
author:

View file

@ -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

View file

@ -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

View file

@ -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: "")