1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
|
# -*- coding: utf-8 -*-
require 'moneta'
Plugin.create :image_file_cache do
@queue = Delayer.generate_class(priority: %i[none check_subdirs check_dirs],
default: :none,
expire: 0.02)
@cache_directory = File.join(Environment::CACHE, 'image_file_cache').freeze
@db = ::Moneta.build(&->(dir){ ->(this){
this.use :Transformer, key: %i[md5 spread]
this.adapter(:File, dir: dir)
} }.(@cache_directory))
on_image_file_cache_cache do |url|
photos = Enumerator.new{|y|
Plugin.filtering(:photo_filter, url, y)
}
Plugin.call(:image_file_cache_photo, photos.first)
end
on_image_file_cache_photo do |photo|
cache_it(photo)
end
# キャッシュがあれば画像を返す
filter_image_cache do |url, image, &stop|
begin
body = @db[url]
if body
stop.call([url, body]) end
[url, image]
rescue => e
error e
[url, image] end end
# キャッシュの有効期限を秒単位で返す
def cache_expire
(UserConfig[:image_file_cache_expire] || 7) * 24 * 60 * 60 end
def cache_it(photo)
notice "cache added #{photo.uri}"
photo.download.next{|downloaded|
@db[downloaded.uri.to_s] = downloaded.blob
}
end
def check_subdirs(dir)
@queue.new(:check_subdirs) do
Dir.foreach(dir)
.map{|x| File.join(dir, x) }
.select{|x| FileTest.file?(x) }
.each{|x|
Reserver.new((File.atime(x) rescue File.mtime(x)) + cache_expire, thread: SerialThread) do
notice "cache deleted #{x}"
File.delete(x) if FileTest.file?(x)
if Dir.foreach(dir).select{|y| File.file? File.join(dir, y) }.empty?
Dir.delete(dir) rescue nil end end
}
end
end
def check_dirs
@queue.new(:check_dirs) do
Dir.foreach(@cache_directory)
.select{|x| x =~ %r<\A[a-fA-F0-9]{2}\Z> }
.shuffle
.each{|subdir|
check_subdirs(File.join(@cache_directory, subdir))
}
Reserver.new(cache_expire, thread: SerialThread) do
check_dirs end
end
end
def _loop
Reserver.new(60, thread: SerialThread) do
if @queue
@queue.run
_loop end end end
on_unload do
@db.close
@db = @queue = nil
end
check_dirs
_loop
end
|