Skip to content

Instantly share code, notes, and snippets.

@vikks
Forked from cyx/create.lua
Created April 24, 2012 14:18
Show Gist options
  • Save vikks/2480047 to your computer and use it in GitHub Desktop.
Save vikks/2480047 to your computer and use it in GitHub Desktop.
local namespace = KEYS[1]
local attributes = ARGV
local model = {
id = namespace .. ":id",
all = namespace .. ":all",
uniques = namespace .. ":uniques",
indices = namespace .. ":indices",
key = namespace .. ":%s"
}
local meta = {
uniques = redis.call("SMEMBERS", model.uniques),
indices = redis.call("SMEMBERS", model.indices)
}
local function dict(list)
local ret = {}
for i = 1, #list, 2 do
ret[list[i]] = list[i + 1]
end
return ret
end
local function list(table)
local atts = {}
for k, v in pairs(table) do
atts[#atts + 1] = k
atts[#atts + 1] = v
end
return atts
end
local function non_unique(table)
for _, att in ipairs(meta.uniques) do
local key = model.uniques .. ":" .. att
local existing = redis.call("HGET", key, table[att])
if existing then return att end
end
end
local function save_uniques(table, id)
for _, att in ipairs(meta.uniques) do
local key = model.uniques .. ":" .. att
redis.call("HSET", key, table[att], id)
end
end
local function save_indices(table, id)
for _, att in ipairs(meta.indices) do
local key = model.indices .. ":" .. att .. ":" .. table[att]
redis.call("SADD", key, id)
end
end
local this = dict(attributes)
local not_unique = non_unique(this)
if not_unique then
return { 500, { not_unique, "not_unique" }}
end
local id = redis.call("INCR", model.id)
local key = model.key:format(id)
save_uniques(this, id)
save_indices(this, id)
redis.call("DEL", key)
redis.call("HMSET", key, unpack(list(this)))
# encoding: UTF-8
require File.expand_path("./helper", File.dirname(__FILE__))
$VERBOSE = false
def redis
Ohm.redis
end
setup do
redis.sadd("User:uniques", "email")
redis.sadd("User:indices", "fname")
redis.sadd("User:indices", "lname")
redis.hset("User:uniques:email", "foo@bar.com", 1)
Ohm::Lua.new("./test/lua", redis)
end
test "returns the unique constraint error" do |lua|
res = lua.run("create",
keys: ["User"],
argv: ["email", "foo@bar.com"])
assert_equal [500, ["email", "not_unique"]], res
end
test "returns the unique constraint error" do |lua|
res = lua.run("create",
keys: ["User"],
argv: ["email", "bar@baz.com"])
assert_equal "1", redis.hget("User:uniques:email", "bar@baz.com")
end
test "saves the attributes" do |lua|
res = lua.run("create",
keys: ["User"],
argv: ["email", "bar@baz.com", "fname", "John", "lname", "Doe"])
assert_equal "bar@baz.com", redis.hget("User:1", "email")
assert_equal "John", redis.hget("User:1", "fname")
assert_equal "Doe", redis.hget("User:1", "lname")
end
test "indexes fname / lname" do |lua|
res = lua.run("create",
keys: ["User"],
argv: ["email", "bar@baz.com", "fname", "John", "lname", "Doe"])
assert redis.sismember("User:indices:fname:John", 1)
assert redis.sismember("User:indices:lname:Doe", 1)
end
__END__
require "sequel"
DB = Sequel.connect("postgres://cyx@localhost/postgres")
DB[:users].truncate
t = Benchmark.measure do
1000.times do |i|
DB[:users].insert(email: "foo#{i}@bar.com", fname: "John#{i}", lname: "Doe#{i}")
end
end
puts t
puts Ohm.redis.keys("User:*").inspect
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment