Commit 1fed5082 authored by Yorick Peterse's avatar Yorick Peterse Committed by Rémy Coutable

Merge branch 'use-project-id-in-repo-cache' into 'master'

Use project ID in repository cache to prevent stale data from persisting across projects

See merge request !5460
Signed-off-by: default avatarRémy Coutable <remy@rymai.me>
parent 54b71feb
...@@ -4,6 +4,7 @@ v 8.10.2 (unreleased) ...@@ -4,6 +4,7 @@ v 8.10.2 (unreleased)
- User can now search branches by name. !5144 - User can now search branches by name. !5144
- Add branch or tag icon to ref in builds page. !5434 - Add branch or tag icon to ref in builds page. !5434
- Fix backup restore. !5459 - Fix backup restore. !5459
- Use project ID in repository cache to prevent stale data from persisting across projects. !5460
- Don't show comment button in gutter of diffs on MR discussion tab - Don't show comment button in gutter of diffs on MR discussion tab
v 8.10.1 v 8.10.1
......
...@@ -1049,7 +1049,7 @@ class Repository ...@@ -1049,7 +1049,7 @@ class Repository
private private
def cache def cache
@cache ||= RepositoryCache.new(path_with_namespace) @cache ||= RepositoryCache.new(path_with_namespace, @project.id)
end end
def head_exists? def head_exists?
......
# Interface to the Redis-backed cache store used by the Repository model # Interface to the Redis-backed cache store used by the Repository model
class RepositoryCache class RepositoryCache
attr_reader :namespace, :backend attr_reader :namespace, :backend, :project_id
def initialize(namespace, backend = Rails.cache) def initialize(namespace, project_id, backend = Rails.cache)
@namespace = namespace @namespace = namespace
@backend = backend @backend = backend
@project_id = project_id
end end
def cache_key(type) def cache_key(type)
"#{type}:#{namespace}" "#{type}:#{namespace}:#{project_id}"
end end
def expire(key) def expire(key)
......
require_relative '../../lib/repository_cache' require 'spec_helper'
describe RepositoryCache, lib: true do describe RepositoryCache, lib: true do
let(:project) { create(:project) }
let(:backend) { double('backend').as_null_object } let(:backend) { double('backend').as_null_object }
let(:cache) { RepositoryCache.new('example', backend) } let(:cache) { RepositoryCache.new('example', project.id, backend) }
describe '#cache_key' do describe '#cache_key' do
it 'includes the namespace' do it 'includes the namespace' do
expect(cache.cache_key(:foo)).to eq 'foo:example' expect(cache.cache_key(:foo)).to eq "foo:example:#{project.id}"
end end
end end
describe '#expire' do describe '#expire' do
it 'expires the given key from the cache' do it 'expires the given key from the cache' do
cache.expire(:foo) cache.expire(:foo)
expect(backend).to have_received(:delete).with('foo:example') expect(backend).to have_received(:delete).with("foo:example:#{project.id}")
end end
end end
describe '#fetch' do describe '#fetch' do
it 'fetches the given key from the cache' do it 'fetches the given key from the cache' do
cache.fetch(:bar) cache.fetch(:bar)
expect(backend).to have_received(:fetch).with('bar:example') expect(backend).to have_received(:fetch).with("bar:example:#{project.id}")
end end
it 'accepts a block' do it 'accepts a block' do
p = -> {} p = -> {}
cache.fetch(:baz, &p) cache.fetch(:baz, &p)
expect(backend).to have_received(:fetch).with('baz:example', &p) expect(backend).to have_received(:fetch).with("baz:example:#{project.id}", &p)
end end
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