-
Notifications
You must be signed in to change notification settings - Fork 8
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Routers and Selectors. Part 1 if
#802
Comments
if the flow started from 'if' rather than condition ':user.age > 18', it would feel more intuitive for me as a reader. This may simply be because the syntax is unfamiliar to me |
So it would look like this
And extended form with two inports would look like this
I like that condition is on the right in both forms, unlike existing draft My concern is that you can't chain
VS if we move condition to the right
But that is also true for an extended form with 2 inports (in both my and your design) - since condition is on the right, you can't chain it
in this example TLDR: it makes if easy to understand for newcomers (because condition is on the right like we used to) and also makes it more consistent (because condition is always on the right and not only in extended form), but it damages its flexibility (because it's not possible to chain it) UPD: This statement is true for all routers, because all of them support extended form with 2 inports |
One addition that can be made to "selector-mode" is that some branches can remain "simple", without dedicated data sender. It can be useful if we want to send condition message in one case, but data message in another.
This is especially useful due to the fact that we can't refer to the same sender twice |
This is a first part in the series of drafts that explores the syntax-level features needed to handle dataflow use cases, beyond the already supported capabilities like fan-in/out, binary/ternary operations, ranges, and struct selectors.
We focus on two main categories of features:
Routers:
Selectors:
These components can be further categorized by how they make decisions:
An important design principle is that all these features must be race-condition free and intuitive to use. For example, instead of extended switch form, deferred connections could theoretically be used, but they introduce intermediate lock nodes with latency that can cause race conditions. By providing first-class routing constructs instead, we ensure safe and predictable behavior without needing complex locking mechanisms.
If
Basic
If is the simplest router that receives a boolean message and routes it into two different directions based on its value.
Example
One Branch, Many Receivers
If supports multiple receivers per branch, which are handled like a fan-out. Keep in mind that the If component will not receive new messages until the previous ones are handled. Therefore, the sender of the If will be blocked by the slowest receiver in a branch.
Example
With Final Receiver
The If component has an extended form where its body is connected to a receiver. In this case, If sends a message to the selected branch receiver first, and then, after that receiver has received the message, it sends to the final receiver.
It is important to note that the basic If, after receiving a boolean message, is blocked only by the selected branch receiver(s). However, If with a final receiver is also blocked by that final receiver. Similarly, final receiver is blocked by the selected branch receiver.
This setup allows answering the question "when has the selected branch received the message?" but not "when has the selected node finished processing?" For example, sending a message to
println
will start printing, but inif {...} -> final_receiver
, the final receiver has no guarantee that printing is finished.One might think that this form of if could be emulated by putting
final_receiver
into branchesThis is not true. It has different semantics because the selected and final receivers will receive messages concurrently, not sequentially. Additionally, it is forbidden to refer to the same receiver twice.
Example
However, an If component with a final receiver can also have multiple receivers per branch, and even multiple final receivers. They are handled like a fan-out and affect the If component in the same way in terms of blocking.
Example
With Two Inports
Previous forms of If had only one inport, which is for the condition. It's possible to use if with 2 inports: one for the condition and one for the data. The purpose is to route one message based on the value of another message.
Example
The If component can have both a final receiver and 2 inports at the same time:
Example
The message sent to the final receiver in this case will have the type
IfResult
. This type allows access to both the condition and the data:Example
Selector
Like every router, If has a form where, in addition to routing, it also performs selecting. It allows selecting both the message to send and the direction to send it.
This form of
if
also supports a final receiver. The message it will receive will also have the typeIfResult<T>
. In this case,data
will be the message from the selected data sender.This form of If also supports multiple branch receivers. Each branch receiver will receive a message from selected branch-sender, final receiver will receive
IfResult
message with selected message.The text was updated successfully, but these errors were encountered: