Packages
mozart
0.3.6
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
86 Versions
Jump to
Current section
86 Versions
Compare versions
6
files changed
+92
additions
-9
deletions
| @@ -1,6 +1,6 @@ | |
| 1 1 | {<<"links">>,[{<<"GitHub">>,<<"https://github.com/CharlesIrvineKC/mozart">>}]}. |
| 2 2 | {<<"name">>,<<"mozart">>}. |
| 3 | - {<<"version">>,<<"0.3.5">>}. |
| 3 | + {<<"version">>,<<"0.3.6">>}. |
| 4 4 | {<<"description">>, |
| 5 5 | <<"Mozart is a BPM platform written in Elixir. It is currently in active development,\nbut it has sufficient functionality for the development of BPM POCs.">>}. |
| 6 6 | {<<"elixir">>,<<"~> 1.16">>}. |
| @@ -61,5 +61,6 @@ | |
| 61 61 | <<"lib/mozart/data/process_model.ex">>, |
| 62 62 | <<"lib/mozart/data/process_state.ex">>,<<"lib/mozart/event">>, |
| 63 63 | <<"lib/mozart/event/task_exit.ex">>,<<"lib/mozart/user_service.ex">>, |
| 64 | - <<".formatter.exs">>,<<"mix.exs">>,<<"README.md">>,<<"LICENSE-2.0">>]}. |
| 64 | + <<"priv">>,<<".formatter.exs">>,<<"mix.exs">>,<<"README.md">>, |
| 65 | + <<"LICENSE-2.0">>]}. |
| 65 66 | {<<"build_tools">>,[<<"mix">>]}. |
| @@ -23,6 +23,7 @@ defmodule Mozart.BpmProcess do | |
| 23 23 | alias Mozart.Task.Timer |
| 24 24 | alias Mozart.Task.Prototype |
| 25 25 | alias Mozart.Task.Repeat |
| 26 | + alias Mozart.Event.TaskExit |
| 26 27 | alias Mozart.Data.ProcessModel |
| 27 28 | |
| 28 29 | defmacro __using__(_opts) do |
| @@ -34,6 +35,9 @@ defmodule Mozart.BpmProcess do | |
| 34 35 | @capture_subtasks false |
| 35 36 | @subtasks [] |
| 36 37 | @subtask_sets [] |
| 38 | + @events %{} |
| 39 | + @event_tasks [] |
| 40 | + @event_task_process_map %{} |
| 37 41 | @before_compile Mozart.BpmProcess |
| 38 42 | end |
| 39 43 | end |
| @@ -67,6 +71,41 @@ defmodule Mozart.BpmProcess do | |
| 67 71 | end |
| 68 72 | end |
| 69 73 | |
| 74 | + @doc """ |
| 75 | + Used to implement a business process event. Arguments are: |
| 76 | + * the name of the event |
| 77 | + * **process**: the name of the process that the event will act upon |
| 78 | + * **exit_task**: the name of the task to be exited |
| 79 | + * **selector**: a function that matches on the target event |
| 80 | + * **do**: one or more tasks to be executed when the target task is exited. |
| 81 | + ``` |
| 82 | + defevent "exit loan decision 1", |
| 83 | + process: "exit a user task 1", |
| 84 | + exit_task: "user task 1", |
| 85 | + selector: &BpmAppWithEvent.event_selector/1 do |
| 86 | + prototype_task("event 1 prototype task 1") |
| 87 | + prototype_task("event 1 prototype task 2") |
| 88 | + end |
| 89 | + ``` |
| 90 | + """ |
| 91 | + defmacro defevent(name, opts, do: tasks) do |
| 92 | + quote do |
| 93 | + [process: process, exit_task: exit_task, selector: selector] = unquote(opts) |
| 94 | + event = %TaskExit{name: unquote(name), exit_task: exit_task, selector: selector} |
| 95 | + @capture_subtasks true |
| 96 | + unquote(tasks) |
| 97 | + @subtasks set_next_tasks(@subtasks) |
| 98 | + first = hd(@subtasks) |
| 99 | + event = Map.put(event, :next, Map.get(hd(@subtasks), :name)) |
| 100 | + @event_task_process_map Map.put(@event_task_process_map, process, @subtasks) |
| 101 | + @events Map.put(@events, process, event) |
| 102 | + @tasks [] |
| 103 | + @subtasks [] |
| 104 | + @subtask_sets [] |
| 105 | + @capture_subtasks false |
| 106 | + end |
| 107 | + end |
| 108 | + |
| 70 109 | @doc false |
| 71 110 | def check_for_duplicates(type, tasks) do |
| 72 111 | task_names = Enum.map(tasks, fn t -> t.name end) |
| @@ -376,7 +415,7 @@ defmodule Mozart.BpmProcess do | |
| 376 415 | """ |
| 377 416 | defmacro receive_task(name, selector: function) do |
| 378 417 | quote do |
| 379 | - task = %Receive{name: unquote(name), message_selector: unquote(function)} |
| 418 | + task = %Receive{name: unquote(name), selector: unquote(function)} |
| 380 419 | |
| 381 420 | insert_new_task(task) |
| 382 421 | end |
| @@ -411,11 +450,53 @@ defmodule Mozart.BpmProcess do | |
| 411 450 | end |
| 412 451 | end |
| 413 452 | |
| 453 | + @doc false |
| 454 | + def merge_event_tasks_to_process(event_task_process_map, processes) do |
| 455 | + process_name_task_list = Map.to_list(event_task_process_map) |
| 456 | + merge_recursive(process_name_task_list, processes) |
| 457 | + end |
| 458 | + |
| 459 | + @doc false |
| 460 | + def merge_recursive([], processes), do: processes |
| 461 | + def merge_recursive([{process_name, tasks} | rest], processes) do |
| 462 | + merge_recursive(rest, |
| 463 | + Enum.map(processes, |
| 464 | + fn p -> |
| 465 | + if process_name == p.name do |
| 466 | + tasks = p.tasks ++ tasks |
| 467 | + Map.put(p, :tasks, tasks) |
| 468 | + else |
| 469 | + p |
| 470 | + end |
| 471 | + end |
| 472 | + ) |
| 473 | + ) |
| 474 | + end |
| 475 | + |
| 476 | + @doc false |
| 477 | + def assign_events_to_processes([], processes), do: processes |
| 478 | + def assign_events_to_processes([{pname, event} | rest], processes) do |
| 479 | + assign_events_to_processes(rest, Enum.map(processes, fn p -> |
| 480 | + if pname == p.name do |
| 481 | + events = [event | p.events] |
| 482 | + Map.put(p, :events, events) |
| 483 | + else |
| 484 | + p |
| 485 | + end |
| 486 | + end)) |
| 487 | + end |
| 488 | + |
| 414 489 | defmacro __before_compile__(_env) do |
| 415 490 | quote do |
| 491 | + if @event_task_process_map != %{} do |
| 492 | + @processes merge_event_tasks_to_process(@event_task_process_map, @processes) |
| 493 | + @processes assign_events_to_processes(Map.to_list(@events), @processes) |
| 494 | + end |
| 416 495 | def get_processes, do: Enum.reverse(@processes) |
| 417 496 | def get_process(name), do: Enum.find(@processes, fn p -> p.name == name end) |
| 418 497 | |
| 498 | + def get_events, do: Map.to_list(@events) |
| 499 | + |
| 419 500 | def load_processes do |
| 420 501 | process_names = Enum.map(@processes, fn p -> p.name end) |
| 421 502 | end |
| @@ -3,7 +3,7 @@ defmodule Mozart.Event.TaskExit do | |
| 3 3 | defstruct [ |
| 4 4 | :name, |
| 5 5 | :function, |
| 6 | - :message_selector, |
| 6 | + :selector, |
| 7 7 | :exit_task, |
| 8 8 | :next, |
| 9 9 | type: :task_exit |
| @@ -277,7 +277,7 @@ defmodule Mozart.ProcessEngine do | |
| 277 277 | |
| 278 278 | def handle_info({:event, payload}, state) do |
| 279 279 | model = PS.get_process_model(state.model_name) |
| 280 | - event = Enum.find(model.events, fn e -> e.message_selector.(payload) end) |
| 280 | + event = Enum.find(model.events, fn e -> e.selector.(payload) end) |
| 281 281 | state = if event, do: exit_task(event, state), else: state |
| 282 282 | {:noreply, state} |
| 283 283 | end |
| @@ -288,7 +288,7 @@ defmodule Mozart.ProcessEngine do | |
| 288 288 | task = Map.put(task, :complete, :exit_on_task_event) |
| 289 289 | |
| 290 290 | if task.type == :subprocess do |
| 291 | - complete_on_task_exit_event(task.sub_process_pid) |
| 291 | + complete_on_task_exit_event(task.subprocess_pid) |
| 292 292 | end |
| 293 293 | |
| 294 294 | # Todo: Code exit repeat task |
| @@ -311,7 +311,7 @@ defmodule Mozart.ProcessEngine do | |
| 311 311 | ## callback utilities |
| 312 312 | |
| 313 313 | defp update_receive_event_task(s_task, payload) do |
| 314 | - select_result = s_task.message_selector.(payload) |
| 314 | + select_result = s_task.selector.(payload) |
| 315 315 | |
| 316 316 | if select_result do |
| 317 317 | Map.put(s_task, :data, select_result) |
| @@ -397,6 +397,7 @@ defmodule Mozart.ProcessEngine do | |
| 397 397 | start_process(new_task.model, data, state.process_key, self()) |
| 398 398 | |
| 399 399 | execute(process_pid) |
| 400 | + state |
| 400 401 | end |
| 401 402 | |
| 402 403 | defp do_new_task_side_effects(_, _, state), do: state |
| @@ -5,7 +5,7 @@ defmodule Mozart.Task.Receive do | |
| 5 5 | :function, |
| 6 6 | :next, |
| 7 7 | :uid, |
| 8 | - :message_selector, |
| 8 | + :selector, |
| 9 9 | :start_time, |
| 10 10 | :finish_time, |
| 11 11 | :duration, |
Loading more files…