Comments (21)
@taoza I confirm! Other functions cannot be used as conditions, at least for the time being
from specification.
I think you can do these types of UIs just as easy with SW. Instead of building your json structure from these fields you would build your jq expression instead.
This would be have to be done by runtime anyways :)
from specification.
Thanks for opening issue, wanted to propose maybe something similar but bit different, let me know what you think:
With jq when implementing expression func would most likely do:
def isAdult($d): $d.applicant | .age >= 18;
With this if you had state data:
{
"applicant": {
"name": "Joe",
"age": 22
}
}
you could do
isAdult(.)
or even pass custom json to isAdult for example:
isAdult({"applicant": {"name": "Joe","age": 22}})
So I am not sure we really need support for functionRef in this case but we could allow for input to be passed to the function referenced by "fn".
Imo would follow the way jq does this, so for example:
"condition": "${ fn:isAdult(INPUT) }",
Where INPUT can be "." or "{...}" just like you can do with straight jq. Can also be references to $SECRETS and other things as well.
This way we could even get rid of "fn" completely.
WDYT
from specification.
Thanks for the prompt reply @tsurdilo.
I like your proposal, especially its simplicity.
I'd also like to confirm that dataConditions
is meant to support either inline jq expression or jq functions but not the other type of functions, e.g. rest
and graphql
. I'm asking while thinking about the limitations in jq and how to work around it for the more complex conditions.
from specification.
We must consider this possibility carefully since it can open a can of worms and add complexity to the model. jq
expressions are simple yet powerful. If data is needed, one can add a state before the Switch
to grab it, prepare it in the state content using stateFilter
, and then proceed to the conditionals. It clears defines the intention.
from specification.
State data filers can be applied on the switch state itself if you need to pre-process stuff, not sure why adding extra state is needed but could be some use case i dont see atm.
If we allow arbitrary args to be passed to functions think it would be ok to pass this way for expression functions too, understand that you can do lots of weird stuff with jq but think you can do same weirdness with any expression type property as well currently. Wondering what scenarios or edge cases you have in mind that we should consider?
from specification.
State data filers can be applied on the switch state itself if you need to pre-process stuff, not sure why adding extra state is needed but could be some use case i dont see atm.
If you need to call an external service, like the OP stated in this description. In that case, another state should be able to call the external function.
from specification.
If you need to call an external service, like the OP stated in this description. In that case, another state should be able to call the external function.
@ricardozanini I guess you are referring to this scenario: #732 (comment)
I figured it might help to elaborate on my use case. I'm thinking of building a visual workflow builder that produces SW DSL. Therefore, I'd like to have a more UI-friendly way to structure conditions, such as explicit arguments and logical operators (AND, OR), as well as reusing the externalised condition implementation while minimising scripts, such as JQ.
Below is an example from Step Functions Workflow Studio that might help to explain what I mean:
I'm fully aware that this direction may not align well with the project but I'm keen to hear your thoughts. Thanks folks!
from specification.
I see. Your use case makes sense. But what I meant is for use cases such as this:
{
{
"functions": [
{
"name": "isAdult",
"operation": "myopenapi.json#isadult",
"type": "rest"
}
]
},
"states":[
{
"name":"CheckApplicant",
"type":"switch",
"dataConditions": [
{
"name": "Applicant is adult",
"condition": {
"functionref": "isAdult",
"arguments": { "age": "${ .user.age }"}
},
"transition": "ApproveApplication"
}
],
"defaultCondition": {
"transition": "RejectApplication"
}
}
]
}
Where the function can be an arbitrary function defined in the workflow rather than a simple jq
. In situations like this, we have no clue about the function's response interface to infer the datacondition. Additionally, we should add support for stateDataFilter
too, so the workflow's author can filter the response somehow since the service might not offer the exactly boolean parameter we are expecting here.
So, suppose you need to rely on an output from a function like this. In that case, I'd say to have a state before the switch
to populate the workflow data context with the information and have the datacondition a simple jq expression to infer over the structure.
I agree that support to explicitly declare the parameter would be an excellent addition to the spec, but not calling any arbitrary function from the conditional statement. The jq function can't implement your scenario? For example:
(.order.total > 10 and .order.country == "CA") or (.order.total > 10 and .order.country == "US")
from specification.
Just fyi in early stages of the project we did have very similar switch state boolean operators, however found that it is very limiting and that expression languages can do this much easier and are more powerful
from specification.
| In that case, I'd say to have a state before the switch to populate the workflow data context with the information and have the datacondition a simple jq expression to infer over the structure.
@ricardozanini i think this is one way, but with state data filter "input" expression type prop: https://github.com/serverlessworkflow/specification/blob/main/schema/workflow.json#L1847
you dont really need to, you can filter the state data directly with it and it would be filtered before any conditions are evaluated (its the first thing that happens when wf state becomes active)
from specification.
yes! but if you need complementary data to perform the evaluation, you would need to fetch this data from somewhere, right? So, in that case one would need to use an operation state. Or am I missing something?
from specification.
I think you can do these types of UIs just as easy with SW. Instead of building your json structure from these fields you would build your jq expression instead.
I agree @tsurdilo, I'm also thinking about exploring this path.
but if you need complementary data to perform the evaluation, you would need to fetch this data from somewhere, right?
@ricardozanini Or perhaps delegate the conditional evaluation to an external service when you can't afford to fetch the data back. For example, when checking the uniqueness of an email address.
from specification.
@taoza, that again is the problem I was talking about. If you have an external service that, let's say receives an email as input and return a boolean value you can't possibly know the interface/data structure by reading the workflow DSL. You can just assume. That's what I was trying to explain in my previous comment. You can rather call the service in another state, include the response to the data context, and validate it in the conditionals in the switch state.
from specification.
let's say receives an email as input and return a boolean value you can't possibly know the interface/data structure by reading the workflow DSL. You can just assume.
@ricardozanini For RESTful APIs, could we gain the certainty from the mandated OpenAPI spec?
Also, could an inline expression do the trick instead of adding the response to the flow state?
Assume the JSON response is:
{
"data": {
"unique": true
}
}
Inside dataConditions
"condition": "${ fn:isEmailUnique | .data.unique }",
from specification.
@ricardozanini For RESTful APIs, could we gain the certainty from the mandated OpenAPI spec?
We can, but users would have to go to the OpenAPI to see the interface; it won't be evident in the DSL.
Yes, your example is valid and clearly states the interface in this case. My concern is that this is not always true, unfortunately. I also understand that adding one more state to the workflow to fetch the information can be too lengthy.
I'd like to hear from other community members about it. Personally, I won't add this feature to the DSL. However, I won't stand against it.
from specification.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
from specification.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
from specification.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
from specification.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
from specification.
Closed as resolved by 1.0.0-alpha1, and therefore as part of #843
from specification.
Related Issues (20)
- flowDirective schema does not support task names HOT 1
- specify jq expression $input variable HOT 3
- Accessing secrets in the workflow definition HOT 9
- Context Data Update Behavior HOT 15
- Context Data Scoping HOT 3
- Rename output.from and output.to HOT 13
- Fix the Script Process
- Remove reliance on key order in "do" HOT 93
- Fix `endpoint` URI format in workflow SCHEMA
- [PROPOSAL] - Protect main branch against CI failures HOT 3
- Document Task's `if` property
- Invalid `do:switch` HOT 59
- Add support for expression objects HOT 8
- Authentication are not referenceable HOT 14
- Define a "Priority of Constituencies" HOT 5
- Specifying Query Parameters for call: HTTP HOT 6
- Add additional authority endpoints to OAUTH2 HOT 15
- Task to transition to a specific task HOT 3
- Where to find documentation for workflow states? HOT 3
- Semantic inconsistencies between `listen` and `emit` tasks HOT 8
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from specification.