heuristic_cache 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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