]> git.r.bdr.sh - rbdr/grafn/blame - README.md
Ignore tap-snapshots from quality checks
[rbdr/grafn] / README.md
CommitLineData
e4c7bafd
RBR
1# Grafn
2
3Graph + Fn: Execute functions as a graph.
4
5## What it's for?
6
7Grafn lets you execute sequences of async functions by defining them as
8vertices in a graph.
9
10This allows you to easily define and manipulate complex dependencies in
11asynchronous code.
12
13## How can I use it?
14
15In order to use it you must first create a graph.
16
17```javascript
18const Grafn = require('grafn');
19
20const graph = new Grafn();
21```
22
23Next you need to add some vertexes.
24
25```javascript
26graph.vertex({
27 name: 'root',
28 action() {
29
30 return 5;
31 }
32});
33```
34
35This is a vertex without dependencies, it means it can be executed without
36waiting for anything else. The return value of this function will be stored
37so it can be used by its dependents.
38
39You can add dependencies by listing the names as an array in the vertex definition.
40
41```javascript
42graph.vertex({
43 name: 'addition',
44 dependencies: ['root'],
45 action(state) {
46
47 return state.root + state.root;
48 }
49});
50```
51
52Notice how the result of the `root` vertex is available in this action.
53
54Vertexes will be executed as soon as all of their dependencies are met. For
55example, consider the following graph
56
57```javascript
58const Grafn = require('grafn');
59
60const graph = new Grafn();
61
62graph.vertex({
63 name: 'root',
64 action() {
65
66 return 5;
67 }
68});
69
70graph.vertex({
71 name: 'addition',
72 dependencies: ['root'],
73 action(state) {
74
75 return state.root + state.root;
76 }
77});
78
79graph.vertex({
80 name: 'subtraction',
81 dependencies: ['root'],
82 action(state) {
83
84 return state.root - state.root;
85 }
86});
87
88graph.vertex({
89 name: 'multiplication',
90 dependencies: ['root'],
91 action(state) {
92
93 return state.root * state.root;
94 }
95});
96
97graph.vertex({
98 name: 'division',
99 dependencies: ['root'],
100 action(state) {
101
102 return state.root / state.root;
103 }
104});
105
106graph.vertex({
107 name: 'tally',
108 dependencies: ['addition', 'subtraction', 'multiplication', 'division'],
109 action(state) {
110
111 console.log('+', state.addition);
112 console.log('-', state.subtraction);
113 console.log('*', state.multiplication);
114 console.log('/', state.division);
115 }
116});
117```
118
119The `addition`, `subtraction`, `multiplication`, and `division` vertices will
120all run as soon as `roott` is executed. However, the final `tally` vertex won't
121run until all other operations are complete.
122
123You can visualize the graph by using the `graph.toString()` method. This
124will output a graphviz digraph:
125
126```graphviz
127digraph {
128 root
129 addition
130 root -> addition
131 subtraction
132 root -> subtraction
133 multiplication
134 root -> multiplication
135 division
136 root -> division
137 tally
138 addition -> tally
139 subtraction -> tally
140 multiplication -> tally
141 division -> tally
142}
143```
144
145![execution graph, before execution][graph-pre-exec]
146
147You can easily change the shape of the graph by changing the dependencies array.
148
149In order to start execution of the graph you should select which node to start
150from.
151
152```
153graph.run('root');
154```
155
156After an execution, you can use `graph.toString()` to check the result of an
157execution. It will highlight which nodes were executed successfully (green), and
158which nodes threw an error (red).
159
160![execution graph, after execution][graph-post-exec]
161
162## Acknowledgements
163
164This project implements the same ideas behind [fluorine][fluorine], a similar
165graph based library. Grafn wouldn't exist without it.
166
167[fluorine]: https://github.com/freshout-dev/fluorine
168[graph-pre-exec]: doc/images/graph-pre-exec.svg
169[graph-post-exec]: doc/images/graph-post-exec.svg