caching_with_tags 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.
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "http://rubygems.org"
2
+
3
+ gem 'rails', '>3.0.0'
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,21 @@
1
+ $:.push File.expand_path("../lib", __FILE__)
2
+ require "caching_with_tags/version"
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = "caching_with_tags"
6
+ s.version = CachingWithTags::VERSION
7
+ s.authors = ["Vitaly Tsevan"]
8
+ s.email = ["vzevan@gmail.com"]
9
+ s.homepage = ""
10
+ s.summary = %q{Realisation of cache tagging for rails}
11
+ s.description = %q{Realisation of cache tagging for rails}
12
+
13
+ s.files = `git ls-files`.split("\n")
14
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
15
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
16
+ s.require_paths = ["lib"]
17
+
18
+ # specify any dependencies here; for example:
19
+ # s.add_development_dependency "rspec"
20
+ s.add_runtime_dependency "rails"
21
+ end
@@ -0,0 +1,6 @@
1
+ require 'rails'
2
+ require 'active_support'
3
+
4
+ require "caching_with_tags/version"
5
+ require "caching_with_tags/store"
6
+ require "caching_with_tags/railtie"
@@ -0,0 +1,8 @@
1
+ class Railtie < ::Rails::Railtie
2
+ initializer 'caching_with_tags.on_rails_init' do
3
+ ActiveSupport.on_load :before_configuration do
4
+ ActiveSupport.send :include, CachingWithTags::StoreMethods
5
+ ActiveSupport.send :include, CachingWithTags::EntryMethods
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,135 @@
1
+ module CachingWithTags
2
+ module StoreMethods
3
+ class ActiveSupport::Cache::Store
4
+ def read(name, options = nil)
5
+ options = merged_options(options)
6
+ key = namespaced_key(name, options)
7
+ instrument(:read, name, options) do |payload|
8
+ ########patched
9
+ entry = read_entry(key, options)
10
+ entry = nil if entry && entry.tags && !tags_actual?(entry.tags)
11
+ #######patch end
12
+
13
+ if entry
14
+ if entry.expired?
15
+ delete_entry(key, options)
16
+ payload[:hit] = false if payload
17
+ nil
18
+ else
19
+ payload[:hit] = true if payload
20
+ entry.value
21
+ end
22
+ else
23
+ payload[:hit] = false if payload
24
+ nil
25
+ end
26
+ end
27
+ end
28
+
29
+ def fetch(name, options = nil)
30
+ if block_given?
31
+ options = merged_options(options)
32
+ key = namespaced_key(name, options)
33
+ ########patched
34
+ unless options[:force]
35
+ entry = instrument(:read, name, options) do |payload|
36
+ payload[:super_operation] = :fetch if payload
37
+ ent = read_entry(key, options)
38
+ ent = nil if ent && ent.tags && !tags_actual?(ent.tags)
39
+ ent
40
+ end
41
+ end
42
+ ########end of patch
43
+ if entry && entry.expired?
44
+ race_ttl = options[:race_condition_ttl].to_f
45
+ if race_ttl and Time.now.to_f - entry.expires_at <= race_ttl
46
+ entry.expires_at = Time.now + race_ttl
47
+ write_entry(key, entry, :expires_in => race_ttl * 2)
48
+ else
49
+ delete_entry(key, options)
50
+ end
51
+ entry = nil
52
+ end
53
+
54
+ if entry
55
+ instrument(:fetch_hit, name, options) { |payload| }
56
+ entry.value
57
+ else
58
+ result = instrument(:generate, name, options) do |payload|
59
+ yield
60
+ end
61
+ write(name, result, options)
62
+ result
63
+ end
64
+ else
65
+ read(name, options)
66
+ end
67
+ end
68
+
69
+ def write(name, value, options = nil)
70
+ options = merged_options(options)
71
+ instrument(:write, name, options) do |payload|
72
+ ######patch
73
+ entry = ActiveSupport::Cache::Entry.new(value, options)
74
+ write_meta(entry, options[:tags]) if options[:tags]
75
+ write_entry(namespaced_key(name, options), entry, options)
76
+ ######end of patch
77
+ end
78
+ end
79
+
80
+ def exist?(name, options = nil)
81
+ options = merged_options(options)
82
+ instrument(:exist?, name) do |payload|
83
+ #####patched
84
+ entry = read_entry(namespaced_key(name, options), options)
85
+ entry = nil if entry && entry.tags && !tags_actual?(entry.tags)
86
+ #####end of patch
87
+ if entry && !entry.expired?
88
+ true
89
+ else
90
+ false
91
+ end
92
+ end
93
+ end
94
+
95
+ #####patch
96
+
97
+ def write_meta(entry, tags)
98
+ t = if tags.is_a?(Array)
99
+ tags.inject({}) do |res, el|
100
+ res[el] = fetch(el, {:namespace => nil}) { 1 }
101
+ res
102
+ end
103
+ end
104
+ entry.tags = t
105
+ end
106
+
107
+ def tags_actual?(tags)
108
+ if tags.is_a?(Hash)
109
+ # We're doing dup here because of Dalli makes force_encoding
110
+ # and ActiveSupport returns frozen values, so it raises an exception.
111
+ # Ruby uses copy-on-write technique so it's extremely cheap to make a dup
112
+ # of all tags.keys as far as we don't modify them
113
+ actual_versions = read_multi(*tags.keys.map { |k| k.dup } << {:namespace => nil})
114
+ actual_versions == tags
115
+ else
116
+ false
117
+ end
118
+ end
119
+
120
+ def increment_tag(name, options = nil)
121
+ options = merged_options(options)
122
+ entry = read_entry(namespaced_key(name, {:namespace => nil}), options)
123
+ value = entry ? entry.value + 1 : 1
124
+ write_entry(namespaced_key(name, {:namespace => nil}), ActiveSupport::Cache::Entry.new(value), options)
125
+ end
126
+ ######end of patch
127
+ end
128
+ end
129
+
130
+ module EntryMethods
131
+ class ActiveSupport::Cache::Entry
132
+ attr_accessor :tags
133
+ end
134
+ end
135
+ end
@@ -0,0 +1,3 @@
1
+ module CachingWithTags
2
+ VERSION = "0.0.1"
3
+ end
metadata ADDED
@@ -0,0 +1,64 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: caching_with_tags
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Vitaly Tsevan
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-04-08 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rails
16
+ requirement: &12632800 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *12632800
25
+ description: Realisation of cache tagging for rails
26
+ email:
27
+ - vzevan@gmail.com
28
+ executables: []
29
+ extensions: []
30
+ extra_rdoc_files: []
31
+ files:
32
+ - .gitignore
33
+ - Gemfile
34
+ - Rakefile
35
+ - caching_with_tags.gemspec
36
+ - lib/caching_with_tags.rb
37
+ - lib/caching_with_tags/railtie.rb
38
+ - lib/caching_with_tags/store.rb
39
+ - lib/caching_with_tags/version.rb
40
+ homepage: ''
41
+ licenses: []
42
+ post_install_message:
43
+ rdoc_options: []
44
+ require_paths:
45
+ - lib
46
+ required_ruby_version: !ruby/object:Gem::Requirement
47
+ none: false
48
+ requirements:
49
+ - - ! '>='
50
+ - !ruby/object:Gem::Version
51
+ version: '0'
52
+ required_rubygems_version: !ruby/object:Gem::Requirement
53
+ none: false
54
+ requirements:
55
+ - - ! '>='
56
+ - !ruby/object:Gem::Version
57
+ version: '0'
58
+ requirements: []
59
+ rubyforge_project:
60
+ rubygems_version: 1.8.10
61
+ signing_key:
62
+ specification_version: 3
63
+ summary: Realisation of cache tagging for rails
64
+ test_files: []