Use redis as a cache store

This commit is contained in:
2024-03-16 19:00:52 +11:00
parent e385e6782e
commit 546c51ed4f
12 changed files with 82 additions and 27 deletions

4
.gitignore vendored
View File

@@ -7,6 +7,8 @@ fly.toml
/publish.rb /publish.rb
/publish_bookmark.rb /publish_bookmark.rb
/publish_photo.rb /publish_photo.rb
/publish_code.rb
/terminal_render.rb
instagram_import.rb instagram_import.rb
node_modules/* node_modules/*
.DS_Store .DS_Store
@@ -14,6 +16,8 @@ node_modules/*
.env.* .env.*
.vimrc.local .vimrc.local
*.dump *.dump
*.rdb
*.onnx
Capfile Capfile
config/deploy.rb config/deploy.rb
config/deploy/production.rb config/deploy/production.rb

View File

@@ -1,4 +1,5 @@
ruby 3.3.0 ruby 3.3.0
postgres 16.1 postgres 16.1
rust 1.74.1 rust 1.74.1
node 20.10.0 nodejs 20.10.0
redis 7.2.4

View File

@@ -29,6 +29,7 @@ gem "georuby"
gem "gpx" gem "gpx"
gem "gnuplot" gem "gnuplot"
gem "matrix" gem "matrix"
gem "redis"
gem "rack-session" gem "rack-session"
gem "rack-rewrite" gem "rack-rewrite"

View File

@@ -364,6 +364,10 @@ GEM
rdoc (6.6.2) rdoc (6.6.2)
psych (>= 4.0.0) psych (>= 4.0.0)
redcarpet (3.6.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) regexp_parser (2.9.0)
reline (0.4.3) reline (0.4.3)
io-console (~> 0.5) io-console (~> 0.5)
@@ -562,6 +566,7 @@ DEPENDENCIES
rack-test rack-test
rake rake
redcarpet redcarpet
redis
reverse_markdown reverse_markdown
rexml rexml
rom-factory rom-factory

View File

@@ -1,3 +1,4 @@
web: bundle exec hanami server web: bundle exec hanami server
tailwind: bundle exec rake tailwind:watch tailwind: bundle exec rake tailwind:watch
assets: bundle exec hanami assets watch assets: bundle exec hanami assets watch
redis: redis-server

View File

@@ -22,8 +22,8 @@ module Adamantium
handle_exception ROM::TupleCountMismatchError => :not_found handle_exception ROM::TupleCountMismatchError => :not_found
handle_exception StandardError => :handle_error handle_exception StandardError => :handle_error
def cache(key:, content_proc:, expiry: TimeMath.min.advance(Time.now, +10)) def cache(key:, params: [], content_proc:, expiry: TimeMath.min.advance(Time.now, +10))
cacher.call(key: key, content_proc: content_proc, expiry: expiry) cacher.call(key: key, params: params, content_proc: content_proc, expiry: expiry)
end end
def not_found(_req, res, _exception) def not_found(_req, res, _exception)

View File

@@ -4,5 +4,8 @@ Hanami.app.register_provider :clients, namespace: true do
register "blue_sky", Adamantium::Client::BlueSky.new register "blue_sky", Adamantium::Client::BlueSky.new
register "omdb", Adamantium::Client::Omdb.new(api_key: target["settings"].omdb_api_key) 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) register "gist", Adamantium::Client::Gist.new(token: target["settings"].gist_client_token)
require "redis"
register "redis", Redis.new
end end
end end

View File

@@ -4,6 +4,9 @@ require "adamantium/types"
module Adamantium module Adamantium
class Settings < Hanami::Settings class Settings < Hanami::Settings
# App Settings
setting :cache_store, default: :redis_cache_store
# Infrastructure # Infrastructure
setting :database_url setting :database_url

View File

@@ -3,42 +3,30 @@ require "json"
module Adamantium module Adamantium
module ViewCache module ViewCache
class Cacher class Cacher
def call(key:, content_proc:, expiry:) include Deps["settings"]
cached_content = read(key: key)
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 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) 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 rendered_content
end end
private private
def write(key:, content:) def cache_store
filename = "#{key}.json" if settings.cache_store == :redis_cache_store
path = File.join(Hanami.app.root, "tmp", filename) RedisCacheStore.new
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 else
cached_data["content"] FileStore.new
end end
end end
end end

View 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

View 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

View File

@@ -4,7 +4,10 @@ module Main
class Index < Action class Index < Action
include Deps["views.posts.index"] include Deps["views.posts.index"]
def handle(req, res) 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 end
end end