Comparison

plugins/mod_http_file_share.lua @ 11332:3e0dcdf6283e

mod_http_file_share: Cache file metadata For faster access by avoiding archive ID. No benchmarks were harmed in the making of this commit. ... no benchmarks were performed at all.
author Kim Alvefur <zash@zash.se>
date Thu, 28 Jan 2021 16:34:13 +0100
parent 11331:7a915fa49373
child 11333:f80056b97cf0
comparison
equal deleted inserted replaced
11331:7a915fa49373 11332:3e0dcdf6283e
15 local jwt = require "util.jwt"; 15 local jwt = require "util.jwt";
16 local errors = require "util.error"; 16 local errors = require "util.error";
17 local dataform = require "util.dataforms".new; 17 local dataform = require "util.dataforms".new;
18 local dt = require "util.datetime"; 18 local dt = require "util.datetime";
19 local hi = require "util.human.units"; 19 local hi = require "util.human.units";
20 local cache = require "util.cache";
20 21
21 local namespace = "urn:xmpp:http:upload:0"; 22 local namespace = "urn:xmpp:http:upload:0";
22 23
23 module:depends("disco"); 24 module:depends("disco");
24 25
52 filesize = { type = "modify"; condition = "not-acceptable"; text = "File too large"; 53 filesize = { type = "modify"; condition = "not-acceptable"; text = "File too large";
53 extra = {tag = st.stanza("file-too-large", {xmlns = namespace}):tag("max-file-size"):text(tostring(file_size_limit)) }; 54 extra = {tag = st.stanza("file-too-large", {xmlns = namespace}):tag("max-file-size"):text(tostring(file_size_limit)) };
54 }; 55 };
55 filesizefmt = { type = "modify"; condition = "bad-request"; text = "File size must be positive integer"; } 56 filesizefmt = { type = "modify"; condition = "bad-request"; text = "File size must be positive integer"; }
56 }); 57 });
58
59 local upload_cache = cache.new(1024);
57 60
58 -- Convenience wrapper for logging file sizes 61 -- Convenience wrapper for logging file sizes
59 local function B(bytes) return hi.format(bytes, "B", "b"); end 62 local function B(bytes) return hi.format(bytes, "B", "b"); end
60 63
61 local function get_filename(slot, create) 64 local function get_filename(slot, create)
212 uploaded, err = false, 413; 215 uploaded, err = false, 413;
213 end 216 end
214 if uploaded then 217 if uploaded then
215 module:log("debug", "Upload of %q completed, %s", filename, B(final_size)); 218 module:log("debug", "Upload of %q completed, %s", filename, B(final_size));
216 assert(os.rename(filename.."~", filename)); 219 assert(os.rename(filename.."~", filename));
220
221 upload_cache:set(upload_info.slot, {
222 name = upload_info.filename;
223 size = tostring(upload_info.filesize);
224 type = upload_info.filetype;
225 time = os.time();
226 });
217 return 201; 227 return 201;
218 else 228 else
219 assert(os.remove(filename.."~")); 229 assert(os.remove(filename.."~"));
220 return err; 230 return err;
221 end 231 end
224 end 234 end
225 235
226 function handle_download(event, path) -- GET /uploads/:slot+filename 236 function handle_download(event, path) -- GET /uploads/:slot+filename
227 local request, response = event.request, event.response; 237 local request, response = event.request, event.response;
228 local slot_id = path:match("^[^/]+"); 238 local slot_id = path:match("^[^/]+");
229 -- TODO cache
230 local basename, filetime, filetype, filesize; 239 local basename, filetime, filetype, filesize;
231 local slot, when = errors.coerce(uploads:get(nil, slot_id)); 240 local cached = upload_cache:get(slot_id);
232 if not slot then 241 if cached then
233 module:log("debug", "uploads:get(%q) --> not-found, %s", slot_id, when); 242 module:log("debug", "Cache hit");
243 -- TODO stats (instead of logging?)
244 basename = cached.name;
245 filesize = cached.size;
246 filetype = cached.type;
247 filetime = cached.time;
248 upload_cache:set(slot_id, cached);
249 -- TODO cache negative hits?
234 else 250 else
235 basename = slot.attr.filename; 251 module:log("debug", "Cache miss");
236 filesize = slot.attr.size; 252 local slot, when = errors.coerce(uploads:get(nil, slot_id));
237 filetype = slot.attr["content-type"]; 253 if not slot then
238 filetime = when; 254 module:log("debug", "uploads:get(%q) --> not-found, %s", slot_id, when);
255 else
256 module:log("debug", "uploads:get(%q) --> %s, %d", slot_id, slot, when);
257 basename = slot.attr.filename;
258 filesize = slot.attr.size;
259 filetype = slot.attr["content-type"];
260 filetime = when;
261 upload_cache:set(slot_id, {
262 name = basename;
263 size = slot.attr.size;
264 type = filetype;
265 time = when;
266 });
267 end
239 end 268 end
240 if not basename then 269 if not basename then
241 return 404; 270 return 404;
242 end 271 end
243 module:log("debug", "uploads:get(%q) --> %s, %d", slot_id, slot, when);
244 local last_modified = os.date('!%a, %d %b %Y %H:%M:%S GMT', filetime); 272 local last_modified = os.date('!%a, %d %b %Y %H:%M:%S GMT', filetime);
245 if request.headers.if_modified_since == last_modified then 273 if request.headers.if_modified_since == last_modified then
246 return 304; 274 return 304;
247 end 275 end
248 local filename = get_filename(slot_id); 276 local filename = get_filename(slot_id);
290 local obsolete_files = array(); 318 local obsolete_files = array();
291 local i = 0; 319 local i = 0;
292 for slot_id in iter do 320 for slot_id in iter do
293 i = i + 1; 321 i = i + 1;
294 obsolete_files:push(get_filename(slot_id)); 322 obsolete_files:push(get_filename(slot_id));
323 upload_cache:set(slot_id, nil);
295 end 324 end
296 325
297 sleep(0.1); 326 sleep(0.1);
298 local n = 0; 327 local n = 0;
299 obsolete_files:filter(function(filename) 328 obsolete_files:filter(function(filename)