:wave: hello folks! I suspect the answer to this w...
# prefect-community
j
πŸ‘‹ hello folks! I suspect the answer to this will be "use prefect 2.0" but wanted to ask: my company is investigating prefect for the use case of storing "DAG-y" transformations elsewhere (perhaps, behind some service interface), and dynamically executing them at runtime. I think prefect 1.0 won't solve this since the
flow
needs to be defined up front, but correct me if i'm wrong. I'll try to add a few more details in the thread, and thanks in advance for your help!
Let's say that i have a workflow that does something like (in pseudocode):
Copy code
def calculate_variable():
    formula, inputs = get_formula_and_inputs()
    input_values = retrieve_input_values()

    return formula(*input_values)
this is a pretty trivial example, imagine that
formula
actually has like n inputs and there are multiple transformation steps along the way (basically,
formula
itself could be thought of as a
flow
, but one that needs to be generated at runtime)
i'm not sure if the right solution is just to have a
@task
that encapsulates all that logic, or if i should be trying to do something else. I think in prefect 1.0, my only option is to have it as a
@task
, but prefect 2.0 doesn't seem that way?
k
Yes that is right that Prefect 2.0 was specifically designed for the use case of adding tasks dynamically. The only tools you have for this in Prefect 1.0 are the conditionals like the
case
task
j
got it, thanks! so if i were to expand that example above a little, let's say that i get back a simple transformation that is represented as a json object would i write something like (in prefect 2.0):
Copy code
@task
get_transformation():
    return {
        operation: "add",
        input_1: "var_1",
        input_2: "var_2"
    }

@task
get_val_for_input(input):
    return 1

@task
add_two_things(val_1, val_2):
    return val_1 + val_2

@flow
do_transformation(transformation):
    if transformation.operation == "add":
        val_1 = get_val_for_input(transformation.input_1)
        val_2 = get_val_for_input(transformation.input_2)
        return add_two_things(val_1, val_2)

@flow
def do_the_thing():
    transformation = get_transformation()
    result = do_transformation(transformation)
    return result
maybe i'm mixing up concepts in my head though because at the surface level this seems possible in prefect 1.0....but maybe not?
k
Yeah to can do that. It’s a lot trickier in Prefect 1 because subflows are not really first-class
a
imagine that
formula
actually has like n inputs
You could solve it in 1.0 using mapping. But if you have the option of using Prefect 2.0, then that's definitely more appropriate.
j
Hmmmm ok. I'll see if I can apply it to a more complex use case, but good to know that the subflow not being a first-class entity is problematic. I'm also correct in my understanding that I can't do tasks of tasks in prefect 1 right? Does that apply in prefect 2 also?
a
why not make it a subflow? in Prefect 2.0, you can replace the
@task
decorator with a flow decorator. This way, you can call it in any other flow. I believe this is a much better (and easier to reason about) pattern than calling tasks from other tasks. In the Radar view, you could drill down from a parent flow to a child flow (subflow), which makes it much easier to troubleshoot when something goes wrong, not even mentioning the modularity/composability of subflows making your workflow code cleaner and more reusable.
Re subflows in 1.0 not being a first-class citizen - it's not entirely true. What Kevin meant is that Prefect 1.0 technically doesn't have subflows (i.e. calling a flow from another flow as a normal function) but rather the orchestrator pattern in which a child flow can be called from a parent flow via an API call
j
ahh thanks for clarification re: using an api call to trigger other flows! Definitely agree on replacing the
@task
with an
@flow
, that was more of just a curiousity question πŸ™‚
πŸ‘ 1
i'll try to apply all this to a more concrete example of my system, but thank you so much for answering my questions. very helpful!