Files
modpol/modpol_core/orgs/process.lua
Nathan Schneider 2028f1ee85 Refactored policy structure
Previously, all modules in an org were fully copied into that
org. Now, the only copy of the modules is at modpol.modules, and orgs
have a policy table at [org].policies, which overrides the config
table in any given module.
2022-02-09 22:14:26 -07:00

176 lines
5.5 KiB
Lua

--- Process functions for orgs
-- @module modpol.orgs.process
--- Call modules
-- @function modpol.orgs.call_module
-- @param module_slug Same as module name
-- @param intiator Initiator for module
-- @param config Config for module
-- @param result
function modpol.orgs:call_module(module_slug, initiator, config, result, parent_id)
if not modpol.modules[module_slug] then
modpol.ocutil.log('Error in ' .. self.name .. ':call_module -> module "' .. module_slug .. '" not found')
return
end
local index = #self.processes + 1
local module = modpol.modules[module_slug]
-- first applies any relevant org policies
-- then overrides with the config values given on input
local new_config = {}
if modpol.util.num_pairs(module.config) > 0 then
for k, v in pairs(module.config) do
new_config[k] = v
-- overrides with org policies
if self.policies[module_slug]
and self.policies[module_slug][k] then
new_config[k] = self.policies[module_slug][k]
end
-- overrides with input settings
if config and config[k] then
new_config[k] = config[k]
end
end
end
-- setting default params
local new_process = {
metatable = {__index = module},
initiator = initiator,
org = self,
id = index,
parent_id = parent_id,
children = {},
config = modpol.util.copy_table(new_config),
data = modpol.util.copy_table(module.data),
slug = module_slug
}
-- call module wrapper for modules, passes its id to child process when called
function new_process:call_module(module_slug, initiator, config, result)
local child_id = self.org:call_module(module_slug, initiator, config, result, self.id)
table.insert(self.children, child_id)
end
setmetatable(new_process, new_process.metatable)
self.processes[index] = new_process
self.processes[index]:initiate(result)
local msg = "Initiating "..module_slug..
" process id "..index.." in org "..self.name
return index
end
--- Get the root process of the given id
-- @function modpol.orgs.get_root_process
-- @param id
-- @return root process
function modpol.orgs:get_root_process(id)
local process = self.processes[id]
while (process.parent_id) do
process = self.processes[process.parent_id]
end
return process
end
--- Delete the process given id
-- @function modpol.orgs.delete_process
-- @param id
function modpol.orgs:delete_process(id)
local process = self.processes[id]
if process and process ~= "deleted" then
-- recursively deletes any children
if #process.children > 0 then
for i, child_id in pairs(process.children) do
self:delete_process(child_id)
end
end
local msg = "Deleting " .. self.processes[id].slug .. " process id "..id.." in org "..self.name
modpol.ocutil.log(msg)
self:record(msg, self.processes[id].slug)
self:wipe_pending_actions(id)
-- sets process to 'deleted' in process table
self.processes[id] = 'deleted'
end
end
--- Delete process tree by id
-- @function modpol.orgs:delete_process_tree
-- @param id Id of process tree
function modpol.orgs:delete_process_tree(id)
self:delete_process(self:get_root_process(id).id)
end
--- Add a new pending action
-- @function modpol.orgs:add_pending_action
-- @param process_id Process id
-- @param user User adding the action
-- @param callback
function modpol.orgs:add_pending_action(process_id, user, callback)
self.pending[user] = self.pending[user] or {}
self.pending[user][process_id] = callback
modpol.interactions.message(
user, "New pending action in org "..self.name)
end
--- Remove a pending action
-- @function modpol.orgs:remove_pending_action
-- @param process_id Process id to be removed
-- @param user
function modpol.orgs:remove_pending_action(process_id, user)
if self.pending[user] then
self.pending[user][process_id] = nil
end
end
--- Wipe all pending actions for process
-- @function modpol.orgs:wipe_pending_actions
-- @param process_id
function modpol.orgs:wipe_pending_actions(process_id)
for user in pairs(self.pending) do
self.pending[user][process_id] = nil
end
end
--- Check if there are pending actions for user
-- @function modpol.orgs:has_pending_actions
-- @param user User
-- @return True if there are pending actions for a user, false if not
function modpol.orgs:has_pending_actions(user)
-- next() will return the next pair in a table
-- if next() returns nil, the table is empty
if not self.pending[user] then
return false
else
if not next(self.pending[user]) then
return false
else
return true
end
end
end
--- Interact a user with given process
-- @function modpol.orgs:interact
-- @param process_id
-- @param user
function modpol.orgs:interact(process_id, user)
local process = self.processes[process_id]
if self.pending[user] then
local callback = self.pending[user][process_id]
if callback and process ~= "deleted" then
-- get data in case callback ends process
local slug = self.processes[process_id].slug
-- run callback
process[callback](process, user)
-- record org data
local msg = "Updating "..slug..
" process id "..process_id.." in org "..self.name
self:record(msg, slug)
end
end
end