Documentation
Document various methods in db.lua and cache.lua
This commit is contained in:
parent
e430d9b512
commit
677f05d69c
|
@ -1,8 +1,11 @@
|
|||
--[[
|
||||
Implements a simple in-memory cache. The cache has no upper size limit, and
|
||||
may cause out-of-memory errors. When this happens, the OS will kill the kore
|
||||
worker process, and the kore parent process will restart with a fresh, empty
|
||||
cache
|
||||
--[[ md
|
||||
|
||||
@name lua/cache
|
||||
|
||||
Implements a simple in memory read through cache.
|
||||
The cache has no upper size limit, and may cause out-of-memory errors.
|
||||
When this happens, the OS will kill the kore worker process,
|
||||
and the kore parent process will restart with a fresh, empty cache.
|
||||
]]
|
||||
|
||||
local sql = require("lsqlite3")
|
||||
|
@ -15,6 +18,68 @@ local ret = {}
|
|||
|
||||
local stmnt_cache, stmnt_insert_cache, stmnt_dirty_cache
|
||||
|
||||
--[[ cat
|
||||
@name lua/cache
|
||||
<h3>Schema for Cache</h3>
|
||||
<p>The cache mechanism is a in-memeory sqlite3 database behind the scenes, it
|
||||
can ensure consistency and atomic updates & dirtying, though it doesn't today.</p>
|
||||
<table>
|
||||
<caption>cache</caption>
|
||||
<tr>
|
||||
<th>Attributes</th>
|
||||
<th>Field</th>
|
||||
<th>Type</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Primary Key</td>
|
||||
<td>path</td>
|
||||
<td>TEXT</td>
|
||||
<td>
|
||||
The logical path this text was rendered at,
|
||||
before browser-specific headers (like accept-encoding)
|
||||
are applied
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>data</td>
|
||||
<td>BLOB</td>
|
||||
<td>
|
||||
The returned result from the function passed into
|
||||
cache.render(), the result must be a string, and
|
||||
may contain nulls.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>updated</td>
|
||||
<td>INTEGER</td>
|
||||
<td>
|
||||
The time this item was rendered at, can be used to set
|
||||
a minimum update frequency. This is used so that web
|
||||
scrapers don't constantly trigger re-renders of the
|
||||
index page.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>dirty</td>
|
||||
<td>INTEGER</td>
|
||||
<td>
|
||||
Does this page need to be re-rendered the next time it
|
||||
is called? For example, an author's story could have
|
||||
multiple hits, which would require rerendering their
|
||||
author page to show the new hit count, but we don't
|
||||
actually need to do it until someone requests the
|
||||
author page. In this case, we keep the old page around
|
||||
to save time trying to clear it and potentially hit
|
||||
sqlite's garbage collector.
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
]]
|
||||
|
||||
local oldconfigure = configure
|
||||
function configure(...)
|
||||
ret.cache = db.sqlassert(sql.open_memory())-- Expose db for testing
|
||||
|
@ -52,7 +117,40 @@ function configure(...)
|
|||
return oldconfigure(...)
|
||||
end
|
||||
|
||||
--Render a page, with cacheing. If you need to dirty a cache, call dirty_cache()
|
||||
--[[ md
|
||||
@name lua/cache
|
||||
|
||||
### cache.render
|
||||
|
||||
Render a page with cacheing.
|
||||
The callback will be called with no arguments, and must return a string.
|
||||
|
||||
Parameters:
|
||||
|
||||
0. pagename - {{lua/string}} - A logical string to associate with this
|
||||
rendered page, this must be passed exactly into render() in order
|
||||
to (potentially) retrive the cached page.
|
||||
0. callback - {{lua/function}} - A function that may be called,
|
||||
if it is called, it is called with no arguments, and must return a string.
|
||||
The returned string may have embedded nulls.
|
||||
|
||||
Returns:
|
||||
|
||||
0. {{lua/string}} - Either the return of the passed function, or the cached
|
||||
string.
|
||||
|
||||
Example:
|
||||
|
||||
cache = require("cache")
|
||||
func = function()
|
||||
print("Called")
|
||||
return "Hello, world!"
|
||||
end
|
||||
print(cache.render("/test",func)) -- prints "Called", then "Hello, world!"
|
||||
print(cache.render("/test",func)) -- prints "Hello, world!"
|
||||
print(cache.render("/test",func)) -- prints "Hello, world!"
|
||||
|
||||
]]
|
||||
function ret.render(pagename,callback)
|
||||
stmnt_cache:bind_names{path=pagename}
|
||||
local err = db.do_sql(stmnt_cache)
|
||||
|
@ -81,8 +179,37 @@ function ret.render(pagename,callback)
|
|||
return text
|
||||
end
|
||||
|
||||
-- Dirty a cached page, causing it to be re-rendered the next time it's
|
||||
-- requested. Doesn't actually delete it or anything, just sets it's dirty bit
|
||||
--[[ md
|
||||
@name lua/cache
|
||||
|
||||
### cache.dirty
|
||||
|
||||
Dirty a cached page, causing it to be re-rendered the next time it's
|
||||
requested. Doesn't actually delete it or free memory, just sets its dirty bit.
|
||||
If the page does not exists or has not been rendered yet, this function does
|
||||
not error.
|
||||
|
||||
Parameters:
|
||||
|
||||
0. url - {{lua/string}} - `pagename` from the render function, the logical
|
||||
string associcated with this rendered page.
|
||||
|
||||
No returns
|
||||
|
||||
Example:
|
||||
|
||||
cache = require("cache")
|
||||
func = function()
|
||||
print("Called")
|
||||
return "Hello, world!"
|
||||
end
|
||||
print(cache.render("/test",func)) -- prints "Called", then "Hello, world!"
|
||||
print(cache.render("/test",func)) -- prints "Hello, world!")
|
||||
cache.dirty("/test")
|
||||
print(cache.render("/test",func)) -- prints "Called", then "Hello, world!"
|
||||
print(cache.render("/test",func)) -- prints "Hello, world!"
|
||||
]]
|
||||
|
||||
function ret.dirty(url)
|
||||
stmnt_dirty_cache:bind_names{
|
||||
path = url
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
--[[ md
|
||||
@name lua/db
|
||||
|
||||
## Overview
|
||||
|
||||
Does most of the database interaction.
|
||||
Creates default empty database during configure()
|
||||
Notably, holds a connection to the open sqlite3 database in .conn
|
||||
]]
|
||||
local sql = require("lsqlite3")
|
||||
|
@ -11,7 +15,9 @@ local config = require("config")
|
|||
local db = {}
|
||||
|
||||
--[[ md
|
||||
@name lua/db/sqlassert
|
||||
@name lua/db
|
||||
|
||||
### db.sqlassert
|
||||
|
||||
Runs an sql query and receives the 3 arguments back, prints a nice error
|
||||
message on fail, and returns true on success.
|
||||
|
@ -36,8 +42,8 @@ that error checking and assignment can all be done on a single line.
|
|||
|
||||
Example:
|
||||
|
||||
> db = require("db")
|
||||
> query = db.sqlassert(db.conn:parepare("SELECT 'Hello, world!'"))
|
||||
db = require("db")
|
||||
query = db.sqlassert(db.conn:parepare("SELECT 'Hello, world!'"))
|
||||
]]
|
||||
function db.sqlassert(r, errcode, err)
|
||||
if not r then
|
||||
|
@ -51,7 +57,9 @@ function db.sqlassert(r, errcode, err)
|
|||
end
|
||||
|
||||
--[[ md
|
||||
@name lua/db/do_sql
|
||||
@name lua/db
|
||||
|
||||
### db.do_sql
|
||||
|
||||
Continuously tries to perform an sql statement until it goes through. This function may call {{lua/coroutine/yield}}
|
||||
|
||||
|
@ -65,12 +73,12 @@ Returns:
|
|||
|
||||
Example:
|
||||
|
||||
> sql = require("lsqlite3")
|
||||
> configure = function(...) end -- Mock smr environment
|
||||
> db = require("db")
|
||||
> configure()
|
||||
> query = db.conn:prepare("SELECT 'Hello, world!';")
|
||||
> assert(db.do_sql(query))
|
||||
sql = require("lsqlite3")
|
||||
configure = function(...) end -- Mock smr environment
|
||||
db = require("db")
|
||||
configure()
|
||||
query = db.conn:prepare("SELECT 'Hello, world!';")
|
||||
assert(db.do_sql(query))
|
||||
]]
|
||||
function db.do_sql(stmnt)
|
||||
if not stmnt then error("No statement",2) end
|
||||
|
@ -88,7 +96,9 @@ function db.do_sql(stmnt)
|
|||
end
|
||||
|
||||
--[[ md
|
||||
@name lua/db/sql_rows
|
||||
@name lua/db
|
||||
|
||||
### db.sql_rows
|
||||
|
||||
Provides an iterator that loops over results in an sql statement or throws an
|
||||
error, then resets the statement after the loop is done.
|
||||
|
@ -107,12 +117,11 @@ Returns:
|
|||
|
||||
Example:
|
||||
|
||||
> db = require("db")
|
||||
> query = db.conn:prepare("SELECT 'Hello, world!';")
|
||||
> for row in db.sql_rows(query) do
|
||||
> print(row)
|
||||
> end
|
||||
Hello, world!
|
||||
db = require("db")
|
||||
query = db.conn:prepare("SELECT 'Hello, world!';")
|
||||
for row in db.sql_rows(query) do
|
||||
print(row) -- prints 'Hello, world!'
|
||||
end
|
||||
|
||||
]]
|
||||
function db.sql_rows(stmnt)
|
||||
|
@ -141,14 +150,24 @@ function db.sql_rows(stmnt)
|
|||
end
|
||||
end
|
||||
|
||||
--[[
|
||||
@name lua/db/sqlbind
|
||||
--[[ md
|
||||
@name lua/db
|
||||
|
||||
Binds an argument to as statement with nice error reporting on failure. Approximatly the same as {{lsqlite/stmt/bind_names}}, but with better error reporting.
|
||||
stmnt :: sql.stmnt - the prepared sql statemnet
|
||||
call :: string - a string "bind" or "bind_blob"
|
||||
position :: number - the argument position to bind to
|
||||
data :: string - The data to bind
|
||||
### db.sqlbind
|
||||
|
||||
Binds an argument to a prepared statement,
|
||||
with nice error reporting on failure.
|
||||
Wraps {{lsqlite/stmnt/bind_name}}
|
||||
with better error reporting.
|
||||
|
||||
Parameters:
|
||||
|
||||
0. stmnt - {{lsqlite/stmnt}} - The prepared statement from {{sqlite/db/prepare}}
|
||||
0. call - {{lua/string}} - Literal string, options are `bind` for most types, or `bind_blob` for strings that may contain embedded nulls
|
||||
0. position - {{lua/number}} - The argument position to bind to, does not support named parameters
|
||||
0. data - Any - the data to bind
|
||||
|
||||
Returns nothing
|
||||
]]
|
||||
function db.sqlbind(stmnt,call,position,data)
|
||||
assert(call == "bind" or call == "bind_blob","Bad bind call, call was:" .. call)
|
||||
|
@ -166,8 +185,6 @@ function db.sqlbind(stmnt,call,position,data)
|
|||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
local oldconfigure = configure
|
||||
db.conn = db.sqlassert(sql.open(config.db))
|
||||
function configure(...)
|
||||
|
@ -191,6 +208,18 @@ function configure(...)
|
|||
return oldconfigure(...)
|
||||
end
|
||||
|
||||
--[[ md
|
||||
|
||||
### db.close()
|
||||
|
||||
Closes the database connection. Not called during normal operation, used to
|
||||
assist in unit testing.
|
||||
|
||||
No parameters
|
||||
|
||||
No returns
|
||||
]]
|
||||
|
||||
function db.close()
|
||||
db.conn:close()
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue