Use redis as a cache store
This commit is contained in:
4
.gitignore
vendored
4
.gitignore
vendored
@@ -7,6 +7,8 @@ fly.toml
|
||||
/publish.rb
|
||||
/publish_bookmark.rb
|
||||
/publish_photo.rb
|
||||
/publish_code.rb
|
||||
/terminal_render.rb
|
||||
instagram_import.rb
|
||||
node_modules/*
|
||||
.DS_Store
|
||||
@@ -14,6 +16,8 @@ node_modules/*
|
||||
.env.*
|
||||
.vimrc.local
|
||||
*.dump
|
||||
*.rdb
|
||||
*.onnx
|
||||
Capfile
|
||||
config/deploy.rb
|
||||
config/deploy/production.rb
|
||||
|
@@ -1,4 +1,5 @@
|
||||
ruby 3.3.0
|
||||
postgres 16.1
|
||||
rust 1.74.1
|
||||
node 20.10.0
|
||||
nodejs 20.10.0
|
||||
redis 7.2.4
|
||||
|
1
Gemfile
1
Gemfile
@@ -29,6 +29,7 @@ gem "georuby"
|
||||
gem "gpx"
|
||||
gem "gnuplot"
|
||||
gem "matrix"
|
||||
gem "redis"
|
||||
|
||||
gem "rack-session"
|
||||
gem "rack-rewrite"
|
||||
|
@@ -364,6 +364,10 @@ GEM
|
||||
rdoc (6.6.2)
|
||||
psych (>= 4.0.0)
|
||||
redcarpet (3.6.0)
|
||||
redis (5.1.0)
|
||||
redis-client (>= 0.17.0)
|
||||
redis-client (0.21.0)
|
||||
connection_pool
|
||||
regexp_parser (2.9.0)
|
||||
reline (0.4.3)
|
||||
io-console (~> 0.5)
|
||||
@@ -562,6 +566,7 @@ DEPENDENCIES
|
||||
rack-test
|
||||
rake
|
||||
redcarpet
|
||||
redis
|
||||
reverse_markdown
|
||||
rexml
|
||||
rom-factory
|
||||
|
@@ -1,3 +1,4 @@
|
||||
web: bundle exec hanami server
|
||||
tailwind: bundle exec rake tailwind:watch
|
||||
assets: bundle exec hanami assets watch
|
||||
redis: redis-server
|
||||
|
@@ -22,8 +22,8 @@ module Adamantium
|
||||
handle_exception ROM::TupleCountMismatchError => :not_found
|
||||
handle_exception StandardError => :handle_error
|
||||
|
||||
def cache(key:, content_proc:, expiry: TimeMath.min.advance(Time.now, +10))
|
||||
cacher.call(key: key, content_proc: content_proc, expiry: expiry)
|
||||
def cache(key:, params: [], content_proc:, expiry: TimeMath.min.advance(Time.now, +10))
|
||||
cacher.call(key: key, params: params, content_proc: content_proc, expiry: expiry)
|
||||
end
|
||||
|
||||
def not_found(_req, res, _exception)
|
||||
|
@@ -4,5 +4,8 @@ Hanami.app.register_provider :clients, namespace: true do
|
||||
register "blue_sky", Adamantium::Client::BlueSky.new
|
||||
register "omdb", Adamantium::Client::Omdb.new(api_key: target["settings"].omdb_api_key)
|
||||
register "gist", Adamantium::Client::Gist.new(token: target["settings"].gist_client_token)
|
||||
|
||||
require "redis"
|
||||
register "redis", Redis.new
|
||||
end
|
||||
end
|
||||
|
@@ -4,6 +4,9 @@ require "adamantium/types"
|
||||
|
||||
module Adamantium
|
||||
class Settings < Hanami::Settings
|
||||
# App Settings
|
||||
setting :cache_store, default: :redis_cache_store
|
||||
|
||||
# Infrastructure
|
||||
setting :database_url
|
||||
|
||||
|
@@ -3,42 +3,30 @@ require "json"
|
||||
module Adamantium
|
||||
module ViewCache
|
||||
class Cacher
|
||||
def call(key:, content_proc:, expiry:)
|
||||
cached_content = read(key: key)
|
||||
include Deps["settings"]
|
||||
|
||||
def call(key:, params:, content_proc:, expiry:)
|
||||
calculated_key = "adamantium:#{key}_#{params.join("_")}"
|
||||
cached_content = cache_store.read(key: calculated_key)
|
||||
|
||||
return cached_content if cached_content
|
||||
|
||||
rendered_content = content_proc.call
|
||||
rendered_content = content_proc.call(*params)
|
||||
|
||||
data = JSON.generate(expire: expiry.to_i, content: rendered_content)
|
||||
|
||||
write(key: key, content: data)
|
||||
cache_store.write(key: calculated_key, content: data, expiry: expiry)
|
||||
|
||||
rendered_content
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def write(key:, content:)
|
||||
filename = "#{key}.json"
|
||||
path = File.join(Hanami.app.root, "tmp", filename)
|
||||
|
||||
File.write(path, content)
|
||||
end
|
||||
|
||||
def read(key:)
|
||||
filename = "#{key}.json"
|
||||
path = File.join(Hanami.app.root, "tmp", filename)
|
||||
|
||||
return nil unless File.exist?(path)
|
||||
|
||||
cached_data = JSON.parse(File.read(path))
|
||||
|
||||
if Time.strptime(cached_data["expire"].to_s, "%s") < Time.now
|
||||
File.delete(path)
|
||||
nil
|
||||
def cache_store
|
||||
if settings.cache_store == :redis_cache_store
|
||||
RedisCacheStore.new
|
||||
else
|
||||
cached_data["content"]
|
||||
FileStore.new
|
||||
end
|
||||
end
|
||||
end
|
||||
|
28
lib/adamantium/view_cache/file_store.rb
Normal file
28
lib/adamantium/view_cache/file_store.rb
Normal file
@@ -0,0 +1,28 @@
|
||||
module Adamantium
|
||||
module ViewCache
|
||||
class FileStore
|
||||
def write(key:, content:, expiry:)
|
||||
filename = "#{key}.json"
|
||||
path = File.join(Hanami.app.root, "tmp", filename)
|
||||
|
||||
File.write(path, content)
|
||||
end
|
||||
|
||||
def read(key:)
|
||||
filename = "#{key}.json"
|
||||
path = File.join(Hanami.app.root, "tmp", filename)
|
||||
|
||||
return nil unless File.exist?(path)
|
||||
|
||||
cached_data = JSON.parse(File.read(path))
|
||||
|
||||
if Time.strptime(cached_data["expire"].to_s, "%s") < Time.now
|
||||
File.delete(path)
|
||||
nil
|
||||
else
|
||||
cached_data["content"]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
18
lib/adamantium/view_cache/redis_cache_store.rb
Normal file
18
lib/adamantium/view_cache/redis_cache_store.rb
Normal file
@@ -0,0 +1,18 @@
|
||||
module Adamantium
|
||||
module ViewCache
|
||||
class RedisCacheStore
|
||||
include Deps["clients.redis"]
|
||||
|
||||
def read(key:)
|
||||
cached_data = redis.get(key)
|
||||
|
||||
JSON.parse(cached_data)["content"] if cached_data
|
||||
end
|
||||
|
||||
def write(key:, content:, expiry:)
|
||||
redis.set(key, content, exat: expiry.to_i)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@@ -4,7 +4,10 @@ module Main
|
||||
class Index < Action
|
||||
include Deps["views.posts.index"]
|
||||
def handle(req, res)
|
||||
res.render index, query: req.params[:q]
|
||||
res.body = cache(key: "posts_index",
|
||||
params: [req.params[:q]],
|
||||
content_proc: ->(q) { res.render index, query: q })
|
||||
res.status = 200
|
||||
end
|
||||
end
|
||||
end
|
||||
|
Reference in New Issue
Block a user