Page not found
63 | 64 |Sorry, but the page you were trying to get to, does not exist. You 65 | may want to try searching this site using the sidebar or using our 66 | API Reference page to find what 67 | you were looking for.
68 | 69 | 81 |├── .gitignore ├── README.md ├── config └── config.exs ├── doc ├── 404.html ├── ElixirFBP.Behaviour.html ├── ElixirFBP.Component.html ├── ElixirFBP.ComponentLoader.html ├── ElixirFBP.Graph.html ├── ElixirFBP.InitialInformationPacket.html ├── ElixirFBP.Network.html ├── ElixirFBP.Subscription.html ├── ElixirFBP.html ├── dist │ ├── app.css │ ├── app.js │ └── sidebar_items.js ├── extra-api-reference.html ├── fonts │ ├── icomoon.eot │ ├── icomoon.svg │ ├── icomoon.ttf │ └── icomoon.woff └── index.html ├── elixirFBP-0.0.1.tar ├── lib ├── elixirFBP.ex └── elixirFBP │ ├── behaviour.ex │ ├── component.ex │ ├── component_loader.ex │ ├── graph.ex │ ├── initial_information_packet.ex │ ├── network.ex │ └── subscription.ex ├── mix.exs ├── mix.lock ├── test ├── ElixirFBP_network_test.exs ├── elixirFBP_component_test.exs ├── elixirFBP_graph_test.exs └── test_helper.exs └── ttb_last_config /.gitignore: -------------------------------------------------------------------------------- 1 | /_build 2 | /deps 3 | erl_crash.dump 4 | *.ez 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ElixirFBP 2 | ========= 3 | 4 | This repository will contain an implementation of Flow-based Programming in the 5 | [Elixir language](http://elixir-lang.org). For more on FBP, see [Wikipedia](http://en.wikipedia.org/wiki/Flow-based_programming), 6 | [J. Paul Morrison](http://www.jpaulmorrison.com/fbp/), and [NoFlo](http://noflojs.org) 7 | 8 | This implementation is discussed [here](http://www.elixirfbp.org). 9 | 10 | # Description 11 | This Elixir implementation of an FBP system is influenced by the FBP Protocol as described at the NoFlo [website](http://noflojs.org/documentation/protocol/). These modules, however, can be used without regard to any particular runtime by using the Network and Graph modules directly. 12 | 13 | Note that an earlier release of this repository contained a runtime implementation 14 | that communicated, via websockets, with a noflo-ui client. The client could be running locally or remotely, using the on-line version at 15 | [app.flowhub.io](http:/app.flowhub.io). This code was refactored out and will appear in another repository. 16 | 17 | # Architecture 18 | ElixirFBP is made up of the following Elixir modules: 19 | * ElixirFBP.Network 20 | * ElixirFBP.Graph 21 | * ElixirFBP.Subscription 22 | 23 | The first two modules are implemented as Elixir [GenServers](http://elixir-lang.org/docs/stable/elixir/GenServer.html) 24 | 25 | ElixirFBP.Network 26 | keeps track of the FBP network that is currently being built and/or run. It 27 | knows how to handle FBP protocol network commands. 28 | 29 | ElixirFBP.Graph keeps track of the FBP graph that is currently being built and/or 30 | run. It knows how to handle FBP protocol graph commands. 31 | 32 | An ElixirFBP.Subscription serves as connection between any two components, hence 33 | there is one Subscription per FBP graph edge. The components correspond to the 34 | publisher and subscriber in the [Reactive Stream protocol](http://www.reactive-streams.org/). A Subscription can limit the number of Information Packets that can be sent from a 35 | publisher to a subscriber, that is, "back pressure" can be applied to the 36 | publisher. 37 | 38 | # Limitations 39 | * The components for this runtime are hard-wired in ElixirFBP. A "discovery" 40 | mechanism to locate Elixir components will be implemented in a future release. 41 | -------------------------------------------------------------------------------- /config/config.exs: -------------------------------------------------------------------------------- 1 | # This file is responsible for configuring your application 2 | # and its dependencies with the aid of the Mix.Config module. 3 | use Mix.Config 4 | 5 | # This configuration is loaded before any dependency and is restricted 6 | # to this project. If another project depends on this project, this 7 | # file won't be loaded nor affect the parent project. For this reason, 8 | # if you want to provide default values for your application for third- 9 | # party users, it should be done in your mix.exs file. 10 | 11 | # Sample configuration: 12 | # 13 | # config :logger, :console, 14 | # level: :info, 15 | # format: "$date $time [$level] $metadata$message\n", 16 | # metadata: [:user_id] 17 | 18 | # It is also possible to import configuration files, relative to this 19 | # directory. For example, you can emulate configuration per environment 20 | # by uncommenting the line below and defining dev.exs, test.exs and such. 21 | # Configuration from the imported file will override the ones defined 22 | # here (which is why it is important to import them last). 23 | # 24 | # import_config "#{Mix.env}.exs" 25 | -------------------------------------------------------------------------------- /doc/404.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 | 6 | 7 |Sorry, but the page you were trying to get to, does not exist. You 65 | may want to try searching this site using the sidebar or using our 66 | API Reference page to find what 67 | you were looking for.
68 | 69 | 81 |description :: String.t
158 |
159 | inports :: [{:atom, atom}]
184 |
185 | loop(%{}, %{}) :: any
210 |
211 | outports :: [{:atom, atom}]
236 |
237 | Component is used to start an FBP component. It takes the component’s name - 75 | an Elixir module name - and spawns a process. It is assumed that the component 76 | module supports a loop function which will be called once the component is 77 | spawned.
78 | 79 |Start the execution of a component in its own process(es). Spawn as many 103 | processes as are specified in the no_of_processes value (the default value is one)
104 |Stop a component. This means find the pid of all of the component’s processes, 113 | unregister it and force an exit
114 |Start the execution of a component in its own process(es). Spawn as many 153 | processes as are specified in the no_of_processes value (the default value is one).
154 |inports is a list of {port, value} tuples where value is an initial value or 155 | a Subscription pid. outports is a list of {port, pid} tuples where the pid is 156 | a Subscription.
157 |inports and outports are used to create the initial arguments sent to a 158 | Component’s loop function. They are also used to create lists of component 159 | pids that must be sent to any Subscriptions that a component’s in or out ports 160 | are connected to.
161 | 162 |Stop a component. This means find the pid of all of the component’s processes, 179 | unregister it and force an exit.
180 | 181 |This module is responsible for loading ElixirFBP components at run time. Given 75 | a list of file paths, it will examine all modules, select those which implement 76 | the ElixirFBP.ComponentBehaviour and develop a list of Component attributes 77 | such as description, inports, and outports.
78 |This code is based on the answer 79 | to a question about loading Elixir modules. The code is from the hex package 80 | manager.
81 | 82 |ElxirFBP.Graph is a GenServer that provides support for the creation and 75 | maintainance of an FBP Graph.
76 |An FBP graph contains Nodes connected by Edges. Facilities are provided for 77 | the creation, deletion, and modification of nodes and edges. Initial Information 78 | Packets (IIP’s) can also be specified.
79 |Graphs are implemented using Erlang’s digraph library.
80 |The digraph Label associated with a node (digraph vertex) is 81 | [component, inports, inport_types, outports, outport_types, metadata] where 82 | component is the string name of a component e.g., “Math.Add”. inports 83 | and outports are lists of atomic name, initial value pairs, e.g., {:augend, 2} and 84 | inport_types and outport_types are lists of atomic name, type, e.g., {:augend, :integer}.
85 |Initial values can be set using the add_initial graph command.
86 |The digraph Label associated with an edge is [src.port,, tgt.port, metadata] where src.port 87 | and tgt.port are atom values for the component’s ports.
88 |Functions supported by this module are based on NoFlo’s FBP Network Protocol, 89 | specifically the graph sub-protocol. See http://noflojs.org/documentation/protocol/ 90 | for the details.
91 |TODO: Provide support for Port and Group maintenance. 92 | TODO: Use secret parameter 93 | TODO: Handle :digraph errors 94 | TODO: Metadata needs to be stored somewhere in add_initial()
95 | 96 |Add an edge to the FBP Graph
133 |Place an initial value at the port of a node in and FBP Graph
142 |Add a node to the FBP Graph. Note the number of default processes is 1
151 |Change an edge’s metadata in an FBP Graph
160 |Change the metadata associated with a node in a graph
169 |Return the current list of edges - primarily used for testing/debugging
178 |Return the edges attached to a node
187 |Retreive the FBP Graph structure - primarily used for testing/debugging
196 |Return info about a node
205 |Return the status variables for this graph
214 |Get the subscription pid for this edge
223 |Callback implementation for stopping this GenServer
232 |Callback implementation for ElixirFBP.Graph.clear() 241 | Create and initialize the FBP Graph Structure which becomes the State
242 |Return the current list of nodes
251 |Remove the edge between the two given node/ports in an FBP Graph
260 |Remove an initial value at the port of a node in the FBP Graph. It is set to 269 | the value nil
270 |Remove a node from an FBP Graph
279 |Rename a node in an FBP Graph
288 |Set the parameters associated with this graph
297 |Start the execution of the components in this graph. Optionally supplying 306 | a run mode of :pull or :push (default)
307 |Starts things off with the creation of the state. Register it with the name 316 | graph_id - converted to an atom
317 |Stop this GenServer
326 |Stop the execution of the components in this graph. 335 | This should normally be called via the Network.stop(graph_id) function
336 |Callback implementation triggered by asking the GenServer to :stop
345 |Add an edge to the FBP Graph
406 | 407 |Place an initial value at the port of a node in and FBP Graph
424 | 425 |Add a node to the FBP Graph. Note the number of default processes is 1.
442 | 443 |Change an edge’s metadata in an FBP Graph
460 | 461 |Change the metadata associated with a node in a graph
478 | 479 |Return the current list of edges - primarily used for testing/debugging.
496 | 497 |Return the edges attached to a node
514 | 515 |Retreive the FBP Graph structure - primarily used for testing/debugging
532 | 533 |Return info about a node.
550 | 551 |Return the status variables for this graph
568 | 569 |Get the subscription pid for this edge.
586 | 587 |Callback implementation for stopping this GenServer.
604 | 605 |Callback implementation for ElixirFBP.Graph.clear() 622 | Create and initialize the FBP Graph Structure which becomes the State
623 | 624 |Return the current list of nodes
641 | 642 |Remove the edge between the two given node/ports in an FBP Graph
659 | 660 |Remove an initial value at the port of a node in the FBP Graph. It is set to 677 | the value nil.
678 | 679 |Remove a node from an FBP Graph
696 | 697 |Rename a node in an FBP Graph
714 | 715 |Set the parameters associated with this graph
732 | 733 |Start the execution of the components in this graph. Optionally supplying 750 | a run mode of :pull or :push (default)
751 | 752 |Starts things off with the creation of the state. Register it with the name 769 | graph_id - converted to an atom.
770 | 771 |Stop this GenServer
788 | 789 |Stop the execution of the components in this graph. 806 | This should normally be called via the Network.stop(graph_id) function.
807 | 808 |Callback implementation triggered by asking the GenServer to :stop
825 | 826 |A special component that can deliver a constant anytime it is sent 75 | a :value message.
76 | 77 |Callback implementation for ElixirFBP.Behaviour.description/0
Callback implementation for ElixirFBP.Behaviour.inports/0
Callback implementation for ElixirFBP.Behaviour.loop/2
Callback implementation for ElixirFBP.Behaviour.outports/0
Callback implementation for ElixirFBP.Behaviour.description/0
.
Callback implementation for ElixirFBP.Behaviour.inports/0
.
Callback implementation for ElixirFBP.Behaviour.loop/2
.
Callback implementation for ElixirFBP.Behaviour.outports/0
.
ElxirFBP.Network is a GenServer that provides support for starting and stopping a 75 | FBP network, and finding out about its state. The network keeps 76 | a dictionary of graphs ids, each of which points to an ElixirFBP.Graph structure. 77 | Graphs are also implemented as GenServers
78 |Functions supported by this module are based on NoFlo’s FBP Network Protocol, 79 | specifically the network sub-protocol. See http://noflojs.org/documentation/protocol/ 80 | for the details. There is one exception: the clear graph command is implemented here.
81 |There is a function - remove_graph - that is not part of the Network Protocol.
82 |This module is registered with its module name.
83 |TODO: Finish implementation of data function
84 | 85 |Clear adds a new graph in the network. This command is part of the Graph protocol 109 | but here it is implemented as a network command because it seems like a better fit
110 |Data transmission on an edge
119 |Retrieve the registered graph name if it exists. A call to clear will have created 128 | and registered it
129 |Get the current status of a graph
138 |Callback implementation for ElixirFBP.Network.stop() 147 | Stop the execution of a graph identified by its id (string)
148 |Callback implementation for ElixirFBP.Network.data
157 |Callback implementation for ElixirFBP.Network.start_link() 166 | Initialize the state - no graphs. There are no initialization args
167 |Remove a graph from this network
176 |Set the network debug switch on or off
185 |Start execution of a graph, optionally specifing whether it is to 194 | run in either :pull or :push (default) mode
195 |Starts things off with the creation of the empty state
204 |Stop the Network GenServer process
213 |Stop the execution of the graph
222 |Callback implmentation for having asked the GenServer to stop processing
231 |Clear adds a new graph in the network. This command is part of the Graph protocol 270 | but here it is implemented as a network command because it seems like a better fit.
271 | 272 |Data transmission on an edge.
289 | 290 |Retrieve the registered graph name if it exists. A call to clear will have created 307 | and registered it.
308 | 309 |Get the current status of a graph
326 | 327 |Callback implementation for ElixirFBP.Network.stop() 344 | Stop the execution of a graph identified by its id (string).
345 | 346 |Callback implementation for ElixirFBP.Network.data
363 | 364 |Callback implementation for ElixirFBP.Network.start_link() 381 | Initialize the state - no graphs. There are no initialization args.
382 | 383 |Remove a graph from this network.
400 | 401 |Set the network debug switch on or off
418 | 419 |Start execution of a graph, optionally specifing whether it is to 436 | run in either :pull or :push (default) mode.
437 | 438 |Starts things off with the creation of the empty state.
455 | 456 |Stop the Network GenServer process
473 | 474 |Stop the execution of the graph
491 | 492 |Callback implmentation for having asked the GenServer to stop processing
509 | 510 |A Subscription serves as a conduit and a control mechanism for the delivery of 75 | data from Publishers (Components) to Subscribers (Components). A Subscriber 76 | must specify how many IPs it is willing to receive via a {:request, n} message 77 | where n is some integer or the atom :infinity. The Subscription will ensure that 78 | no more IPs than have been asked for will be sent.
79 |When a subscriber asks for an infinite number of values via a {:request, :infinity} 80 | message, the Subscription effectively becoming a push flow without any back pressure.
81 |A Subscription is able to deal with multiple Publisher and/or Subscriber 82 | Component processes. Values are devlivered to multiple Subscriber processes 83 | in a round-robin manner.
84 |The design of this module borrows ideas and terminology from the Reactive Stream 85 | project: http://www.reactive-streams.org/
86 | 87 |This function serves as a Subscriptions’s main computational loop, dealing 111 | with requests for data from Subscribers and responses from Publishers. The 112 | subscriber_index points to the next subscriber that is to receive data
113 |The new function doesn’t do much except initialize a Subscription structure 122 | with values for the names of the publisher and subscriber ports that this 123 | subscription will connect to and manage. Also see the start() function below. 124 | The initial value for a subscription’s capacity is set to :infinity
125 |The new function doesn’t do much except initialize a Subscription structure 134 | with values for the names of the publisher and subscriber ports that this 135 | subscription will connect to and manage. Also see the start() function below. 136 | An initial value for the subscription’s capacity is supplied
137 |The start function does nothing more than spawn a Subscription process. The other 146 | values in the Subscription structure are initialized after the Components that 147 | are connected to this subscription have been started. See Component.start(); 148 | it is then that we know how many subscriber and publisher processes are 149 | attached to this subscription
150 |This function serves as a Subscriptions’s main computational loop, dealing 195 | with requests for data from Subscribers and responses from Publishers. The 196 | subscriber_index points to the next subscriber that is to receive data.
197 |The subscriber and publisher processes are started with Component.start. after 198 | starting a component’s process(es), the function sends lists of process pids 199 | as messages to this subscription process.
200 | 201 |The new function doesn’t do much except initialize a Subscription structure 218 | with values for the names of the publisher and subscriber ports that this 219 | subscription will connect to and manage. Also see the start() function below. 220 | The initial value for a subscription’s capacity is set to :infinity.
221 | 222 |The new function doesn’t do much except initialize a Subscription structure 239 | with values for the names of the publisher and subscriber ports that this 240 | subscription will connect to and manage. Also see the start() function below. 241 | An initial value for the subscription’s capacity is supplied.
242 | 243 |The start function does nothing more than spawn a Subscription process. The other 260 | values in the Subscription structure are initialized after the Components that 261 | are connected to this subscription have been started. See Component.start(); 262 | it is then that we know how many subscriber and publisher processes are 263 | attached to this subscription.
264 | 265 |ElixirFBP is an implementation of the flow-based programming (FBP) technique. 75 | An FBP program is represented by a directed graph where the nodes are 76 | components that can receive Information Packets (IPs) via in ports and send 77 | IPs - typically after some computation - out the out ports.
78 |In ElixirFBP, each component is a module that must specify the names of its 79 | in and out ports and it must implement a loop function.
80 |An FBP program is created by adding components to an ElixrFBP.Graph. The 81 | graph, in turn, is kept inside and managed by an ElixirFBP.Network.
82 | 83 |ElixirFBP is an implementation of the flow-based programming (FBP) technique. 79 | An FBP program is represented by a directed graph where the nodes are 80 | components that can receive Information Packets (IPs) via in ports and send 81 | IPs - typically after some computation - out the out ports
82 |Component is used to start an FBP component. It takes the component’s name - 93 | an Elixir module name - and spawns a process. It is assumed that the component 94 | module supports a loop function which will be called once the component is 95 | spawned
96 |This module is responsible for loading ElixirFBP components at run time. Given 103 | a list of file paths, it will examine all modules, select those which implement 104 | the ElixirFBP.ComponentBehaviour and develop a list of Component attributes 105 | such as description, inports, and outports
106 |ElxirFBP.Graph is a GenServer that provides support for the creation and 113 | maintainance of an FBP Graph
114 |A special component that can deliver a constant anytime it is sent 121 | a :value message
122 |ElxirFBP.Network is a GenServer that provides support for starting and stopping a 129 | FBP network, and finding out about its state. The network keeps 130 | a dictionary of graphs ids, each of which points to an ElixirFBP.Graph structure. 131 | Graphs are also implemented as GenServers
132 |A Subscription serves as a conduit and a control mechanism for the delivery of 139 | data from Publishers (Components) to Subscribers (Components). A Subscriber 140 | must specify how many IPs it is willing to receive via a {:request, n} message 141 | where n is some integer or the atom :infinity. The Subscription will ensure that 142 | no more IPs than have been asked for will be sent
143 |