diff options
author | Kaarle Ritvanen <kaarle.ritvanen@datakunkku.fi> | 2014-01-03 01:00:01 +0200 |
---|---|---|
committer | Kaarle Ritvanen <kaarle.ritvanen@datakunkku.fi> | 2014-01-03 03:45:39 +0200 |
commit | 849ed1cb3792af468999a312449faf3e599e67c1 (patch) | |
tree | 04456d38b803e29e44302b7f44e0525e1395cd77 | |
parent | 15ea19da7079cb4c2019b53dae62d5cf6562ce63 (diff) | |
download | acf2-849ed1cb3792af468999a312449faf3e599e67c1.tar.bz2 acf2-849ed1cb3792af468999a312449faf3e599e67c1.tar.xz |
deferred final commit for configurable backend addresses
-rw-r--r-- | acf2/init.lua | 5 | ||||
-rw-r--r-- | acf2/model/init.lua | 2 | ||||
-rw-r--r-- | acf2/persistence/defer.lua | 47 | ||||
-rw-r--r-- | acf2/transaction/base.lua | 6 | ||||
-rw-r--r-- | acf2/transaction/init.lua | 13 | ||||
-rw-r--r-- | server.lua | 22 |
6 files changed, 86 insertions, 9 deletions
diff --git a/acf2/init.lua b/acf2/init.lua index b5bd1d1..95ce91e 100644 --- a/acf2/init.lua +++ b/acf2/init.lua @@ -1,5 +1,5 @@ --[[ -Copyright (c) 2012-2013 Kaarle Ritvanen +Copyright (c) 2012-2014 Kaarle Ritvanen See LICENSE file for license details --]] @@ -19,4 +19,7 @@ local txn = M.start_txn() for _, rv in pairs(mods) do if type(rv) == 'function' then rv(txn) end end txn:commit() +local def_store = require('acf2.persistence.defer') +function M.commit() def_store:commit() end + return M diff --git a/acf2/model/init.lua b/acf2/model/init.lua index 51d39c8..9383ad9 100644 --- a/acf2/model/init.lua +++ b/acf2/model/init.lua @@ -57,6 +57,7 @@ local super = object.super M.path = require('acf2.path') local store = require('acf2.persistence') +local def_store = require('acf2.persistence.defer') local util = require('acf2.util') local update = util.update @@ -265,6 +266,7 @@ end function M.trigger(phase, addr, func) store:trigger(phase, addr, func) end +function M.defer(addr) def_store:defer(addr) end return M diff --git a/acf2/persistence/defer.lua b/acf2/persistence/defer.lua new file mode 100644 index 0000000..e93f49e --- /dev/null +++ b/acf2/persistence/defer.lua @@ -0,0 +1,47 @@ +--[[ +Copyright (c) 2012-2014 Kaarle Ritvanen +See LICENSE file for license details +--]] + +local object = require('acf2.object') +local super = object.super + +local pth = require('acf2.path') + + +local DeferringCommitter = object.class( + require('acf2.transaction.base').Transaction +) + +function DeferringCommitter:init(backend) + super(self, DeferringCommitter):init(backend) + self.defer_paths = {} + self.committed = true +end + +function DeferringCommitter:defer(path) self.defer_paths[path] = true end + +function DeferringCommitter:_set_multiple(mods) + super(self, DeferringCommitter):_set_multiple(mods) + + if not self.committed then return end + self.committed = false + + for _, mod in ipairs(mods) do + local path, value = unpack(mod) + while path > '/' do + if self.defer_paths[path] then return end + path = pth.parent(path) + end + end + + self:commit() +end + +function DeferringCommitter:commit() + super(self, DeferringCommitter):commit() + self.committed = true +end + + +return DeferringCommitter(require('acf2.persistence')) diff --git a/acf2/transaction/base.lua b/acf2/transaction/base.lua index 142b0a5..8ca21f3 100644 --- a/acf2/transaction/base.lua +++ b/acf2/transaction/base.lua @@ -90,9 +90,11 @@ M.Transaction = class(M.TransactionBackend) function M.Transaction:init(backend) object.super(self, M.Transaction):init() - self.backend = backend + self:reset() +end +function M.Transaction:reset() self.started = gen_number() self.access_time = {} @@ -215,6 +217,8 @@ function M.Transaction:commit() for path, _ in pairs(self.added) do insert_add(path) end self.backend:comp_and_setm(self.access_time, mods) + + self:reset() end diff --git a/acf2/transaction/init.lua b/acf2/transaction/init.lua index 482c00e..943e337 100644 --- a/acf2/transaction/init.lua +++ b/acf2/transaction/init.lua @@ -113,7 +113,14 @@ end local store = require('acf2.persistence') - -return function(txn, defer_validation) - return ModelTransaction(txn or store, not (txn and defer_validation)) +local def_store = require('acf2.persistence.defer') + +return function(options) + options = options or {} + return ModelTransaction( + options.parent or ( + options.allow_commit_defer and def_store or store + ), + not (txn and options.defer_validation) + ) end @@ -1,5 +1,5 @@ --[[ -Copyright (c) 2012-2013 Kaarle Ritvanen +Copyright (c) 2012-2014 Kaarle Ritvanen See LICENSE file for license details --]] @@ -8,6 +8,7 @@ local mnode = acf.model.node local isinstance = acf.object.isinstance local json = require('cjson') +local posix = require('posix') local stringy = require('stringy') @@ -37,7 +38,11 @@ return function(env) else res = '' end return code, headers, coroutine.wrap( - function() coroutine.yield(res) end + function() + coroutine.yield(res) + posix.close(uwsgi.connection_fd()) + acf.commit() + end ) end @@ -77,7 +82,16 @@ return function(env) return wrap(400, nil, 'Invalid transaction ID') end end - local txn = acf.start_txn(parent_txn, true) + + local function new_txn(defer_validation) + return acf.start_txn{ + allow_commit_defer=true, + defer_validation=defer_validation, + parent=parent_txn + } + end + + local txn = new_txn(true) local function fetch_user(name) user = name and txn:fetch('/auth/users')[name] @@ -247,7 +261,7 @@ return function(env) session.last_txn_id = session.last_txn_id + 1 local txn_id = session.last_txn_id - session.txns[txn_id] = acf.start_txn(parent_txn) + session.txns[txn_id] = new_txn() return 204, {['X-ACF-Transaction-ID']=txn_id} end |