How can I loop through a list of objects and run different actions based on values?

I have an action that returns a list of objects like:
[{media: "email", "content": "test"}, {media: "sms": "content": "short text"}, ...]

Now I need to iterate through all list objects and run target action based on the values in media. For the above example I need to get result().result and iterate through all and run email action, sms action, etc. Is this possible? Is there a better way of doing this in the workflow?

In fact I have one result but many actions will be run based on the values present in media.

determine_media:
    action: mypack.determine_media
    input:
      media: <% ctx().media %>
    next:

In Orquesta workflows you have the with items concept, and you can then loop through the items. See: Orquesta Workflow Definition — StackStorm 3.2.0 documentation

So for example say you had that list of items stored in ctx().media_list by a publish from the previous task - or you can access a task’s result directly with task().result, you could use something similar to:

determine_media:
action: mypack.determine_media
input:
media: <% item(my_obj).media %>
with:
items: my_obj in <% ctx().media_list %>

@amanda11 thank you for your reply. What you are actually doing is that you are sending each item of the list to determine_media action itself. What I want to do is in fact to call different actions (after determine media) in parallel. Let’s say the output of determine_media action consists of sms and also email. Here I need to call email action and also sms action both in parallel. Is this possible?

I wanted to use chain for that but it seems to work linearly.

I’m not sure of the best way.

One way - could be.

determine_media has 2 tasks after it - one for sms and one for email. Each of those is a loop over the with items with task(determine_media).result. Those actions could be sub-workflows - whose first task just checks they are of the correct type and then goes onto your actual action.

Or you could probably with some Jinja or YAQL trickery take that result into two separate lists to parse through. And then have two with_items on the separate lists running in parallel.

I assume that you have already defined task for sms and email. You can use yaql expression for filtering and assigning them to the different variable in the context. After that you can use those variables in the action tasks.

determine_media:
  action: mypack.determine_media
  input:
    media: <% ctx().media %>
  next:
    - when: <% succeeded() %>
      - publish:
          - emails: <% result().result.filter($.media = "email") %>
          - smss: <% result().result.filter($.media = "sms") %>
    do:
      - email_task
      - sms_task

email_task:
  action: mypack.email_action
  input:
    media: <% ctx().emails %>
    
sms_task:
  action: mypack.sms_action
  input:
    media: <% ctx().smss %>
1 Like

Thank you @kyildiz ,
Just this code section result().result is retrieved from the output of determine_media output?

@alirezastack Yes that’s right, result().result part gets the result of determine_media action.