Skip to content

Commit

Permalink
Code is messy but all tests pass.
Browse files Browse the repository at this point in the history
  • Loading branch information
slact committed Feb 1, 2011
1 parent 86b8359 commit 9e7d914
Show file tree
Hide file tree
Showing 7 changed files with 71 additions and 70 deletions.
2 changes: 0 additions & 2 deletions lohm.lua
Expand Up @@ -6,7 +6,6 @@ module ("lohm", function(t)
__call = function(self, ...) return t.new(...) end,
__index = function(self, k)
return function(arg, redis)
debug.print("ARRG",self, k, arg)
arg.type=k
return Model.new(arg, redis)
end
Expand All @@ -21,7 +20,6 @@ end)
-- indices (table): attributes to index (and with what index, if given. defaults to Index:defaultIndex()

function new(arg, redis_connection)
debug.print("GRARG", arg)
local res, err = Model.new(arg, redis_connection)
return res, err
end
Expand Down
32 changes: 14 additions & 18 deletions lohm/data.lua
Expand Up @@ -35,7 +35,6 @@ end)
local ccreate, cresume, cstatus = coroutine.create, coroutine.resume, coroutine.status

function transactionize(self, redis, callbacks)
debug.print(callbacks)
local transaction_coroutines = {} --TODO: reuse this table, memoize more, etc.
for i,naked_callback in pairs(callbacks) do
table.insert(transaction_coroutines, ccreate(naked_callback))
Expand All @@ -52,7 +51,7 @@ function transactionize(self, redis, callbacks)
while i<=#transaction_coroutines do
local transaction_callback = transaction_coroutines[i]
success, last_ret, last_err = assert(cresume(transaction_callback, self, redis, my_id))
print("PREMULTI", success, last_ret, last_err)
--print("PREMULTI", success, last_ret, last_err)
if cstatus(transaction_callback)~='dead' then
i = i + 1
else
Expand All @@ -66,7 +65,7 @@ function transactionize(self, redis, callbacks)
local transaction_callback = transaction_coroutines[i]
local already_queued = redis:commands_queued()
success, last_ret, last_err = assert(cresume(transaction_callback))
print("MULTI ", success, last_ret, last_err)
--print("MULTI ", success, last_ret, last_err)
if cstatus(transaction_callback) ~= 'dead' then
queued_commands_offset[transaction_callback]={ already_queued, redis:commands_queued() }
i = i + 1
Expand All @@ -78,7 +77,7 @@ function transactionize(self, redis, callbacks)
if not res then return nil, err end
for i, transaction_callback in ipairs(transaction_coroutines) do
success, last_ret, last_err = assert(cresume(transaction_callback, tslice(res, unpack(queued_commands_offset[transaction_callback]))))
print("POSTMULTI", success, last_ret, last_err)
--print("POSTMULTI", success, last_ret, last_err)
--we no longer care about the coroutine's status. we're done.
end
if not last_ret and not last_err then
Expand Down Expand Up @@ -144,15 +143,6 @@ function new(datatype, model, arg)
return self
end,

addCallbackIterator = function(self, event_name, iterator)
--this is beginning to seem more and more like a decent hack
--and less and less a sound architectural decision.
assert(type(iterator) ~= 'function', "no iterator provided")
assert(event_name, "realistic event name please")
table.insert(callback_iterators[event_name], iterator)
return self
end,

addCallbacks = function(self, event_name, callbacks, bind_to)
for i, cb in pairs(callbacks) do
assert(self:addCallback(event_name, cb))
Expand All @@ -170,19 +160,17 @@ function new(datatype, model, arg)
}
for i, operation in pairs{'load', 'delete', 'save'} do
data_prototype[operation]=function(self, redis)
print(operation, "IN PROGRESS")
local key = self:getKey()
if not key and operation=='save' then
self:setId(model:reserveNextId(redis))
key = self:getKey()
end
if not key then error(("Cannot %s data without a key"):format(operation)) end
local res, err = transactionize(self, model.redis, self:getCallbacks(operation))
print(type(res), err)
return (res and self), err
end
end

--merge custom object properties into the prototype
for i,v in pairs(arg.prototype or arg.object or {}) do
if not rawget(data_prototype, i) then
Expand All @@ -192,6 +180,14 @@ function new(datatype, model, arg)
end
end

local obj = require("lohm." .. datatype)
return obj.initialize(data_prototype, arg)
--should this expire automatcally?
if arg.expire then
data_prototype:addCallback('save', function(self, redis)
redis:multi()
assert(redis:expire(self:getKey(), arg.expire or 30))
end)
end

local obj_module = require("lohm." .. datatype)
return obj_module.initialize(data_prototype, arg)
end
24 changes: 15 additions & 9 deletions lohm/hash.lua
@@ -1,6 +1,8 @@
local print, getmetatable, rawget = print, getmetatable, rawget
local pairs, ipairs, table, error, setmetatable, assert, type, coroutine, unpack, next = pairs, ipairs, table, error, setmetatable, assert, type, coroutine, unpack, next
local lohm = require "lohm"
local Query = require "lohm.index".query
local Index = require "lohm.index"
local debug = debug
local function I(...) return ... end
local Index = require "lohm.index"
Expand Down Expand Up @@ -102,8 +104,6 @@ function initialize(prototype, arg)
local id = redis:hget(self:getKey(), attr_name)
if id then val:setId(id) end
end
debug.print("UNVAL", attributes)
print("VALLY", rawget(self, attr_name), event, val, type(val))
assert(rawget(val,queued) ~= true) --redis-lua queued indicator
if val.getKey then
local key = val:getKey()
Expand All @@ -118,7 +118,6 @@ function initialize(prototype, arg)
val = attr_model:new({}, val, false)
self[attr_name]=val
end
debug.print("VAL", event, attr_name, val, "here okay")
assert(val==rawget(self, attr_name))
return callback(val, redis)
end)
Expand Down Expand Up @@ -147,31 +146,39 @@ function initialize(prototype, arg)
if type(attr)=='table' then
attr, index = i, attr
else
index = Index:new(indexType, model, attr)
index = Index.new(model, attr)
end

indices[attr] = index

prototype:addCallback('save', function(self, redis)
local savedval = redis:hget(self:getKey(), attr)
assert(index:update(self, redis, self:getId(), self[attr], savedval))
local newval = rawget(self, attr) --mustn't trigger autoloader
if type(newval)=='table' then
newval = newval:getId()
end
assert(type(newval)~='table')
assert(self:getId())
assert(index:update(self:getId(), newval, savedval))
end)

prototype:addCallback('delete', function(self, redis)
local savedval = redis:hget(self:getKey(), attr)
assert(index:update(self, redis, self:getId(), nil, savedval))
assert(index:update(self:getId(), nil, savedval))
end)
end
end
model.findByAttr = function(self, arg)
local query
for attr, val in pairs(arg) do
local this_set = indices[attr](val)
if query then
query:intersect(indices[attr](val))
query:intersect(this_set)
else
query = lohm.query(indices[attr](val))
query = Query(this_set, model)
end
end
model.redis:echo("FOO")
return query:exec()
end

Expand All @@ -195,7 +202,6 @@ function initialize(prototype, arg)
return proto
else
local key = self:getKey()
print(key, attr)
if key then
local res = attributes[attr].load(self, model.redis, attr)
self[attr]=res
Expand Down
55 changes: 31 additions & 24 deletions lohm/index.lua
@@ -1,5 +1,6 @@
local print, type, assert, pcall, require, table, tostring, pairs, ipairs, setmetatable = print, type, assert, pcall, require, table, tostring, pairs, ipairs, setmetatable
local error = error
local debug = debug
local lohm = require "lohm"
module("lohm.index", function(t, k)
setmetatable(t, {
Expand Down Expand Up @@ -40,7 +41,7 @@ function getDefault()
end


local query_meta = {
local query_prototype = {
union = function(self, set)
table.insert(self.queue, {command='sunionstore', key=set:getKey()})
return self
Expand All @@ -52,69 +53,75 @@ local query_meta = {
end,

exec = function(self)
self.redis:transaction({cas=true, watch=self.set:getKey()}, function(redis)
local temp_key, base_set_key = nil, self.set:getKey()
local res, err = self.redis:transaction({cas=true}, function(redis)
local queue = self.queue
for i, cmd in ipairs(queue) do
--[[for i, cmd in ipairs(queue) do
redis:watch(cmd.key)
end
redis:multi()
end]]
if #queue >= 1 then
local TempSet = self.temp_set_model
local temp = TempSet:new(nil, TempSet:reserveNextId(), false)
local temp_key = temp.getKey()
redis:expire(temp_key, 10) -- expire that set in 10 seconds flat.
local base_set_key = self.set:getKey()
redis:multi()
temp_key = temp:getKey()
self.set = temp
for i=1, #queue do
local cmd = queue[i]
redis[cmd.command](temp_key, cmd.key, base_set_key or temp_key)
assert(cmd.key)
redis[cmd.command](redis, temp_key, cmd.key, base_set_key or temp_key)
base_set_key = nil
end
redis:expire(temp_key, 30)
else
redis:multi()
end
redis:smembers(temp_key or base_set_key)
end)
--note that the temporary result set is not deleted explicitly, but it does expire.
local res = redis:smembers(temp_key)
for i,v in pairs(assert(redis:smembers(res_key))) do
res = res[#res]
for i,v in pairs(res) do
res[i]=self.model:new(nil, v, false)
end
return res, temp
return res
end
}

local query_meta = { __index = query_prototype }
function query(starting_set, model)
local self = setmetatable({
set = starting_set,
queue = {},
redis = model.redis,
model = model
model = model,
temp_set_model = lohm.new({type="set", key="~index_result:%s", expire=10}, model.redis),
}, query_meta)
return self
end

local index

function new(model, name)
if not indices[indexType] then
error(("Unknown index '%s'. Known indices: %s."):format(tostring(indexType), allIndices()))
end
assert(type(name)=='string', 'What do you want indexed? (no name parameter)')

local Index = lohm.new({ type='set', key=model:key(("%s:index.%s:%%s"):format(name or "NONAME", indexType))}, model.redis)
local Index = lohm.new({ type='set', key=model:key(("index.hash:%s:%%s"):format(name or "NONAME"))}, model.redis)

return setmetatable({
model = Index,
update = function(self, id, newval, oldval)
local id = assert(self:getId(), "id must be given")
assert(id, "id must be given")
assert(type(newval)~='table')
assert(type(oldval)~='table')
local redis = self.model.redis
if(oldval~=nil) then
self(oldval):remove(id):save()
redis:srem(self:getSetKey(oldval), id)
end
if(newval~=nil) then
self(newval):add(id):save()
redis:sadd(self:getSetKey(newval), id)
end
return self
end,
getSet = function(self, val)
return self.model:new(nil, hash(val), false)
end,
getSetKey = function(self, val)
return (self.model:key(hash(val)))
end,
}, {__call = function(self, ...)
return self:getSet(...)
end })
Expand Down
6 changes: 2 additions & 4 deletions lohm/model.lua
Expand Up @@ -175,8 +175,6 @@ end
function new(arg, redisconn)

local model, object = arg.model or {}, arg.object or {}
debug.print("ARG IS", arg)
print(debug.traceback())
assert(type(arg.key)=='string', "Redis " .. (arg.type or "") .. " object Must Have a key parameter (something like 'foo:%s').")
assert(redisconn, "Valid redis connection needed")
assert(redisconn:ping())
Expand All @@ -188,15 +186,15 @@ function new(arg, redisconn)
local idmatch = key:gsub("([%^%$%(%)%.%[%]%*%+%-%?])", "<0/0>%1") --note that we aren't filtering the % char. because it's used in sprintf.
idmatch = ("^" .. idmatch .. "$"):format("(.*)"):gsub("<0/0>", "%%")
model.id = function(self, key)
print(debug.traceback())
return key:find(idmatch)
end
model.key = function(self, id)
return key:format(id)
end
local newobject = Data[arg.type or "hash"](model, arg)
model.new = function(self, res, id)
return newobject(res or {}, id)
local obj, err = newobject(res or {}, id)
return obj, err
end
model.load = function(self, id)
return newobject(nil, id, true)
Expand Down
3 changes: 0 additions & 3 deletions lohm/set.lua
Expand Up @@ -103,7 +103,6 @@ function initialize(prototype, attributes)
prototype:addCallback('save', function(self, redis)

local saved = tcopy(savedset)
debug.print("SAVEY", saved, savedset)
local key = self:getKey()
local member
for i,v in pairs(self) do
Expand All @@ -127,10 +126,8 @@ function initialize(prototype, attributes)

--leftovers to be removed
for i,v in pairs(saved) do
print(i,v)
delta.rem[v]=true
end
debug.print(delta)
for v, _ in pairs(delta.rem) do
redis:srem(key, v)
end
Expand Down

0 comments on commit 9e7d914

Please sign in to comment.