Commit
Also added Instrumentation and a log subscriber
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
module ActiveFedora | ||
# = Active Fedora Ldp Cache | ||
class LdpCache | ||
module ClassMethods | ||
# Enable the query cache within the block if Active Fedora is configured. | ||
# If it's not, it will execute the given block. | ||
def cache(&block) | ||
service = ActiveFedora.fedora.ldp_resource_service | ||
service.cache(&block) | ||
end | ||
|
||
# Disable the query cache within the block if Active Fedora is configured. | ||
# If it's not, it will execute the given block. | ||
def uncached(&block) | ||
ActiveFedora.fedora.ldp_resource_service.uncached(&block) | ||
end | ||
end | ||
|
||
def initialize(app) | ||
@app = app | ||
end | ||
|
||
def call(env) | ||
ActiveFedora.fedora.ldp_resource_service.enable_cache! | ||
|
||
response = @app.call(env) | ||
response[2] = Rack::BodyProxy.new(response[2]) do | ||
reset_cache_settings | ||
end | ||
|
||
response | ||
rescue Exception => e | ||
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong.
jcoyne
Author
Member
|
||
reset_cache_settings | ||
raise e | ||
end | ||
|
||
private | ||
|
||
def reset_cache_settings | ||
ActiveFedora.fedora.ldp_resource_service.clear_cache | ||
ActiveFedora.fedora.ldp_resource_service.disable_cache! | ||
end | ||
|
||
end | ||
end | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
module ActiveFedora | ||
module LdpCachingService | ||
|
||
def initialize(*) | ||
super | ||
@cache = {} | ||
@cache_enabled = false | ||
end | ||
|
||
def get(klass, id) | ||
if @cache_enabled | ||
cache_resource(id) { super } | ||
else | ||
super | ||
end | ||
end | ||
|
||
def update(*) | ||
clear_cache if @cache_enabled | ||
super | ||
end | ||
|
||
# Enable the cache within the block. | ||
def cache | ||
old, @cache_enabled = @cache_enabled, true | ||
yield | ||
ensure | ||
@cache_enabled = old | ||
clear_cache unless @cache_enabled | ||
end | ||
|
||
def enable_cache! | ||
@cache_enabled = true | ||
end | ||
|
||
def disable_cache! | ||
@cache_enabled = false | ||
end | ||
|
||
# Disable the query cache within the block. | ||
def uncached | ||
old, @cache_enabled = @cache_enabled, false | ||
yield | ||
ensure | ||
@cache_enabled = old | ||
end | ||
|
||
def clear_cache | ||
@cache.clear | ||
end | ||
|
||
private | ||
|
||
def cache_resource(id, &block) | ||
result = | ||
if @cache.key?(id) | ||
ActiveSupport::Notifications.instrument("ldp.active_fedora", | ||
id: id, name: "CACHE", ldp_service: object_id) | ||
@cache[id] | ||
else | ||
@cache[id] = yield | ||
end | ||
result.dup | ||
end | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,22 +1,40 @@ | ||
module ActiveFedora | ||
class LdpResourceService | ||
module LdpOperations | ||
def get(klass, id) | ||
log(klass, id) do | ||
if id | ||
LdpResource.new(connection, to_uri(klass, id)) | ||
else | ||
LdpResource.new(connection, nil, nil, ActiveFedora.fedora.host + ActiveFedora.fedora.base_path) | ||
end | ||
end | ||
end | ||
|
||
# TODO break the cache. | ||
def update(change_set, klass, id) | ||
SparqlInsert.new(change_set.changes).execute(to_uri(klass, id)) | ||
end | ||
|
||
|
||
private | ||
def log(klass, id) | ||
ActiveSupport::Notifications.instrument("ldp.active_fedora", | ||
id: id, name: "Load #{klass}", ldp_service: object_id) { yield } | ||
end | ||
|
||
def to_uri(klass, id) | ||
klass.id_to_uri(id) | ||
end | ||
end | ||
attr_reader :connection | ||
include LdpOperations | ||
include LdpCachingService | ||
|
||
def initialize(conn) | ||
@connection = conn | ||
super() | ||
end | ||
|
||
def get(klass, id) | ||
if id | ||
LdpResource.new(connection, to_uri(klass, id)) | ||
else | ||
LdpResource.new(connection, nil, nil, ActiveFedora.fedora.host + ActiveFedora.fedora.base_path) | ||
end | ||
end | ||
|
||
private | ||
def to_uri(klass, id) | ||
klass.id_to_uri(id) | ||
end | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
module ActiveFedora | ||
class LogSubscriber < ActiveSupport::LogSubscriber | ||
|
||
def initialize | ||
super | ||
@odd = false | ||
end | ||
|
||
def ldp(event) | ||
return unless logger.debug? | ||
|
||
payload = event.payload | ||
|
||
name = "#{payload[:name]} (#{event.duration.round(1)}ms)" | ||
id = payload[:id] || "[no id]" | ||
|
||
if odd? | ||
name = color(name, CYAN, true) | ||
id = color(id, nil, true) | ||
else | ||
name = color(name, MAGENTA, true) | ||
end | ||
|
||
debug " #{name} #{id} Service: #{payload[:ldp_service]}" | ||
end | ||
|
||
def odd? | ||
@odd = !@odd | ||
end | ||
|
||
def logger | ||
ActiveFedora::Base.logger | ||
end | ||
end | ||
end | ||
|
||
ActiveFedora::LogSubscriber.attach_to :active_fedora | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
require 'spec_helper' | ||
|
||
describe "Caching" do | ||
before do | ||
class TestClass < ActiveFedora::Base | ||
property :title, predicate: ::RDF::DC.title | ||
end | ||
end | ||
|
||
after { Object.send(:remove_const, :TestClass) } | ||
|
||
let!(:object) { TestClass.create(id: '123') } | ||
|
||
describe "#cache" do | ||
it "should find records in the cache" do | ||
expect(ActiveFedora::LdpResource).to receive(:new).once.and_call_original | ||
ActiveFedora::Base.cache do | ||
TestClass.find(object.id) | ||
TestClass.find(object.id) | ||
end | ||
end | ||
|
||
it "should clear the cache at the end of the block" do | ||
expect(ActiveFedora::LdpResource).to receive(:new).twice.and_call_original | ||
ActiveFedora::Base.cache do | ||
TestClass.find(object.id) | ||
end | ||
ActiveFedora::Base.cache do | ||
TestClass.find(object.id) | ||
end | ||
end | ||
|
||
context "an update" do | ||
it "should flush the cache" do | ||
expect(ActiveFedora::LdpResource).to receive(:new).twice.and_call_original | ||
ActiveFedora::Base.cache do | ||
TestClass.find(object.id) | ||
object.title= ['foo'] | ||
object.save! | ||
TestClass.find(object.id) | ||
end | ||
end | ||
end | ||
end | ||
|
||
describe "#uncached" do | ||
it "should not use the cache" do | ||
expect(ActiveFedora::LdpResource).to receive(:new).twice.and_call_original | ||
ActiveFedora::Base.cache do | ||
TestClass.find(object.id) | ||
ActiveFedora::Base.uncached do | ||
TestClass.find(object.id) | ||
end | ||
TestClass.find(object.id) | ||
end | ||
end | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -20,6 +20,7 @@ | |
|
||
ActiveFedora::Base.logger = Logger.new(STDERR) | ||
ActiveFedora::Base.logger.level = Logger::WARN | ||
# require 'http_logger' | ||
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong.
jcoyne
Author
Member
|
||
# HttpLogger.logger = Logger.new(STDOUT) | ||
# HttpLogger.ignore = [/localhost:8983\/solr/] | ||
# HttpLogger.colorize = false | ||
|
rescue StandardError instead?