Packages
mozart
0.8.4
1.0.1
1.0.0
0.9.8
0.9.7
0.9.6
0.9.5
0.9.4
0.9.3
0.9.2
0.9.1
0.9.0
0.8.9
0.8.8
0.8.7
0.8.6
0.8.5
0.8.4
0.8.3
0.8.2
0.8.1
0.8.0
0.7.8
0.7.7
0.7.6
0.7.5
0.7.4
0.7.3
0.7.2
0.7.1
0.7.0
0.6.8
0.6.7
0.6.6
0.6.5
0.6.4
0.6.3
0.6.2
0.6.1
0.6.0
0.5.8
0.5.7
0.5.6
0.5.5
0.5.4
0.5.3
0.5.2
0.5.1
0.5.0
0.4.5
0.4.4
0.4.3
0.4.2
0.4.1
0.4.0
0.3.7
0.3.6
0.3.5
0.3.4
0.3.3
0.3.2
0.3.1
0.3.0
0.2.11
0.2.10
0.2.9
0.2.8
0.2.7
0.2.6
0.2.5
0.2.4
0.2.3
0.2.2
0.2.1
0.2.0
0.1.11
0.1.10
0.1.9
0.1.8
0.1.7
0.1.6
0.1.5
0.1.4
0.1.3
0.1.2
0.1.1
0.1.0
Mozart is an Elixir based BPM platform. It provides a powerful and highly readable DSL for implementing executable business process models.
Current section
Files
Jump to
Current section
Files
lib/mozart/process_service.ex
defmodule Mozart.ProcessService do
@moduledoc """
This modeule provides a set of utility services.
"""
@doc false
use GenServer
alias Mozart.ProcessEngine, as: PE
require Logger
## Client API
@doc false
def start_link(_init_arg) do
GenServer.start_link(__MODULE__, nil, name: __MODULE__)
end
@doc false
def persist_process_state(pe_state) do
GenServer.cast(__MODULE__, {:persist_process_state, pe_state})
end
@doc false
def delete_process_state(pe_state) do
GenServer.cast(__MODULE__, {:delete_process_state, pe_state})
end
@doc false
def get_all_open_tasks() do
GenServer.call(__MODULE__, :get_all_open_tasks)
end
@doc false
def get_persisted_process_state(pe_uid) do
GenServer.call(__MODULE__, {:get_persisted_process_state, pe_uid})
end
@doc false
def get_persisted_processes() do
GenServer.call(__MODULE__, :get_persisted_processes)
end
@doc """
Get active process instances
"""
def get_active_processes() do
GenServer.call(__MODULE__, :get_active_processes)
end
@doc false
def get_cached_state(uid) do
GenServer.call(__MODULE__, {:get_cached_state, uid})
end
@doc false
def get_processes_for_business_key(business_key) do
GenServer.call(__MODULE__, {:get_processes_for_business_key, business_key})
end
@doc """
Returns the state of the completed process corresponding to the process engine's uid
"""
def get_completed_process(uid) do
GenServer.call(__MODULE__, {:get_completed_process, uid})
end
@doc """
Returns the data accumulated by the completed process
"""
def get_completed_process_data(uid) do
GenServer.call(__MODULE__, {:get_completed_process_data, uid})
end
@doc false
def get_process_pid_from_uid(uid) do
GenServer.call(__MODULE__, {:get_process_pid_from_uid, uid})
end
@doc """
Returns the user tasks that can be completed by users belonging to one of the input group.
"""
def get_user_tasks_for_group(group) do
GenServer.call(__MODULE__, {:get_user_tasks_for_group, group})
end
@doc false
def update_for_completed_process(process_state) do
GenServer.call(__MODULE__, {:update_for_completed_process, process_state})
end
@doc false
def get_user_task(uid) do
GenServer.call(__MODULE__, {:get_user_task, uid})
end
@doc false
def get_completed_processes() do
GenServer.call(__MODULE__, :get_completed_processes)
end
@doc false
def get_process_ppid(process_uid) do
GenServer.call(__MODULE__, {:get_process_ppid, process_uid})
end
@doc false
def get_user_tasks() do
GenServer.call(__MODULE__, :get_user_tasks)
end
@doc false
def register_process_instance(uid, pid, business_key) do
GenServer.cast(__MODULE__, {:register_process_instance, uid, pid, business_key})
end
@doc false
def process_completed_process_instance(process_state) do
GenServer.call(__MODULE__, {:process_completed_process_instance, process_state})
end
@doc false
def get_state() do
GenServer.call(__MODULE__, :get_state)
end
@doc """
Completes a user task.
"""
def complete_user_task(user_task_uid, data) do
GenServer.cast(__MODULE__, {:complete_user_task, user_task_uid, data})
end
@doc false
def assign_user_task(task_uid, user_id) do
GenServer.cast(__MODULE__, {:assign_user_task, task_uid, user_id})
end
@doc false
def insert_user_task(task) do
GenServer.cast(__MODULE__, {:insert_user_task, task})
end
@doc false
def clear_user_tasks() do
GenServer.cast(__MODULE__, :clear_user_tasks)
end
@doc false
def clear_state() do
GenServer.call(__MODULE__, :clear_state)
end
@doc false
def cache_pe_state(uid, pe_state) do
GenServer.call(__MODULE__, {:cache_pe_state, uid, pe_state})
end
@doc """
Loads a list of process model into the state of the
ProcessService.
"""
def load_process_models(models) do
GenServer.call(__MODULE__, {:load_process_models, models})
end
@doc false
def load_types(types) do
GenServer.call(__MODULE__, {:load_types, types})
end
@doc false
def get_type(type_name) do
GenServer.call(__MODULE__, {:get_type, type_name})
end
@doc """
Loads a BPM Application
"""
def load_bpm_application(bpm_application) do
GenServer.call(__MODULE__, {:load_bpm_application, bpm_application})
end
@doc """
Gets a BPM Application
"""
def get_bpm_application(app_name) do
GenServer.call(__MODULE__, {:get_bpm_application, app_name})
end
@doc """
Gets the names of all BPM applications
"""
def get_bpm_applications do
GenServer.call(__MODULE__, :get_bpm_applications)
end
@doc """
Retrieves a process model by name.
"""
def get_process_model(process) do
GenServer.call(__MODULE__, {:get_process_model, process})
end
@doc false
def get_process_models do
GenServer.call(__MODULE__, :get_process_models)
end
@doc """
Loads a single process model in the repository.
"""
def load_process_model(model) do
GenServer.call(__MODULE__, {:load_process_model, model})
end
@doc false
def clear_then_load_process_models(models) do
GenServer.call(__MODULE__, {:clear_then_load_process_models, models})
end
@doc false
def get_process_model_db() do
GenServer.call(__MODULE__, :get_process_model_db)
end
@doc false
def get_completed_process_db() do
GenServer.call(__MODULE__, :get_completed_process_db)
end
@doc false
def get_user_task_db() do
GenServer.call(__MODULE__, :get_user_task_db)
end
## Callbacks
@doc false
def init(_init_arg) do
initial_state = %{
active_process_groups: %{},
active_processes: %{},
restart_state_cache: %{}
}
Logger.info("Process service initialized")
{:ok, initial_state, {:continue, :initialize_databases}}
end
def handle_continue(:initialize_databases, state) do
env = Application.fetch_env(:mozart, :database_path)
path =
case env do
:error -> "database"
{:ok, value} -> value
end
{:ok, user_task_db} = CubDB.start_link(data_dir: path <> "/user_task_db")
{:ok, completed_process_db} = CubDB.start_link(data_dir: path <> "/completed_process_db")
{:ok, process_model_db} = CubDB.start_link(data_dir: path <> "/process_model_db")
{:ok, bpm_application_db} = CubDB.start_link(data_dir: path <> "/bpm_application_db")
{:ok, process_state_db} = CubDB.start_link(data_dir: path <> "/process_state_db")
{:ok, type_db} = CubDB.start_link(data_dir: path <> "/type_db")
database_config = %{
user_task_db: user_task_db,
completed_process_db: completed_process_db,
process_model_db: process_model_db,
bpm_application_db: bpm_application_db,
process_state_db: process_state_db,
type_db: type_db
}
state = Map.merge(state, database_config)
{:noreply, state}
end
def handle_call(:get_all_open_tasks, _from, state) do
processes = state.active_processes
states = Enum.map(processes, fn {_uid, pid} -> Mozart.ProcessEngine.get_state(pid) end)
open_tasks = Enum.map(states, fn s -> s.open_tasks end)
task_lists = Enum.map(open_tasks, fn map -> Map.values(map) end)
task_list = List.flatten(task_lists)
open_task_names = Enum.map(task_list, fn t -> t.name end)
{:reply, open_task_names, state}
end
def handle_call({:get_processes_for_business_key, business_key}, _from, state) do
process_group = Map.get(state.active_process_groups, business_key)
process_pids = Map.values(process_group)
process_states = Enum.map(process_pids, fn pid -> PE.get_state(pid) end)
{:reply, process_states, state}
end
def handle_call(:get_process_model_db, _from, state) do
{:reply, state.process_model_db, state}
end
def handle_call(:get_user_task_db, _from, state) do
{:reply, state.user_task_db, state}
end
def handle_call(:get_completed_process_db, _from, state) do
{:reply, state.completed_process_db, state}
end
@doc false
def handle_call(:clear_state, _from, state) do
CubDB.clear(state.user_task_db)
CubDB.clear(state.completed_process_db)
CubDB.clear(state.process_model_db)
CubDB.clear(state.bpm_application_db)
CubDB.clear(state.process_state_db)
CubDB.clear(state.type_db)
new_state = %{
active_processes: %{},
active_process_groups: %{},
restart_state_cache: %{},
user_task_db: state.user_task_db,
completed_process_db: state.completed_process_db,
process_model_db: state.process_model_db,
bpm_application_db: state.bpm_application_db,
process_state_db: state.process_state_db,
type_db: state.type_db
}
{:reply, new_state, new_state}
end
def handle_call(:get_active_processes, _from, state) do
{:reply, state.active_processes, state}
end
def handle_call(:get_state, _from, state) do
{:reply, state, state}
end
def handle_call(:get_completed_processes, _from, state) do
{:reply, get_completed_processes_local(state), state}
end
def handle_call({:get_process_pid_from_uid, uid}, _from, state) do
{:reply, Map.get(state.active_processes, uid), state}
end
def handle_call({:get_process_ppid, process_uid}, _from, state) do
{:reply, Map.get(state.active_processes, process_uid), state}
end
def handle_call({:get_completed_process, uid}, _from, state) do
{:reply, CubDB.get(state.completed_process_db, uid), state}
end
def handle_call({:get_completed_process_data, uid}, _from, state) do
completed_process = CubDB.get(state.completed_process_db, uid)
{:reply, completed_process.data, state}
end
def handle_call({:get_user_tasks_for_group, group}, _from, state) do
tasks = get_user_tasks_for_groups_local(group, state)
{:reply, tasks, state}
end
def handle_call(:get_user_tasks, _from, state) do
{:reply, get_user_tasks(state), state}
end
def handle_call({:get_user_task, uid}, _from, state) do
{:reply, get_user_task_by_id(state, uid), state}
end
def handle_call({:get_cached_state, uid}, _from, state) do
{pe_state, new_cache} = Map.pop(state.restart_state_cache, uid)
state = if pe_state, do: Map.put(state, :restart_state_cache, new_cache), else: state
{:reply, pe_state, state}
end
def handle_call({:cache_pe_state, uid, pe_state}, _from, state) do
state =
Map.put(state, :restart_state_cache, Map.put(state.restart_state_cache, uid, pe_state))
{:reply, pe_state, state}
end
def handle_call({:load_bpm_application, bpm_application}, _from, state) do
CubDB.put(state.bpm_application_db, bpm_application.process, bpm_application)
{:reply, :ok, state}
end
def handle_call({:get_bpm_application, app_name}, _from, state) do
app = CubDB.get(state.bpm_application_db, app_name)
{:reply, app, state}
end
def handle_call(:get_bpm_applications, _from, state) do
apps = CubDB.select(state.bpm_application_db) |> Enum.to_list()
{:reply, apps, state}
end
def handle_call({:load_process_models, models}, _from, state) do
Enum.each(models, fn m -> CubDB.put(state.process_model_db, m.name, m) end)
{:reply, state, state}
end
def handle_call({:load_types, types}, _from, state) do
Enum.each(types, fn t -> CubDB.put(state.type_db, t.param_name, t) end)
{:reply, state, state}
end
def handle_call({:get_type, type_name}, _from, state) do
{:reply, CubDB.get(state.type_db, type_name), state}
end
def handle_call({:get_process_model, name}, _from, state) do
{:reply, CubDB.get(state.process_model_db, name), state}
end
def handle_call(:get_process_models, _from, state) do
models =
CubDB.select(state.process_model_db)
|> Enum.to_list()
{:reply, models, state}
end
@doc false
def handle_call({:load_process_model, process_model}, _from, state) do
{:reply, CubDB.put(state.process_model_db, process_model.name, process_model), state}
end
@doc false
def handle_call({:clear_then_load_process_models, models}, _from, state) do
CubDB.clear(state.process_model_db)
Enum.each(models, fn m -> CubDB.put(state.process_model_db, m.name, m) end)
{:reply, models, Map.put(state, :process_models, models)}
end
def handle_call({:update_for_completed_process, pe_process}, _from, state) do
state = Map.put(state, :active_processes, Map.delete(state.active_processes, pe_process.uid))
state =
Map.put(
state,
:active_process_groups,
Map.delete(state.active_process_groups, pe_process.business_key)
)
CubDB.put(state.completed_process_db, pe_process.uid, pe_process)
{:reply, pe_process, state}
end
def handle_call({:get_persisted_process_state, pe_uid}, _from, state) do
{:reply, CubDB.get(state.process_state_db, pe_uid), state}
end
def handle_call(:get_persisted_processes, _from, state) do
persisted_processes = CubDB.select(state.process_state_db) |> Enum.to_list()
{:reply, persisted_processes, state}
end
def handle_cast({:persist_process_state, pe_state}, state) do
CubDB.put(state.process_state_db, pe_state.uid, pe_state)
{:noreply, state}
end
def handle_cast({:delete_process_state, pe_state}, state) do
CubDB.delete(state.process_state_db, pe_state.uid)
{:noreply, state}
end
def handle_cast({:register_process_instance, uid, pid, business_key}, state) do
active_processes = Map.put(state.active_processes, uid, pid)
state = Map.put(state, :active_processes, active_processes)
state = get_active_process_groups(uid, pid, business_key, state)
{:noreply, state}
end
def handle_cast({:complete_user_task, user_task_uid, data}, state) do
user_task = get_user_task_by_id(state, user_task_uid)
ppid = Map.get(state.active_processes, user_task.process_uid)
CubDB.delete(state.user_task_db, user_task_uid)
PE.complete_user_task_and_go(ppid, user_task_uid, data)
{:noreply, state}
end
def handle_cast({:assign_user_task, task_uid, user_id}, state) do
user_task = get_user_task_by_id(state, task_uid) |> Map.put(:assigned_user, user_id)
ppid = Map.get(state.active_processes, user_task.process_uid)
insert_user_task(state, user_task)
PE.assign_user_task(ppid, task_uid, user_id)
{:noreply, state}
end
def handle_cast(:clear_user_tasks, state) do
CubDB.clear(state.user_task_db)
{:noreply, state}
end
def handle_cast({:insert_user_task, task}, state) do
insert_user_task(state, task)
{:noreply, state}
end
@doc false
def get_active_process_groups(uid, pid, business_key, state) do
processes = Map.get(state.active_process_groups, business_key) || %{}
processes = Map.put(processes, uid, pid)
active_process_groups = Map.put(state.active_process_groups, business_key, processes)
Map.put(state, :active_process_groups, active_process_groups)
end
defp insert_user_task(state, task) do
CubDB.put(state.user_task_db, task.uid, task)
end
defp get_user_tasks_for_groups_local(group, state) do
CubDB.select(state.user_task_db)
|> Stream.map(fn {_uid, t} -> t end)
|> Stream.filter(&(&1.assigned_group == group))
|> Enum.to_list()
end
@doc false
def get_completed_processes_local(state) do
CubDB.select(state.completed_process_db)
|> Stream.map(fn {_k, v} -> v end)
|> Enum.to_list()
end
defp get_user_task_by_id(state, uid) do
CubDB.get(state.user_task_db, uid)
end
defp get_user_tasks(state) do
CubDB.select(state.user_task_db) |> Stream.map(fn {_k, v} -> v end) |> Enum.to_list()
end
end