middleman-caching-proxy 0.1.0 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: cefacd267c25aa55daa8c3aab6adba286294d201
4
- data.tar.gz: b02aa54ec0e117b924dedf78d0647d994f1d3d4e
3
+ metadata.gz: 81c6ce51f0c02f5c109266f1a158568dcd3dfc62
4
+ data.tar.gz: 968b0211af2b5c69a92d92fbc47da19c0903ce89
5
5
  SHA512:
6
- metadata.gz: dc4feea092dfe37bf0067a8faf6bd5d5f9289c305c6f10570d4f5e421083a8b0326c448b3bd38c9df79e39a5347de28350670b14e2717515a296d3c4e3414999
7
- data.tar.gz: 24be5f3a39fa8d3d8e10b5f3b27a1d27c83f747bd16996a818a123509fa61951479ad5eeceaf83b2377d2daf9767eb8acf1151e9906bdb256fc31b3c4d6ede0f
6
+ metadata.gz: d612e58dc98456e7a15ac4cbe0200925bba21575ce6df8b2c237d7bbc8b543f4f668975efae5bc5bd3bdfa30cfc54a44dfb3e9a5672c894684c04777043b086b
7
+ data.tar.gz: 23204aae5624bc0d4a3f86248ea084fc03739de55092239782620c2267c9cc297eb0139679e1f0980e1f932b91af8ada5e1ef10a6527c98a6e6fc1b4b04acd93
data/Gemfile CHANGED
@@ -1,4 +1,4 @@
1
- source 'https://rubygems.org'
1
+ source "https://rubygems.org"
2
2
 
3
- # Specify your gem's dependencies in middleman-caching-proxy.gemspec
4
3
  gemspec
4
+
data/README.md CHANGED
@@ -1,8 +1,7 @@
1
- # Middleman::Caching::Proxy
1
+ # Middleman::CachingProxy
2
2
 
3
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/middleman/caching/proxy`. To experiment with that code, run `bin/console` for an interactive prompt.
4
-
5
- TODO: Delete this and the text above, and describe your gem
3
+ Caches the result of `proxy` calls allong with the fingerprint of their inputs.
4
+ If the inputs remain the same, uses the cached version.
6
5
 
7
6
  ## Installation
8
7
 
@@ -22,20 +21,51 @@ Or install it yourself as:
22
21
 
23
22
  ## Usage
24
23
 
25
- TODO: Write usage instructions here
24
+ In `config.rb`:
25
+
26
+ ```ruby
27
+ activate :caching_proxy
28
+
29
+ things.each do |thing|
30
+ proxy_with_cache(
31
+ path: "/things/#{thing.slug}",
32
+ template: "/templates/thing_template.html",
33
+ proxy_options: {locals: {thing: thing}},
34
+ fingerprint: thing.updated_at.to_i
35
+ )
36
+ end
37
+ ```
38
+
39
+ There are 4 required parameters:
40
+
41
+ * `path`: the page path,
42
+ * `template`: the page template,
43
+ * `proxy_options`: options to pass to the `proxy` invocation,
44
+ * `fingerprint`: a value that indicates the 'version' of the item. If this
45
+ value changes, the cached version will be skipped and updated.
26
46
 
27
47
  ## Development
28
48
 
29
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
49
+ After checking out the repo, run `bin/setup` to install dependencies.
50
+ Then, run `rake spec` to run the tests.
51
+ You can also run `bin/console` for an interactive prompt that will allow you
52
+ to experiment.
30
53
 
31
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
54
+ To install this gem onto your local machine, run `bundle exec rake install`.
55
+ To release a new version, update the version number in `version.rb`, and then
56
+ run `bundle exec rake release`, which will create a git tag for the version,
57
+ push git commits and tags, and push the `.gem` file to
58
+ [rubygems.org](https://rubygems.org).
32
59
 
33
60
  ## Contributing
34
61
 
35
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/middleman-caching-proxy. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
36
-
62
+ Bug reports and pull requests are welcome on GitHub at
63
+ https://github.com/joeyates/middleman-caching-proxy. This project is intended
64
+ to be a safe, welcoming space for collaboration, and contributors are expected
65
+ to adhere to the [Contributor Covenant](http://contributor-covenant.org) code
66
+ of conduct.
37
67
 
38
68
  ## License
39
69
 
40
- The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
41
-
70
+ The gem is available as open source under the terms of the
71
+ [MIT License](http://opensource.org/licenses/MIT).
@@ -1,179 +1,7 @@
1
1
  require "middleman-core"
2
- require "middleman-core/sitemap/resource"
3
- require "semantic"
4
2
 
5
- class CacheItem
6
- attr_reader :path
7
- attr_reader :template
8
- attr_reader :proxy_options
9
- attr_reader :fingerprint
3
+ require "middleman/caching_proxy/extension"
10
4
 
11
- def initialize(path:, template:, proxy_options:, fingerprint:)
12
- @path = path
13
- @template = template
14
- @proxy_options = proxy_options
15
- @fingerprint = fingerprint
16
- end
17
- end
18
-
19
- class CachedResource
20
- attr_reader :path
21
- attr_reader :cached_path
22
- attr_reader :build_path
23
-
24
- def initialize(path:, cached_path:, build_path:)
25
- @path = path
26
- @cached_path = cached_path
27
- @build_path = build_path
28
- end
29
-
30
- def destination_path
31
- path[1..-1]
32
- end
33
-
34
- def ext
35
- ""
36
- end
37
-
38
- def ignored?
39
- false # Seems to mean "actualyy include in build?"
40
- end
41
-
42
- def binary?
43
- true # Seems to mean "do a binary copy or make a rack request?"
44
- end
45
-
46
- def source_file
47
- cached_path
48
- end
49
-
50
- def content_type
51
- "text/html"
52
- end
53
- end
54
-
55
- class MiddlemanExtension < ::Middleman::Extension
56
- option :cache_directory,
57
- "tmp/proxy_cache",
58
- "The directory where cache files will be stored"
59
-
60
- if Semantic::Version.new(Middleman::VERSION).major >= 4
61
- expose_to_config :proxy_with_cache
62
- end
63
-
64
- attr_reader :copy_from_cache
65
- attr_reader :copy_to_cache
66
-
67
- def initialize(app, options_hash = {}, &block)
68
- super
69
-
70
- require "fileutils"
71
-
72
- if Semantic::Version.new(Middleman::VERSION).major <= 3
73
- app.send :include, InstanceMethods
74
- end
75
-
76
- @cache_manifest = nil
77
- @copy_from_cache = []
78
- @copy_to_cache = []
79
- end
80
-
81
- def after_configuration
82
- ensure_cache_directory
83
- end
84
-
85
- def after_build(builder)
86
- copy_proxied_files_to_cache
87
- File.open(cache_manifest_path, "w") do |f|
88
- f.write cache.to_json
89
- end
90
- end
91
-
92
- def add(item)
93
- if matches_cached?(item)
94
- copy_from_cache << item
95
- true
96
- else
97
- cache[item.path] = item.fingerprint
98
- copy_to_cache << item
99
- false
100
- end
101
- end
102
-
103
- def manipulate_resource_list(resources)
104
- resources + cached_resources
105
- end
106
-
107
- module InstanceMethods
108
- def proxy_with_cache(path:, template:, proxy_options:, fingerprint:)
109
- item = CacheItem.new(
110
- path: path,
111
- template: template,
112
- proxy_options: proxy_options,
113
- fingerprint: fingerprint
114
- )
115
- will_use_cache = extensions[:caching_proxy].add(item)
116
- if !will_use_cache
117
- proxy item.path, item.template, item.proxy_options
118
- end
119
- end
120
- end
121
-
122
- private
123
-
124
- def matches_cached?(item)
125
- cached_path = cache_path(item.path)
126
- exists = File.exist?(cached_path)
127
- return false if !exists
128
- return false if cache[item.path].nil?
129
- return false if cache[item.path] != item.fingerprint
130
- true
131
- end
132
-
133
- def copy_proxied_files_to_cache
134
- copy_to_cache.each do |item|
135
- cached_path = cache_path(item.path)
136
- build = build_path(item.path)
137
- cache_subdirectory = File.dirname(cached_path)
138
- FileUtils.mkdir_p cache_subdirectory
139
- FileUtils.cp build, cached_path
140
- end
141
- end
142
-
143
- def cached_resources
144
- copy_from_cache.map do |item|
145
- cached_path = cache_path(item.path)
146
- build = build_path(item.path)
147
- CachedResource.new(
148
- path: item.path, cached_path: cached_path, build_path: build
149
- )
150
- end
151
- end
152
-
153
- def cache
154
- return @cache_manifest if @cache_manifest
155
- if File.exist?(cache_manifest_path)
156
- @cache_manifest = JSON.load(File.read(cache_manifest_path))
157
- else
158
- @cache_manifest = {}
159
- end
160
- end
161
-
162
- def cache_manifest_path
163
- cache_path(".cache.json")
164
- end
165
-
166
- def cache_path(path)
167
- ::File.join(options.cache_directory, path)
168
- end
169
-
170
- def build_path(path)
171
- File.join("build", path)
172
- end
173
-
174
- def ensure_cache_directory
175
- FileUtils.mkdir_p options.cache_directory
176
- end
177
- end
178
-
179
- ::Middleman::Extensions.register(:caching_proxy, MiddlemanExtension)
5
+ ::Middleman::Extensions.register(
6
+ :caching_proxy, Middleman::CachingProxy::Extension
7
+ )
@@ -0,0 +1,44 @@
1
+ require "autostruct/wrap"
2
+ require "fileutils"
3
+
4
+ require "middleman/caching_proxy/cache_manifest"
5
+
6
+ class Cache
7
+ def initialize(path:, key:)
8
+ @manifest = nil
9
+ end
10
+ include Autostruct::Wrap
11
+
12
+ def has?(item)
13
+ cached_path = full_path(item: item)
14
+ return false if !::File.exist?(cached_path)
15
+ manifest.has?(item)
16
+ end
17
+
18
+ def add(item:, source:)
19
+ manifest.add item
20
+ cached_path = full_path(item: item)
21
+ copy_in source, cached_path
22
+ end
23
+
24
+ def full_path(item:)
25
+ ::File.join(path, "items", item.path)
26
+ end
27
+
28
+ def save
29
+ manifest.save
30
+ end
31
+
32
+ private
33
+
34
+ def manifest
35
+ @manifest ||= CacheManifest.new(path: path, key: key)
36
+ end
37
+
38
+ def copy_in(source, cached_path)
39
+ cache_subdirectory = ::File.dirname(cached_path)
40
+ FileUtils.mkdir_p cache_subdirectory
41
+
42
+ FileUtils.cp source, cached_path
43
+ end
44
+ end
@@ -0,0 +1,6 @@
1
+ require "autostruct/wrap"
2
+
3
+ class CacheItem
4
+ def initialize(path:, template:, proxy_options:, fingerprint:); end
5
+ include Autostruct::Wrap
6
+ end
@@ -0,0 +1,79 @@
1
+ require "autostruct/wrap"
2
+ require "fileutils"
3
+
4
+ require "middleman/caching_proxy/version"
5
+
6
+ class CacheManifest
7
+ FILENAME = ".manifest.json"
8
+ KEY = "key"
9
+ ITEMS = "items"
10
+ VERSION = "version"
11
+
12
+ def initialize(path:, key:)
13
+ @manifest = nil
14
+ @items = nil
15
+ end
16
+ include Autostruct::Wrap
17
+
18
+ def has?(item)
19
+ items[item.path] == item.fingerprint
20
+ end
21
+
22
+ def add(item)
23
+ items[item.path] = item.fingerprint
24
+ end
25
+
26
+ def save
27
+ ensure_cache_directory
28
+ File.open(manifest_path, "w") do |f|
29
+ f.write build(items: items).to_json
30
+ end
31
+ end
32
+
33
+ private
34
+
35
+ def items
36
+ @items ||= manifest[ITEMS]
37
+ end
38
+
39
+ def manifest_path
40
+ ::File.join(path, FILENAME)
41
+ end
42
+
43
+ def manifest
44
+ return @manifest if @manifest
45
+ @manifest = build
46
+ if File.exist?(manifest_path)
47
+ from_disk = JSON.load(File.read(manifest_path))
48
+ if is_ok?(from_disk)
49
+ @manifest = from_disk
50
+ end
51
+ end
52
+ @manifest
53
+ end
54
+
55
+ def is_ok?(manifest)
56
+ return false if manifest.nil?
57
+ return false if manifest[VERSION] != version
58
+ # Clear cache if key changes
59
+ return false if manifest[KEY] != key
60
+ return false if !manifest[ITEMS].is_a?(Hash)
61
+ true
62
+ end
63
+
64
+ def build(items: [])
65
+ {
66
+ KEY => key,
67
+ ITEMS => items,
68
+ VERSION => version
69
+ }
70
+ end
71
+
72
+ def version
73
+ Middleman::CachingProxy::VERSION
74
+ end
75
+
76
+ def ensure_cache_directory
77
+ FileUtils.mkdir_p path
78
+ end
79
+ end
@@ -0,0 +1,30 @@
1
+ require "autostruct/wrap"
2
+
3
+ class CachedResource
4
+ def initialize(path:, cached_path:, build_path:); end
5
+ include Autostruct::Wrap
6
+
7
+ def destination_path
8
+ path[1..-1]
9
+ end
10
+
11
+ def ext
12
+ ""
13
+ end
14
+
15
+ def ignored?
16
+ false # Seems to mean "actually include in build?"
17
+ end
18
+
19
+ def binary?
20
+ true # Seems to mean "do a binary copy or make a rack request?"
21
+ end
22
+
23
+ def source_file
24
+ cached_path
25
+ end
26
+
27
+ def content_type
28
+ "text/html"
29
+ end
30
+ end
@@ -0,0 +1,102 @@
1
+ require "middleman-core"
2
+ require "semantic"
3
+
4
+ require "middleman/caching_proxy/cache"
5
+ require "middleman/caching_proxy/cache_item"
6
+ require "middleman/caching_proxy/cached_resource"
7
+
8
+ class Middleman::CachingProxy::Extension < ::Middleman::Extension
9
+ option :cache_directory,
10
+ "tmp/proxy_cache",
11
+ "The directory where cache files will be stored"
12
+ option :cache_key,
13
+ nil,
14
+ "A global cache key"
15
+
16
+ if Semantic::Version.new(Middleman::VERSION).major >= 4
17
+ expose_to_config :proxy_with_cache
18
+ end
19
+
20
+ module InstanceMethods
21
+ def proxy_with_cache(path:, template:, proxy_options:, fingerprint:)
22
+ item = CacheItem.new(
23
+ path: path,
24
+ template: template,
25
+ proxy_options: proxy_options,
26
+ fingerprint: fingerprint
27
+ )
28
+ will_use_cache = extensions[:caching_proxy].add(item)
29
+ if !will_use_cache
30
+ proxy item.path, item.template, item.proxy_options
31
+ end
32
+ end
33
+ end
34
+
35
+ attr_reader :copy_from_cache
36
+ attr_reader :add_to_cache
37
+
38
+ def initialize(app, options_hash = {}, &block)
39
+ super
40
+
41
+ if Semantic::Version.new(Middleman::VERSION).major <= 3
42
+ app.send :include, InstanceMethods
43
+ end
44
+
45
+ if !options.cache_key
46
+ raise "Please supply a cache_key value"
47
+ end
48
+
49
+ @copy_from_cache = []
50
+ @add_to_cache = []
51
+ @cache = nil
52
+ end
53
+
54
+ def manipulate_resource_list(resources)
55
+ resources + cached_resources
56
+ end
57
+
58
+ def after_build(_builder)
59
+ copy_new_files_to_cache
60
+ cache.save
61
+ end
62
+
63
+ def add(item)
64
+ if cache.has?(item)
65
+ copy_from_cache << item
66
+ true
67
+ else
68
+ add_to_cache << item
69
+ false
70
+ end
71
+ end
72
+
73
+ private
74
+
75
+ def cache
76
+ @cache ||= Cache.new(path: options.cache_directory, key: options.cache_key)
77
+ end
78
+
79
+ def copy_new_files_to_cache
80
+ add_to_cache.each do |item|
81
+ # Handle directory_indexes extension
82
+ resource = app.sitemap.find_resource_by_path(item.path)
83
+ build_path = relative_build_path(resource.destination_path)
84
+ cache.add item: item, source: build_path
85
+ end
86
+ end
87
+
88
+ def cached_resources
89
+ copy_from_cache.map do |item|
90
+ cached_path = cache.full_path(item: item)
91
+ # TODO: Handle directory_indexes extension
92
+ build_path = relative_build_path(item.path)
93
+ CachedResource.new(
94
+ path: item.path, cached_path: cached_path, build_path: build_path
95
+ )
96
+ end
97
+ end
98
+
99
+ def relative_build_path(path)
100
+ File.join("build", path)
101
+ end
102
+ end
@@ -2,6 +2,6 @@ module Middleman; end
2
2
 
3
3
  module Middleman
4
4
  module CachingProxy
5
- VERSION = "0.1.0"
5
+ VERSION = "0.1.2"
6
6
  end
7
7
  end
@@ -1,7 +1,7 @@
1
1
  # coding: utf-8
2
2
  lib = File.expand_path('../lib', __FILE__)
3
3
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require 'middleman/caching_proxy/version'
4
+ require "middleman/caching_proxy/version"
5
5
 
6
6
  Gem::Specification.new do |spec|
7
7
  spec.name = "middleman-caching-proxy"
@@ -21,6 +21,7 @@ Gem::Specification.new do |spec|
21
21
 
22
22
  spec.add_runtime_dependency "middleman", ">= 3.0.0", "< 4.0.0"
23
23
  spec.add_runtime_dependency "semantic"
24
+ spec.add_runtime_dependency "autostruct"
24
25
 
25
26
  spec.add_development_dependency "bundler", "~> 1.13"
26
27
  spec.add_development_dependency "rake", "~> 10.0"
@@ -1,11 +1,7 @@
1
1
  require "spec_helper"
2
2
 
3
- describe Middleman::Caching::Proxy do
3
+ describe Middleman::CachingProxy do
4
4
  it "has a version number" do
5
5
  expect(Middleman::Caching::Proxy::VERSION).not_to be nil
6
6
  end
7
-
8
- it "does something useful" do
9
- expect(false).to eq(true)
10
- end
11
7
  end
data/spec/spec_helper.rb CHANGED
@@ -1,2 +1,2 @@
1
1
  $LOAD_PATH.unshift File.expand_path("../../lib", __FILE__)
2
- require "middleman/caching/proxy"
2
+ require "middleman/caching_proxy"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: middleman-caching-proxy
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joe Yates
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-11-16 00:00:00.000000000 Z
11
+ date: 2016-11-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: middleman
@@ -44,6 +44,20 @@ dependencies:
44
44
  - - ">="
45
45
  - !ruby/object:Gem::Version
46
46
  version: '0'
47
+ - !ruby/object:Gem::Dependency
48
+ name: autostruct
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
47
61
  - !ruby/object:Gem::Dependency
48
62
  name: bundler
49
63
  requirement: !ruby/object:Gem::Requirement
@@ -106,9 +120,14 @@ files:
106
120
  - bin/setup
107
121
  - lib/middleman-caching-proxy.rb
108
122
  - lib/middleman/caching_proxy.rb
123
+ - lib/middleman/caching_proxy/cache.rb
124
+ - lib/middleman/caching_proxy/cache_item.rb
125
+ - lib/middleman/caching_proxy/cache_manifest.rb
126
+ - lib/middleman/caching_proxy/cached_resource.rb
127
+ - lib/middleman/caching_proxy/extension.rb
109
128
  - lib/middleman/caching_proxy/version.rb
110
129
  - middleman-caching-proxy.gemspec
111
- - spec/middleman/caching/proxy_spec.rb
130
+ - spec/middleman/caching_proxy_spec.rb
112
131
  - spec/spec_helper.rb
113
132
  homepage: https://github.com/joeyates/middleman-caching-proxy
114
133
  licenses: