local sql = require("lsqlite3") local queries = require("queries") local util = require("util") local ret = {} local stmnt_cache, stmnt_insert_cache local oldconfigure = configure function configure(...) local cache = sqlassert(sql.open_memory()) --A cache table to store rendered pages that do not need to be --rerendered. In theory this could OOM the program eventually and start --swapping to disk. TODO: fixme assert(cache:exec([[ CREATE TABLE IF NOT EXISTS cache ( path TEXT PRIMARY KEY, data BLOB, updated INTEGER, dirty INTEGER ); ]])) stmnt_cache = cache:prepare([[ SELECT data FROM cache WHERE path = :path AND ((dirty = 0) OR (strftime('%s','now') - updated) < 20) ; ]]) stmnt_insert_cache = cache:prepare([[ INSERT OR REPLACE INTO cache ( path, data, updated, dirty ) VALUES ( :path, :data, strftime('%s','now'), 0 ); ]]) stmnt_dirty_cache = cache:prepare([[ UPDATE OR IGNORE cache SET dirty = 1 WHERE path = :path; ]]) return oldconfigure(...) end --Render a page, with cacheing. If you need to dirty a cache, call dirty_cache() function ret.render(pagename,callback) print("Running render...") stmnt_cache:bind_names{path=pagename} local err = util.do_sql(stmnt_cache) if err == sql.DONE then stmnt_cache:reset() --page is not cached elseif err == sql.ROW then print("Cache hit:" .. pagename) data = stmnt_cache:get_values() stmnt_cache:reset() return data[1] else --sql.ERROR or sql.MISUSE error("Failed to check cache for page " .. pagename) end --We didn't have the paged cached, render it print("Cache miss, running function") local text = callback() print("Saving data...") --And save the data back into the cache stmnt_insert_cache:bind_names{ path=pagename, data=text, } err = util.do_sql(stmnt_insert_cache) if err == sql.ERROR or err == sql.MISUSE then error("Failed to update cache for page " .. pagename) end stmnt_insert_cache:reset() return text end function ret.dirty(url) print("Dirtying cache:",url) stmnt_dirty_cache:bind_names{ path = url } err = util.do_sql(stmnt_dirty_cache) stmnt_dirty_cache:reset() end function ret.close() end return ret