basic concepts - modrpc/info GitHub Wiki
ModPy is a Python library for programming software systems in distributed and mobile environments. ModPy library facilitates development of distrubted services which can be used remotely. Also, it allows to define processes reactive to remote events.
A ModPy system is loosely defined to be a collection of ModPy nodes. where a ModPy node can 1) provide services by defining functions and 2) use services through function calls.
A ModPy system is a collection of interconnected ModPy nodes, where a ModPy node is any device where the ModPy runtime is running. Each ModPy node has a unique name within the system. A ModPy system is a dynamic notion in the sense that as ModPy nodes come and go, the system can dynamically change.
Within the system, nodes can interact with other nodes by using the names of nodes. A node name is a string which makes handling of the ModPy system very easy.
- A ModPy node is a container of ModPy modules.
- A ModPy module consists of ModPy resources.
- A ModPy resource is a function, an event, or a process.
- A ModPy function is a service which can be accessed by other nodes.
- A ModPy event is an event which can be observed by other nodes.
- A ModPy process is a piece of code reactive to ModPy events.
A ModPy node is any device which runs the ModPy runtime. Each ModPy node has a unique name, through which other nodes can designate the node. A node can provide services to other node. Also, a node can contain reactive processes, which reacts to events generated by other nodes.
Typically, a set of services and reactive processes are bundled in a single Python module.
For example, mods.robot_ctrl
package can contain servo
module, which in turn contain services such as turn_right
and turn_left
.
A ModPy node is a container of ModPy modules.
node = modpy.init_node(name="mynode0") # initialize the node
from mods.robot_ctrl import servo, motor # import ModPy modules
node.start() # start the node
A ModPy resource is an artifact which either provides services to other nodes or adds an internal behavior of nodes. There are three types of resources: functions, events, and processes.
A ModPy function is a Python function which can be invoked either locally or from other nodes. A ModPy function can be defined by adding the decorator @modpy.func.
@modpy.func
def add(a, b):
return a + b
result = await modpy.call("n0/add", 10, 20)
A ModPy event is a resource which can be fired by its owner and be observed by its subscribers. To define a new event, use the @modpy.event decorator.
@modpy.event
def data_ready_ev():
# return payload, if any, which will be shipped along with the event notification
return data_value;
Given that a node "n0" provides data_ready_ev
event, "n0" can generate its event instance using the ModPy function fire
. It will wake up all subscribers, which have been waiting for this event.
# a function inside node "n0" can fire the event
@modpy.proc
def battery_watcher():
while True:
if (battery_level < 25):
# by default, the result of data_ready_ev() will be sent as the payload
# of the event instance; one can override this by adding the optional
# payload argument
await modpy.fire("data_ready_ev");
Writing a code which waits for the event is simple.
# another note has a process which waits for the event
@modpy.proc
def my_event_subscriber():
while True:
event = await modpy.waitfor("n0/data_ready_ev")
print(event.value) # event.value contains the data sent
Also, one can wait for multiple events at the same time.
while True:
event = await modpy.waitfor("n0/data_ready_ev", "n1/data_ready_ev")
if (event.key == "n0/data_ready_ev"):
print("Data ready at n0")
else:
print("Data ready at n1")
A ModPy process is a function with an infinite loop which waits for events and performs actions over the received events. A ModPy process can be started, stopped, resumed, and killed.
A ModPy node can contain multiple processes alive at the same time.
A ModPy process is essentially a generalization of event callbacks, which waits for some event and perform some predefined functions.
Below example shows a process which models a pipeline stage which 1) waits for data to be ready, 2) grabs the data, and 3) notify that data is available.
@modpy.proc
def fifo_stage(leftnode):
while True:
event = await modpy.waitfor("%s/data_ready" % leftnode)
data = ""
while data != "<EOF>":
line = await modpy.call("%s/get_line" % leftnode)
await modpy.fire("data_ready")
Consider a series of nodes: "n0" through "n9". Each node contains a fifo_stage process inside.
for i in reversed(range(9)):
await modpy.start("n%d:fifo_stage"%(i+1), "n%d"%i)
ModPy stands for "Modular RPC for Python". Originally, I started working on a different language (Golang) where there is no "module" construct. However, Python does have "modules" so it could be a bit confusing when we say "ModPy modules'. Just consider them as loosely meaning that it is a collection of ModPy resources -- techinically, it is a Python package which contains ModPy resource definitions.