heuristic_cache 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ Y2NlNjM4YjhkNWJjZDA2YzJiYjllOGRlM2JkMWIwMDUzNTAwMmIwZQ==
5
+ data.tar.gz: !binary |-
6
+ ODZlNzE5Yzg3NjcwMTg5MGE4NWM0Y2M5NWYzZGM0NmViNDRmOWU1Yg==
7
+ !binary "U0hBNTEy":
8
+ metadata.gz: !binary |-
9
+ YzhiYTJjOTA5ODU4NDdjODY0OWUwZjgwNzlkMGYxY2Q1MmZmOGZmNGY3Yjg5
10
+ ODFhZDA2NjgzNjM0YjUwNDBjZDM0NzkyZjMwNzU3OTllZWMxZjU4NWY0Y2Ni
11
+ NzYwYTc0M2VkYzJhMDY0NzIzNzNjYTJlYzFmOTg0YWE5MTgwNjE=
12
+ data.tar.gz: !binary |-
13
+ NzBmNDE2YWI2NTA1OWQzNTQwZDRhYzgyMzU2MWU1NjdjNmJlMzU0MjQzMjUx
14
+ ZjQ4ZGVjMDU3ZWUxNmIxMzVkOTg1OTUzMTc0OWQyNWNjY2RlYzI2YzQ5ZWUx
15
+ MjM1NDE0ODdiYTE3NzQ4MzMwZTgwMWM5ZWVhYTM1OTZjOTBkZGY=
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --color
2
+ --format progress
3
+
data/.ruby-gemset ADDED
@@ -0,0 +1 @@
1
+ heuristic_cache
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ ruby-1.9.3-p392
data/.travis.yml ADDED
@@ -0,0 +1,12 @@
1
+ bundler_args: --without development
2
+ rvm:
3
+ - 1.9.3
4
+ - 2.0.0
5
+ - ruby-head
6
+ - rbx-19mode
7
+ - jruby
8
+
9
+ matrix:
10
+ allow_failures:
11
+ - rvm: ruby-head
12
+
data/Gemfile ADDED
@@ -0,0 +1,14 @@
1
+ source 'https://rubygems.org'
2
+ gemspec
3
+
4
+ group :development do
5
+ gem 'debugger', :require => false
6
+ end
7
+
8
+ group :test do
9
+ gem 'rake'
10
+ gem 'rspec'
11
+ gem 'mocha', '= 0.13.3', :require => false
12
+ gem 'timecop'
13
+ end
14
+
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Wilson Souza, Luiz Rocha
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,31 @@
1
+ # Heuristic Cache
2
+
3
+ [![Build Status](https://travis-ci.org/abril/heuristic-cache.png?branch=master)](https://travis-ci.org/abril/heuristic-cache)
4
+
5
+ TODO: Write a gem description
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ gem 'heuristic_cache'
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install heuristic_cache
20
+
21
+ ## Usage
22
+
23
+ TODO: Write usage instructions here
24
+
25
+ ## Contributing
26
+
27
+ 1. Fork it
28
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
29
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
30
+ 4. Push to the branch (`git push origin my-new-feature`)
31
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new('spec')
5
+
6
+ task :default => :spec
@@ -0,0 +1,30 @@
1
+ commom: &commom
2
+ cache_config:
3
+ coefficient:
4
+ materia:
5
+ show: 0.02
6
+ lista_editorial:
7
+ show: 0.02
8
+ galeria_multimidia:
9
+ show: 0.02
10
+ time_to_live:
11
+ maximum: 3600
12
+ minimum: 60
13
+ default: 60
14
+ cacheable_statuses:
15
+ - disponivel
16
+
17
+ development:
18
+ <<: *commom
19
+ dev:
20
+ <<: *commom
21
+ test:
22
+ <<: *commom
23
+ qa:
24
+ <<: *commom
25
+ qalegado:
26
+ <<: *commom
27
+ stage:
28
+ <<: *commom
29
+ production:
30
+ <<: *commom
@@ -0,0 +1,24 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'heuristic_cache/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'heuristic_cache'
8
+ spec.version = AlxHeuristicCache::VERSION.to_s
9
+ spec.authors = ['Wilson Souza', 'Luiz Rocha']
10
+ spec.email = ['willroberto@gmail.com', 'lsdrocha@gmail.com']
11
+ spec.summary = 'Heuristic TTL for HTTP-Cache Headers'
12
+ spec.homepage = 'https://github.com/abril/heuristic-cache'
13
+ spec.license = 'MIT'
14
+
15
+ spec.files = `git ls-files`.split($/)
16
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
+ spec.require_paths = ['lib']
19
+
20
+ spec.add_development_dependency 'bundler', '~> 1.3'
21
+ spec.add_development_dependency 'rake'
22
+ spec.add_development_dependency 'step-up', '0.8.2'
23
+ end
24
+
@@ -0,0 +1,59 @@
1
+ # encoding: UTF-8
2
+
3
+ module Commons
4
+
5
+ require "yaml"
6
+
7
+ class Yml < Hash
8
+
9
+ attr_accessor :from
10
+
11
+ def initialize(from)
12
+ self.from = from
13
+ end
14
+
15
+ def self.read(file)
16
+
17
+ raise ArgumentError, 'Param file é required' if file == nil
18
+
19
+ yaml_file = file.end_with?(".yml") ? file : "#{file}.yml"
20
+ begin
21
+ yaml_configs = YAML::load_file(yaml_file)
22
+ return self.prepare_configs(yaml_configs, yaml_file, true)
23
+ rescue Exception => e
24
+ message = "Error when reading yml file: #{e.message}"
25
+ STDOUT.puts(message)
26
+ raise e
27
+ end
28
+ end
29
+
30
+ def [](key)
31
+ prepare_value(super(key), key)
32
+ end
33
+
34
+ def fetch(*args)
35
+ begin
36
+ return prepare_value(super(*args), args.first)
37
+ rescue IndexError => e
38
+ message = "Missing attribute '#{args.first}' in #{self.from}"
39
+ STDOUT.puts(message)
40
+ raise RuntimeError.new(message)
41
+ end
42
+ end
43
+
44
+ def self.prepare_configs(configs, file, symbolize_keys = false)
45
+ if configs.is_a?(Hash)
46
+ configs.symbolize_keys! if symbolize_keys && configs.respond_to?(:symbolize_keys!)
47
+ configs = Yml.new(file).merge(configs)
48
+ end
49
+ configs
50
+ end
51
+
52
+ private
53
+ def prepare_value(value, from_key)
54
+ value.is_a?(Hash) ? Yml.new("'#{from_key}:#{self.from}'").merge(value) : value
55
+ end
56
+
57
+ end
58
+
59
+ end
@@ -0,0 +1,18 @@
1
+ # encoding: utf-8
2
+ require File.expand_path("heuristic_cache", File.dirname(__FILE__)) unless defined?(::HeuristicCache)
3
+
4
+ module AlxHeuristicCache
5
+
6
+ module Helpers
7
+
8
+ def cacheable?(object)
9
+ ::HeuristicCache.cacheable?(object)
10
+ end
11
+
12
+ def ttl_for(object, action)
13
+ ::HeuristicCache::TTL.for(object, action)
14
+ end
15
+
16
+ end
17
+
18
+ end
@@ -0,0 +1,82 @@
1
+ # encoding: UTF-8
2
+
3
+ module HeuristicCache
4
+ CACHEABLE_STATUSES = Array.new
5
+
6
+ def self.init(file, env = 'development')
7
+
8
+ raise ArgumentError, 'Param env is required' if env == nil
9
+
10
+ raise ArgumentError, 'Param file (path config file) is required' if file == nil
11
+
12
+ raise ArgumentError, 'Param file (path config file) is invalid' unless File.exists?(file)
13
+
14
+ config = ::Commons::Yml.read(file)[env.to_s]['cache_config']
15
+
16
+ STDOUT.puts 'WARNING: attr time_to_live is required' if config["time_to_live"] == nil
17
+ TTL.init(config["time_to_live"])
18
+
19
+ STDOUT.puts 'WARNING: attr coefficient is required' if config["coefficient"] == nil
20
+ Coefficient.init(config["coefficient"])
21
+
22
+ CACHEABLE_STATUSES.concat(config["cacheable_statuses"])
23
+
24
+ nil
25
+
26
+ end
27
+
28
+ def self.cacheable?(object)
29
+ CACHEABLE_STATUSES.empty? ? true : object.respond_to?(:status) && CACHEABLE_STATUSES.include?(object.status)
30
+ end
31
+
32
+ class TTL
33
+
34
+ def self.init(yml)
35
+ @ttls = yml
36
+ end
37
+
38
+ def self.maximum
39
+ @ttls["maximum"]
40
+ end
41
+
42
+ def self.greater_than_maximum?(value)
43
+ value > self.maximum
44
+ end
45
+
46
+ def self.minimum
47
+ @ttls["minimum"]
48
+ end
49
+
50
+ def self.lower_than_minimum?(value)
51
+ value < self.minimum
52
+ end
53
+
54
+ def self.default
55
+ @ttls["default"]
56
+ end
57
+
58
+ def self.for(object, action)
59
+ return TTL.default unless object.respond_to?(:updated_at) && !object.updated_at.nil?
60
+
61
+ difference = Time.now.to_i - object.updated_at.to_i
62
+ coefficient = Coefficient.for(object.class.to_s.downcase, action)
63
+ heuristic_ttl = (difference * coefficient).to_i
64
+
65
+ return TTL.minimum if TTL.lower_than_minimum?(heuristic_ttl)
66
+ return TTL.maximum if TTL.greater_than_maximum?(heuristic_ttl)
67
+
68
+ heuristic_ttl
69
+ end
70
+
71
+ end
72
+
73
+ class Coefficient
74
+ def self.init(yml)
75
+ @coefficients = yml
76
+ end
77
+ def self.for(model, action)
78
+ @coefficients[model][action.to_s]
79
+ end
80
+ end
81
+
82
+ end
@@ -0,0 +1,6 @@
1
+ # encoding: UTF-8
2
+ module AlxHeuristicCache
3
+
4
+ VERSION = '0.0.1'
5
+
6
+ end
@@ -0,0 +1,5 @@
1
+ # encoding: UTF-8
2
+ require "heuristic_cache/version"
3
+ require "heuristic_cache/heuristic_cache"
4
+ require "heuristic_cache/cache_helper"
5
+ require "commons/yml"
@@ -0,0 +1,23 @@
1
+ require "spec_helper"
2
+
3
+ describe "AlxHeuristicCache::Helpers" do
4
+
5
+ context "When call any helper" do
6
+
7
+ it "should call class HeuristicCache.cacheable?" do
8
+ ::HeuristicCache.expects(:cacheable?).returns(true)
9
+ TestAlxHeuristicCache.new.cacheable?("teste")
10
+ end
11
+
12
+ it "should call class HeuristicCache::TTL.for" do
13
+ ::HeuristicCache::TTL.expects(:for).returns(1)
14
+ TestAlxHeuristicCache.new.ttl_for("teste", "new")
15
+ end
16
+
17
+ end
18
+
19
+ end
20
+
21
+ class TestAlxHeuristicCache
22
+ include AlxHeuristicCache::Helpers
23
+ end
@@ -0,0 +1,30 @@
1
+ # encoding: utf-8
2
+
3
+ require "spec_helper"
4
+
5
+ describe ::HeuristicCache do
6
+ context "cacheable? method" do
7
+
8
+ it "should return false for a nil parameter" do
9
+ ::HeuristicCache.cacheable?(nil).should == false
10
+ end
11
+
12
+ it "should return false for a object without status method" do
13
+ ::HeuristicCache.cacheable?("").should == false
14
+ end
15
+
16
+ it "should return false for a object with rascunho status" do
17
+ ::HeuristicCache.cacheable?(HeuristicCacheObj.new(:status => "rascunho")).should == false
18
+ end
19
+
20
+ it "should return false for a object with agendado status" do
21
+ ::HeuristicCache.cacheable?(HeuristicCacheObj.new(:status => "agendado")).should == false
22
+ end
23
+
24
+ it "should return true for a object with disponivel status" do
25
+ ::HeuristicCache.cacheable?(HeuristicCacheObj.new(:status => "disponivel")).should == true
26
+ end
27
+
28
+ end
29
+
30
+ end
@@ -0,0 +1,57 @@
1
+ # encoding: utf-8
2
+
3
+ require "spec_helper"
4
+ require 'timecop'
5
+
6
+ describe ::HeuristicCache::TTL do
7
+
8
+ context "for method" do
9
+
10
+ before(:each) do
11
+ Timecop.travel(Time.local(2013, 1, 1, 15, 0, 0))
12
+ Timecop.freeze(Time.local(2013, 1, 1, 15, 0, 0))
13
+
14
+ ::HeuristicCache::Coefficient.stubs(:for).returns(0.1)
15
+ ::HeuristicCache::TTL.stubs(:minimum).returns(60)
16
+ ::HeuristicCache::TTL.stubs(:maximum).returns(86400)
17
+ end
18
+
19
+ after(:all) do
20
+ Timecop.return
21
+
22
+ ::HeuristicCache::Coefficient.unstub(:for)
23
+ ::HeuristicCache::TTL.unstub(:minimum)
24
+ ::HeuristicCache::TTL.unstub(:maximum)
25
+ end
26
+
27
+ it "should return the default_ttl for nil instances" do
28
+ ::HeuristicCache::TTL.for(nil, :show).should == ::HeuristicCache::TTL.default
29
+ end
30
+
31
+ it "should return the default_ttl for objects that doesn't respond to updated_at" do
32
+ ::HeuristicCache::TTL.for("", :show).should == ::HeuristicCache::TTL.default
33
+ end
34
+
35
+ it "should return the default_ttl for objects with null updated_at" do
36
+ materia = HeuristicCacheObj.new(:updated_at => nil)
37
+ ::HeuristicCache::TTL.for(materia, :show).should == ::HeuristicCache::TTL.default
38
+ end
39
+
40
+ it "should return a calculated ttl for objects with updated_at" do
41
+ materia = HeuristicCacheObj.new(:updated_at => Time.parse("2013-01-01 10:00:00"))
42
+ ::HeuristicCache::TTL.for(materia, :show).should == 1800 # 30 minutos
43
+ end
44
+
45
+ it "should return ::HeuristicCache::TTL.maximum of ttl for objects with old updated_at" do
46
+ materia = HeuristicCacheObj.new(:updated_at => Time.parse("2000-01-01 10:00:00"))
47
+ ::HeuristicCache::TTL.for(materia, :show).should == ::HeuristicCache::TTL.maximum
48
+ end
49
+
50
+ it "should return ::HeuristicCache::TTL.minimum of ttl for objects with very new updated_at" do
51
+ materia = HeuristicCacheObj .new(:updated_at => Time.parse("2013-01-01 15:01:00"))
52
+ ::HeuristicCache::TTL.for(materia, :show).should == ::HeuristicCache::TTL.minimum
53
+ end
54
+
55
+ end
56
+
57
+ end
@@ -0,0 +1,32 @@
1
+ gem_root = File.expand_path("../../lib")
2
+ $:.unshift gem_root unless $:.include? gem_root
3
+
4
+ STDOUT.puts Dir[File.expand_path("../../lib/**/*.rb", __FILE__)]
5
+
6
+ Dir[File.expand_path("../../lib/**/*.rb", __FILE__)].each {|f| require f }
7
+
8
+ # This file was generated by the `rspec --init` command. Conventionally, all
9
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
10
+ # Require this file using `require "spec_helper"` to ensure that it is only
11
+ # loaded once.
12
+ #
13
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
14
+ RSpec.configure do |config|
15
+ config.mock_with :mocha
16
+ config.treat_symbols_as_metadata_keys_with_true_values = true
17
+ config.run_all_when_everything_filtered = true
18
+ config.filter_run :focus
19
+
20
+ # Run specs in random order to surface order dependencies. If you find an
21
+ # order dependency and want to debug it, you can fix the order by providing
22
+ # the seed, which is printed after each run.
23
+ # --seed 1234
24
+ config.order = 'random'
25
+ end
26
+
27
+ # Requires supporting ruby files with custom matchers and macros, etc,
28
+ # in spec/support/ and its subdirectories.
29
+ Dir[File.expand_path("../support/**/*.rb", __FILE__)].each {|f| require f }
30
+
31
+ ::HeuristicCache.init(File.join(File.dirname(__FILE__), "..", "config", "heuristic_cache_test.yml"), 'test')
32
+
@@ -0,0 +1,7 @@
1
+ class HeuristicCacheObj
2
+ attr_accessor :status, :updated_at
3
+ def initialize(hash)
4
+ @status = hash[:status]
5
+ @updated_at = hash[:updated_at]
6
+ end
7
+ end
metadata ADDED
@@ -0,0 +1,114 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: heuristic_cache
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Wilson Souza
8
+ - Luiz Rocha
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-08-05 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: bundler
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - ~>
19
+ - !ruby/object:Gem::Version
20
+ version: '1.3'
21
+ type: :development
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ~>
26
+ - !ruby/object:Gem::Version
27
+ version: '1.3'
28
+ - !ruby/object:Gem::Dependency
29
+ name: rake
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - ! '>='
33
+ - !ruby/object:Gem::Version
34
+ version: '0'
35
+ type: :development
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ! '>='
40
+ - !ruby/object:Gem::Version
41
+ version: '0'
42
+ - !ruby/object:Gem::Dependency
43
+ name: step-up
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - '='
47
+ - !ruby/object:Gem::Version
48
+ version: 0.8.2
49
+ type: :development
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - '='
54
+ - !ruby/object:Gem::Version
55
+ version: 0.8.2
56
+ description:
57
+ email:
58
+ - willroberto@gmail.com
59
+ - lsdrocha@gmail.com
60
+ executables: []
61
+ extensions: []
62
+ extra_rdoc_files: []
63
+ files:
64
+ - .gitignore
65
+ - .rspec
66
+ - .ruby-gemset
67
+ - .ruby-version
68
+ - .travis.yml
69
+ - Gemfile
70
+ - LICENSE
71
+ - README.md
72
+ - Rakefile
73
+ - config/heuristic_cache_test.yml
74
+ - heuristic_cache.gemspec
75
+ - lib/commons/yml.rb
76
+ - lib/heuristic_cache.rb
77
+ - lib/heuristic_cache/cache_helper.rb
78
+ - lib/heuristic_cache/heuristic_cache.rb
79
+ - lib/heuristic_cache/version.rb
80
+ - spec/lib/alx_heuristic_cache/cache_helper_spec.rb
81
+ - spec/lib/alx_heuristic_cache/heuristic_cache_spec.rb
82
+ - spec/lib/alx_heuristic_cache/heuristic_cache_ttl_spec.rb
83
+ - spec/spec_helper.rb
84
+ - spec/support/heuristc_cache_obj.rb
85
+ homepage: https://github.com/abril/heuristic-cache
86
+ licenses:
87
+ - MIT
88
+ metadata: {}
89
+ post_install_message:
90
+ rdoc_options: []
91
+ require_paths:
92
+ - lib
93
+ required_ruby_version: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - ! '>='
96
+ - !ruby/object:Gem::Version
97
+ version: '0'
98
+ required_rubygems_version: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ! '>='
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ requirements: []
104
+ rubyforge_project:
105
+ rubygems_version: 2.0.5
106
+ signing_key:
107
+ specification_version: 4
108
+ summary: Heuristic TTL for HTTP-Cache Headers
109
+ test_files:
110
+ - spec/lib/alx_heuristic_cache/cache_helper_spec.rb
111
+ - spec/lib/alx_heuristic_cache/heuristic_cache_spec.rb
112
+ - spec/lib/alx_heuristic_cache/heuristic_cache_ttl_spec.rb
113
+ - spec/spec_helper.rb
114
+ - spec/support/heuristc_cache_obj.rb