Start stubbing an S3 blob cache
This commit is contained in:
parent
899f8c6fbc
commit
b5f2c2df1a
4 changed files with 98 additions and 10 deletions
|
|
@ -2,9 +2,9 @@
|
|||
|
||||
begin
|
||||
require 'cbor'
|
||||
rescue LoadError
|
||||
require 'json'
|
||||
rescue LoadError # Load CBOR if possible
|
||||
end
|
||||
require 'json'
|
||||
|
||||
module FicTracker::Util
|
||||
class Cache
|
||||
|
|
@ -26,6 +26,9 @@ module FicTracker::Util
|
|||
when :redis, 'redis'
|
||||
require_relative 'cache/redis'
|
||||
cache = CacheImpl::Redis.new(**options)
|
||||
when :s3, 'S3'
|
||||
require_relative 'cache/s3'
|
||||
cache = CacheImpl::Redis.new(**options)
|
||||
when :none, 'none', nil
|
||||
require_relative 'cache/dummy'
|
||||
cache = CacheImpl::Dummy.new
|
||||
|
|
@ -127,8 +130,8 @@ module FicTracker::Util
|
|||
|
||||
def best_encoder?(data)
|
||||
pod_encoder = :none if data.is_a?(String)
|
||||
pod_encoder ||= :cbor if Object.const_defined?(:CBOR)
|
||||
pod_encoder ||= :json if Object.const_defined?(:JSON)
|
||||
pod_encoder ||= :cbor if Object.const_defined?(:CBOR) && data.respond_to?(:to_cbor)
|
||||
pod_encoder ||= :json if Object.const_defined?(:JSON) && data.respond_to?(:to_json)
|
||||
pod_encoder ||= :marshal
|
||||
return pod_encoder if is_pod?(data)
|
||||
|
||||
|
|
@ -139,11 +142,9 @@ module FicTracker::Util
|
|||
encode ||= @encoder
|
||||
encode ||= best_encoder?(data)
|
||||
|
||||
flags = 0
|
||||
flags = ENCODING_NONE
|
||||
case encode
|
||||
when :none
|
||||
data = data
|
||||
flags |= ENCODING_NONE
|
||||
when :marshal
|
||||
data = Marshal.dump(data)
|
||||
flags |= ENCODING_MARSHAL
|
||||
|
|
|
|||
2
lib/fic_tracker/util/cache/database.rb
vendored
2
lib/fic_tracker/util/cache/database.rb
vendored
|
|
@ -12,8 +12,8 @@ module FicTracker::Util::CacheImpl
|
|||
end
|
||||
|
||||
def expire
|
||||
@dataset.where { Sequel::CURRENT_DATE >= expire_at }.update(expired: true)
|
||||
dataset_expired.delete
|
||||
@dataset.where { Sequel::CURRENT_DATE >= expire_at }.update(expired: true)
|
||||
end
|
||||
|
||||
def has?(key)
|
||||
|
|
|
|||
4
lib/fic_tracker/util/cache/file.rb
vendored
4
lib/fic_tracker/util/cache/file.rb
vendored
|
|
@ -7,7 +7,7 @@ module FicTracker::Util::CacheImpl
|
|||
# A filesystem-backed in-memory cache
|
||||
class File < Base
|
||||
def initialize(dir: nil)
|
||||
@dir = dir || Dir.mktmpdir('ficagg')
|
||||
@dir = dir || Dir.mktmpdir('fictrack')
|
||||
|
||||
@internal = Memory.new
|
||||
end
|
||||
|
|
@ -88,7 +88,7 @@ module FicTracker::Util::CacheImpl
|
|||
|
||||
def meta_valid?(meta)
|
||||
return true unless meta[:ttl]
|
||||
|
||||
|
||||
Time.now < Time.at(meta[:ttl])
|
||||
end
|
||||
|
||||
|
|
|
|||
87
lib/fic_tracker/util/cache/s3.rb
vendored
Normal file
87
lib/fic_tracker/util/cache/s3.rb
vendored
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 's3-light'
|
||||
|
||||
class S3Light::Object
|
||||
def read
|
||||
response = client.with_connection do |connection|
|
||||
connection.make_request(:get, "/#{bucket.name}/#{key}")
|
||||
end
|
||||
|
||||
response.body.to_s
|
||||
end
|
||||
end
|
||||
|
||||
module FicTracker::Util::CacheImpl
|
||||
# A cache using an S3 bucket
|
||||
class S3 < Base
|
||||
def initialize(access_key:, secret_key:, bucket:, **s3)
|
||||
@connection = nil # ...
|
||||
@bucket = nil # ...
|
||||
@objects = @bucket.objects
|
||||
|
||||
load_bucket!
|
||||
end
|
||||
|
||||
def expire
|
||||
to_destroy = @objects.all.reject do |obj|
|
||||
obj.key.end_with?('.meta') || check_meta(obj.key)
|
||||
end
|
||||
return if to_destroy.empty?
|
||||
|
||||
@objects.destroy_batch keys: to_destroy.map(&:key)
|
||||
end
|
||||
|
||||
def has?(key)
|
||||
return check_meta key
|
||||
end
|
||||
|
||||
def get(key)
|
||||
return nil unless check_meta key
|
||||
|
||||
@objects.find_by(key:).read
|
||||
end
|
||||
|
||||
def set(key, value, expiry = nil)
|
||||
expiry = expiry >= 0 ? Time.now + expiry : nil if expiry.is_a?(Numeric)
|
||||
expiry = nil if expiry.is_a?(Numeric)
|
||||
meta = {
|
||||
key: key,
|
||||
ttl: expiry&.to_i
|
||||
}.compact.to_json
|
||||
|
||||
@objects.new(key:, input: value).save!
|
||||
@objects.new(key: "#{key}.meta", input: meta.to_json).save!
|
||||
|
||||
value
|
||||
end
|
||||
|
||||
def delete(key)
|
||||
@objects.destroy_batch keys: [
|
||||
key,
|
||||
"#{key}.meta"
|
||||
]
|
||||
nil
|
||||
end
|
||||
|
||||
def clear
|
||||
to_destroy = @objects.all.map(&:key)
|
||||
return if to_destroy.empty?
|
||||
|
||||
@objects.destroy_batch keys: to_destroy
|
||||
nil
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def check_meta(key)
|
||||
meta_key = "#{key}.meta"
|
||||
return true unless @objects.exists? meta_key
|
||||
|
||||
meta = JSON.parse(@objects.find_by(key: meta_key))
|
||||
return true unless meta[:ttl]
|
||||
|
||||
Time.now < Time.at(meta[:ttl])
|
||||
end
|
||||
end
|
||||
end
|
||||
Loading…
Add table
Reference in a new issue