lib/cachai.rb in cachai-0.0.1 vs lib/cachai.rb in cachai-0.0.2

- old
+ new

@@ -1,26 +1,35 @@ require 'sinatra/base' +require 'redis' require 'json' require 'rake' + require_relative 'comment' require_relative 'akismet' module Cachai class Middleware < Sinatra::Base # set :database_file, "config/database.yml" # set :public_folder, File.join(settings.root, 'public') # set :protection, true + # set :logging, nil + + # use Rack::CommonLogger, LOGGER + # use Rack::Static, :urls => %w(/css /img /js /favicon.ico), :root => 'public' use ActiveRecord::ConnectionAdapters::ConnectionManagement def initialize(app, opts = nil) opts = opts || {} @domain = opts.delete(:domain) or raise 'Domain required.' load_schema unless schema_loaded? + redis_host = opts.delete(:redis_host) || 'localhost' + @redis = Redis.new(:host => redis_host) + if key = opts.delete(:akismet_key) @akismet = Akismet.new(:api_key => key, :blog => "http://#{@domain}") else puts "No Akismet key found! Will not check comments for spam." end @@ -30,22 +39,21 @@ get '/comments.?:format?' do check_domain!(params[:domain]) # puts "Comments for: #{params[:domain]}#{params[:path]}" - list = get_comments(params[:path]) + json_list = get_comments(params[:path]) if params[:callback] content_type 'application/javascript' - "#{params[:callback]}(#{list.to_json});" + "#{params[:callback]}(#{json_list});" else json(list) end end post '/comments.?:format?' do - begin data = JSON.parse(request.body.read) check_domain!(data['domain']) headers['Access-Control-Allow-Origin'] = data['protocol'] + '//' + data['domain'] @@ -60,10 +68,12 @@ :author_email => data['author_email'], :author_url => data['author_url'] } comment = Comment.create!(attrs) + + @redis.del(redis_key(data['path'])) json({ :status => 'ok', :comment => comment }) rescue JSON::ParserError status 400 and json({ :error => 'Invalid JSON.' }) rescue ActiveRecord::RecordInvalid => e @@ -71,21 +81,31 @@ end end private + def set_cache(timestamp) + return if timestamp.nil? + last_modified timestamp + cache_control :public, :must_revalidate, :max_age => 60 + end + + def prevent_cache + cache_control :public, :no_cache, :no_store, :must_revalidate, :max_age => 0 + # expires 1.year.ago + end + def load_schema require 'sinatra/activerecord/rake' - # Rake::Task['db:schema:load'].invoke require_relative '../db/schema.rb' end def schema_loaded? Comment.first true rescue ActiveRecord::StatementInvalid => e - # SQLite3::SQLException => e + # SQLite3::SQLException => e # return !e.message['no such table'] false end def check_domain!(domain) @@ -96,14 +116,25 @@ halt(404, message || 'Not found.') end def json(obj) content_type 'application/json' - obj.to_json + return obj.is_a?(String) ? obj : obj.to_json end - def get_comments(document_path) - Comment.where({ :path => document_path }) + def get_comments(path) + key = redis_key(path) + unless json_list = @redis.get(key) + puts "Not cached. Getting from DB: #{path}" + json_list = Comment.where({ :path => path }).to_json + @redis.set(key, json_list) + @redis.expire(key, 60 * 60) # one hour + end + json_list + end + + def redis_key(path) + "comments:#{@domain}:#{path}" end def is_spam?(data, link, request) return false unless @akismet # return true if blacklisted?(name, email, content)