Permalink
Browse files

simplified reimplementation

  • Loading branch information...
1 parent 5dc2657 commit 2ee4531422564e5f3b00957458d2ed0513cd20d2 Sven Fuchs committed Sep 4, 2010
View
0 README
No changes.
View
@@ -0,0 +1,10 @@
+require 'rake'
+require 'rake/testtask'
+
+Rake::TestTask.new do |t|
+ t.libs << 'lib'
+ t.pattern = 'test/**/*_test.rb'
+ t.verbose = false
+end
+
+task :default => :test
@@ -1,14 +0,0 @@
-require 'fileutils'
-
-module FileUtils
- def self.rmdir_p(path)
- begin
- while(true)
- FileUtils.rmdir(path)
- path = File.dirname(path)
- end
- rescue Errno::EEXIST, Errno::ENOTEMPTY, Errno::ENOENT, Errno::EINVAL, Errno::ENOTDIR
- # Stop trying to remove parent directories
- end
- end
-end
@@ -1,88 +0,0 @@
-# Simple mechanism to track calls on methods.
-#
-# Include the module and call track_methods(an_array, :foo, :bar) on any object.
-# This will set up the methods :foo and :bar on the object's metaclass.
-#
-# When the method :foo is called for the first time this is recorded to the
-# given array and the method is removed from the metaclass (so it only records
-# the) first call. The given array will then equal [[the_object, :foo]].
-module MethodCallTracking
- def track_method_calls(tracker, *methods)
- if methods.empty?
- # FIXME this assumes ActiveRecord
- define_track_method(tracker, @attributes, :[], [self, nil])
- else
- methods.each do |method|
- define_track_method(tracker, self, method, [self, method])
- end
- end
- end
-
- # Sets up a method in the meta class of the target object which will save
- # a reference when the method is called first, then removes itself and
- # delegates to the regular method in the class. (Cheap method proxy pattern
- # that leverages Ruby's way of looking up a method in the meta class first
- # and then in the regular class second.)
- def define_track_method(tracker, target, method, reference)
- meta_class = class << target; self; end
- meta_class.send :define_method, method do |*args|
- tracker << reference
- meta_class.send(:remove_method, method)
- super
- end
- end
-
- # Tracks method access on trackable objects. Trackables can be given as
- #
- # * instance variable names (when starting with an @)
- # * method names (otherwise)
- # * Hashes that use ivar or method names as keys and method names as values:
- #
- # So both of these:
- #
- # Tracker.new controller, :'@foo', :bar, { :'@baz' => :buz }
- # Tracker.new controller, :'@foo', :bar, { :'@baz' => [:buz] }
- #
- # would set up access tracking for the controller's ivar @foo, the method :bar
- # and the method :buz on the ivar @baz.
- class Tracker
- attr_reader :references
-
- def initialize
- @references = []
- end
-
- def track(owner, *trackables)
- trackables.each do |trackable|
- trackable = { trackable => nil } unless trackable.is_a?(Hash)
- trackable.each do |trackable, methods|
- trackable = resolve_trackable(owner, trackable)
- track_methods(trackable, methods) unless trackable.nil? # FIXME issue warning
- end
- end
- end
-
- protected
-
- # Resolves the trackable by looking it up on the owner. Trackables will be
- # interpreted as instance variables when they start with an @ and as method
- # names otherwise.
- def resolve_trackable(owner, trackable)
- case trackable.to_s
- when /^@/; owner.instance_variable_get(trackable.to_sym)
- else owner.send(trackable.to_sym)
- end
- end
-
- # Wraps the trackable into a MethodReadObserver and registers itself as an observer.
- # Sets up tracking for the read_attribute method when the methods argument is nil.
- # Sets up tracking for any other given methods otherwise.
- def track_methods(trackable, methods)
- if trackable.is_a?(Array)
- trackable.each { |trackable| track_methods(trackable, methods) }
- else
- trackable.track_method_calls(references, *Array(methods))
- end
- end
- end
-end
View
@@ -1,41 +1,50 @@
-require 'uri'
+require 'rack/request'
-require 'rack/cache'
-require 'rack/cache/storage'
-require 'rack/cache/utils'
+module Rack
+ module Cache
+ class Tags
+ autoload :Store, 'rack/cache/tags/store'
-require 'rack/cache/tags/context'
-require 'rack/cache/tags/storage'
-require 'rack/cache/tags/tag_store'
-require 'rack/cache/tags/meta_store'
-require 'rack/cache/tags/purger'
+ class << self
+ def store
+ @store ||= Store::ActiveRecord.new
+ end
-module Rack::Cache
- TAGS_HEADER = 'X-Cache-Tags'
- PURGE_TAGS_HEADER = 'X-Cache-Purge-Tags'
-
- Context.class_eval do
- option_accessor :tagstore
-
- def tagstore
- uri = options['rack-cache.tagstore']
- storage.resolve_tagstore_uri(uri)
- end
- end
+ def store=(store)
+ @store ||= store
+ end
+ end
- Purge::Purger.class_eval do
- include Tags::Purger
- end
+ TAGS_HEADER = 'rack-cache.tags'
+ PURGE_HEADER = 'rack-cache.purge'
+ PURGE_TAGS_HEADER = 'rack-cache.purge-tags'
+
+ attr_reader :app
- module Tags
- class << self
- def new(backend, options={}, &b)
- Context.new(backend, options, &b)
+ def initialize(app)
+ @app = app
end
- def normalize(tags)
- Array(tags).join(',').split(',').map { |tag| tag.strip }
+ def call(env)
+ status, headers, body = app.call(env)
+ if status == 200
+ store(Rack::Request.new(env).url, headers[TAGS_HEADER]) if headers.key?(TAGS_HEADER)
+ purge(headers) if headers.key?(PURGE_TAGS_HEADER)
+ end
+ [status, headers, body]
end
+
+ protected
+
+ def store(*args)
+ self.class.store.store(*args)
+ end
+
+ def purge(headers)
+ urls = self.class.store.purge(headers[PURGE_TAGS_HEADER])
+ headers[PURGE_HEADER] = urls unless urls.empty?
+ headers.delete(PURGE_TAGS_HEADER)
+ end
end
end
end
@@ -1,54 +0,0 @@
-module Rack::Cache::Tags
- class Context
- def initialize(backend, options = {})
- @backend = backend
- @options = options
- yield self if block_given?
- end
-
- def call(env)
- @env = env
- request = Rack::Cache::Request.new(env)
- response = Rack::Cache::Response.new(*@backend.call(env))
-
- tags = response.headers.delete(Rack::Cache::PURGE_TAGS_HEADER)
- return response.to_a unless tags
-
- uris = tagged_uris(tags)
- if false && env.key?('rack-cache.purger')
- # TODO directly purge using uris?
- else
- set_purge_header(response, uris)
- purge_taggings(request, uris)
- end
-
- response.to_a
- end
-
- protected
-
- def tagged_uris(tags)
- tags = Rack::Cache::Tags.normalize(tags)
- tags.inject([]) { |uris, tag| uris + tagstore.read_tag(tag) }
- end
-
- def set_purge_header(response, uris)
- response.headers[Rack::Cache::PURGE_HEADER] = uris.join("\n")
- end
-
- def purge_taggings(request, uris)
- tagstore = self.tagstore
- keys = uris.map { |uri| Rack::Cache::Utils::Key.call(request, uri) }
- keys.each { |key| tagstore.purge(key) }
- end
-
- def tagstore
- uri = @env['rack-cache.tagstore']
- storage.resolve_tagstore_uri(uri)
- end
-
- def storage
- Rack::Cache::Storage.instance
- end
- end
-end
@@ -1,22 +0,0 @@
-module Rack::Cache::Tags::MetaStore
- def store(request, response, entity_store)
- key = super
-
- tags = response.headers[Rack::Cache::TAGS_HEADER]
- tagstore(request).store(key, tags) if tags
-
- key
- end
-
- def tagstore(request)
- uri = request.env['rack-cache.tagstore']
- storage.resolve_tagstore_uri(uri)
- end
-
- def storage
- Rack::Cache::Storage.instance
- end
-
- Rack::Cache::MetaStore::Heap.send(:include, self)
- Rack::Cache::MetaStore::Disk.send(:include, self)
-end
@@ -1,18 +0,0 @@
-module Rack
- module Cache
- module Tags
- module Purger
- def purge(arg)
- keys = super
- tagstore = self.tagstore
- keys.each { |key| tagstore.purge(key) }
- end
-
- def tagstore
- uri = context.env['rack-cache.tagstore']
- storage.resolve_tagstore_uri(uri)
- end
- end
- end
- end
-end
Oops, something went wrong.

0 comments on commit 2ee4531

Please sign in to comment.