This repository has been archived by the owner on Mar 14, 2018. It is now read-only.
/
cache.rb
109 lines (94 loc) · 2.78 KB
/
cache.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
require 'net/http'
require 'dalli'
module BundlerApi
FastlyClient = Struct.new(:service_id, :base_url, :api_key) do
def purge_key(key)
uri = URI("https://api.fastly.com/service/#{service_id}/purge/#{key}")
http(uri).post uri.request_uri, nil, "Fastly-Key" => api_key
end
def purge_path(path)
uri = URI("#{base_url}#{path}")
http(uri).send_request 'PURGE', uri.path, nil, "Fastly-Key" => api_key
end
def http(uri)
return unless ENV['RACK_ENV'] == "production"
Net::HTTP.new(uri.host, uri.port).tap do |http|
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
end
end
end
class CacheInvalidator
def initialize(memcached: nil, cdn: nil)
@memcached_client = memcached
@cdn_client = cdn
end
def verify_responses!(responses)
failures = responses.compact.select {|r| r.code >= 400 }
return if failures.empty?
failures.map! do |response|
"- #{response.uri} => #{response.code}, #{response.body}"
end
raise "The following cache purge requests failed:\n#{failures.join("\n")}"
end
def purge_specs
keys = %w(dependencies)
paths = %w(
/latest_specs.4.8.gz
/specs.4.8.gz
/prerelease_specs.4.8.gz
/versions
/names
)
puts "Purging #{(keys + paths).join(', ')}"
responses = keys.map {|k| cdn_client.purge_key(k) }
responses += paths.map {|k| cdn_client.purge_path(k) }
verify_responses!(responses)
end
def purge_gem(name)
purge_memory_cache(name)
paths = %W(
/quick/Marshal.4.8/#{name}.gemspec.rz
/gems/#{name}.gem
/info/#{name}
)
puts "Purging #{paths.join(', ')}"
responses = paths.map {|k| cdn_client.purge_path(k) }
verify_responses!(responses)
end
def purge_memory_cache(name)
memcached_client.delete "deps/v1/#{name}"
end
def cdn_client
@cdn_client ||= if ENV['FASTLY_SERVICE_ID']
FastlyClient.new(
ENV['FASTLY_SERVICE_ID'],
ENV['FASTLY_BASE_URL'],
ENV['FASTLY_API_KEY']
)
else
# Create a mock Fastly client
Class.new do
def purge_key(key); end
def purge_path(path); end
end.new
end
end
def memcached_client
@memcached_client ||= if ENV["MEMCACHEDCLOUD_SERVERS"]
servers = (ENV["MEMCACHEDCLOUD_SERVERS"] || "").split(",")
Dalli::Client.new(
servers, {
username: ENV["MEMCACHEDCLOUD_USERNAME"],
password: ENV["MEMCACHEDCLOUD_PASSWORD"],
failover: true,
socket_timeout: 1.5,
socket_failure_delay: 0.2
}
)
else
Dalli::Client.new
end
end
end
end