mirror of https://github.com/codevalet/canary
Refactoring the access to the Jenkins services through a caching DAO layer
MiniCache is not thread-safe (derp) so smashing a Concurrent::Hash into it should solve that problem RUBY AMIRITE
This commit is contained in:
parent
ce0ba7e520
commit
1ed83a6b72
|
@ -50,3 +50,4 @@ build-iPhoneSimulator/
|
|||
# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
|
||||
.rvmrc
|
||||
vendor/
|
||||
*.html
|
||||
|
|
5
Gemfile
5
Gemfile
|
@ -1,7 +1,10 @@
|
|||
source 'https://rubygems.org'
|
||||
|
||||
gem 'concurrent-ruby'
|
||||
gem 'faraday'
|
||||
gem 'faraday_middleware'
|
||||
gem 'haml'
|
||||
gem 'httparty'
|
||||
gem 'mini_cache'
|
||||
gem 'puma'
|
||||
gem 'sentry-raven'
|
||||
gem 'sentry-api'
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
concurrent-ruby (1.0.5)
|
||||
diff-lcs (1.3)
|
||||
faraday (0.13.1)
|
||||
multipart-post (>= 1.2, < 3)
|
||||
faraday_middleware (0.12.2)
|
||||
faraday (>= 0.7.4, < 1.0)
|
||||
haml (5.0.2)
|
||||
temple (>= 0.8.0)
|
||||
tilt
|
||||
|
@ -14,6 +17,7 @@ GEM
|
|||
httparty (0.15.6)
|
||||
multi_xml (>= 0.5.2)
|
||||
mimemagic (0.3.2)
|
||||
mini_cache (1.1.0)
|
||||
multi_xml (0.6.0)
|
||||
multipart-post (2.0.0)
|
||||
mustermann (1.0.1)
|
||||
|
@ -50,8 +54,11 @@ PLATFORMS
|
|||
ruby
|
||||
|
||||
DEPENDENCIES
|
||||
concurrent-ruby
|
||||
faraday
|
||||
faraday_middleware
|
||||
haml
|
||||
httparty
|
||||
mini_cache
|
||||
puma
|
||||
rspec
|
||||
sentry-api
|
||||
|
|
|
@ -12,6 +12,9 @@ pipeline {
|
|||
steps {
|
||||
sh 'make check'
|
||||
}
|
||||
always {
|
||||
archiveArtifacts 'rspec.html'
|
||||
}
|
||||
}
|
||||
stage('Build container') {
|
||||
steps {
|
||||
|
|
5
Makefile
5
Makefile
|
@ -4,7 +4,10 @@ all: check container
|
|||
check: spec check-container
|
||||
|
||||
spec: depends
|
||||
./scripts/ruby bundle exec rspec -c
|
||||
./scripts/ruby bundle exec rspec -c \
|
||||
--order random \
|
||||
--format progress \
|
||||
--format html --out rspec.html
|
||||
|
||||
depends: Gemfile
|
||||
./scripts/ruby bundle install
|
||||
|
|
|
@ -5,7 +5,7 @@ require 'raven'
|
|||
require 'sinatra/base'
|
||||
require 'sentry-api'
|
||||
|
||||
require 'canary/jenkins'
|
||||
require 'canary/dao/jenkins'
|
||||
|
||||
module CodeValet
|
||||
module Canary
|
||||
|
@ -35,7 +35,7 @@ module CodeValet
|
|||
:layout => :_base,
|
||||
:locals => {
|
||||
:projects => projects,
|
||||
:jenkins => Jenkins,
|
||||
:jenkins => DAO::Jenkins.new,
|
||||
}
|
||||
end
|
||||
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
require 'concurrent/hash'
|
||||
require 'mini_cache'
|
||||
|
||||
module CodeValet
|
||||
module Canary
|
||||
# The DAO module contains some data-access objects which are to be used
|
||||
# from the web tier.
|
||||
module DAO
|
||||
# Unless otherwise specified, cached entries should "live" for this
|
||||
# number of seconds
|
||||
DEFAULT_CACHE_SECONDS = 120
|
||||
|
||||
# Access the caching object
|
||||
#
|
||||
# @returs [MiniCache::Store]
|
||||
def self.cache
|
||||
return @cache unless @cache.nil?
|
||||
|
||||
@cache = MiniCache::Store.new
|
||||
@cache.instance_variable_set(:@data, Concurrent::Hash.new)
|
||||
return @cache
|
||||
end
|
||||
|
||||
# Reset the cache, primarily intended for testing
|
||||
def self.clear_cache
|
||||
@cache = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,50 @@
|
|||
require 'faraday'
|
||||
require 'canary/dao'
|
||||
|
||||
module CodeValet::Canary::DAO
|
||||
class Jenkins
|
||||
# Base URL to contrict
|
||||
URL_BASE = ENV['JENKINS_URL_BASE'] || 'https://codevalet.io'
|
||||
CACHE_SECONDS = 300
|
||||
|
||||
attr_reader :error
|
||||
|
||||
def errored?
|
||||
return !@error.nil?
|
||||
end
|
||||
|
||||
def rebuiltAlpha
|
||||
return cache.get_or_set('rebuiltAlpha', :expires_in => CACHE_SECONDS) do
|
||||
rebuiltFor('codevalet')
|
||||
end
|
||||
end
|
||||
|
||||
def rebuiltGA
|
||||
return cache.get_or_set('rebuiltGA', :expires_in => CACHE_SECONDS) do
|
||||
rebuiltFor('rtyler')
|
||||
end
|
||||
end
|
||||
|
||||
# Method for directly querying a Jenkins instance to ask when it was last
|
||||
# rebuilt
|
||||
#
|
||||
# @return [String] response from the server if we reached it
|
||||
# @return [nil] nil on no response, #errored? should be set
|
||||
def rebuiltFor(user)
|
||||
# NOTE: worth investigating whether Jenkins will provide the appropriate
|
||||
# caching headers to
|
||||
url = "#{URL_BASE}/u/#{user}/userContent/builtOn.txt"
|
||||
response = Faraday.get(url)
|
||||
if response.success?
|
||||
return response.body
|
||||
end
|
||||
@error = response.status
|
||||
return nil
|
||||
end
|
||||
|
||||
private
|
||||
def cache
|
||||
return CodeValet::Canary::DAO.cache
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,27 +0,0 @@
|
|||
require 'httparty'
|
||||
|
||||
module CodeValet
|
||||
module Canary
|
||||
class Jenkins
|
||||
URL_BASE = ENV['JENKINS_URL_BASE'] || 'https://codevalet.io'
|
||||
|
||||
# https://codevalet.io/u/codevalet/userContent/builtOn.txt
|
||||
def self.rebuiltAlpha
|
||||
return self.rebuiltUrlFor('codevalet')
|
||||
end
|
||||
|
||||
def self.rebuiltGa
|
||||
return self.rebuiltUrlFor('rtyler')
|
||||
end
|
||||
|
||||
def self.rebuiltUrlFor(user)
|
||||
url = "#{URL_BASE}/u/#{user}/userContent/builtOn.txt"
|
||||
response = HTTParty.get(url)
|
||||
if response.ok?
|
||||
return response.body
|
||||
end
|
||||
return 'failed to retrieve last built information..'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,43 @@
|
|||
require 'spec_helper'
|
||||
|
||||
require 'canary/dao/jenkins'
|
||||
|
||||
describe CodeValet::Canary::DAO::Jenkins do
|
||||
before :each do
|
||||
CodeValet::Canary::DAO.clear_cache
|
||||
end
|
||||
|
||||
context 'a bare instance' do
|
||||
it { should_not be_errored }
|
||||
|
||||
context 'with a stubbed network call' do
|
||||
let(:response) { 'stubbed!' }
|
||||
before :each do
|
||||
expect(subject).to receive(:rebuiltFor).and_return(response)
|
||||
end
|
||||
|
||||
it 'provides a response on #rebuiltAlpha' do
|
||||
expect(subject.rebuiltAlpha).to eql(response)
|
||||
end
|
||||
|
||||
it 'provides a response on #rebuiltGA' do
|
||||
expect(subject.rebuiltGA).to eql(response)
|
||||
end
|
||||
|
||||
it 'should cache subsequent calls on #rebuiltAlpha' do
|
||||
3.times do
|
||||
expect(subject.rebuiltAlpha).to eql(response)
|
||||
end
|
||||
end
|
||||
|
||||
it 'should cache subsequent calls on #rebuiltGA' do
|
||||
3.times do
|
||||
expect(subject.rebuiltGA).to eql(response)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'with network errors' do
|
||||
end
|
||||
end
|
|
@ -0,0 +1,8 @@
|
|||
require 'spec_helper'
|
||||
|
||||
require 'canary/dao'
|
||||
|
||||
describe CodeValet::Canary::DAO do
|
||||
it { should respond_to :cache }
|
||||
it { should respond_to :clear_cache }
|
||||
end
|
|
@ -0,0 +1,3 @@
|
|||
require 'rspec'
|
||||
|
||||
$LOAD_PATH.unshift << File.expand_path(File.dirname(__FILE__) + '/../app')
|
|
@ -31,7 +31,7 @@
|
|||
general availability
|
||||
channel was last rebuilt on:
|
||||
%code
|
||||
= jenkins.rebuiltGa
|
||||
= jenkins.rebuiltGA
|
||||
|
||||
.row
|
||||
.col-md-12
|
||||
|
|
Loading…
Reference in New Issue