Solved

Best Practice Question – Tracking Multiple Item States

  • 10 December 2018
  • 6 replies
  • 38 views

Userlevel 5
Badge +14

This is a general best practice question for people who have been around the block a few times with Nintex Workflow for SharePoint (on prem, though I'm not entirely sure that it'll matter). 


The Basic scenario is this. 

 

I have a SharePoint List we'll call "Orders" that has a Nintex Form for the only Content Type (Order) available. The Order Form contains a Repeating Section of 'Line Items' which can be filled out by the user. Those Line Items, at some point further on in the process, will be converted to individual Items on another List (let's call it 'Line Items List') on a different Site

 

Each one of thoseLine Items have a workflow which runs on it and carries it through various States as people complete tasks and verify the integrity of said work. 

 

However, at a particular 'State', I would like to create a SINGLE task back on the Site containing the Orders List, so that the Order's creator can do a final verification of all the uploaded / modified data on those Line Items

 

This is a simple visual to kinda show what I'm on about: 

221632_pastedImage_12.png

 

As you can see, I'm going from One to Many and then back to One. 

 

The problem is, is that I have not found a particularly good way of going from Many down to One. Tracking the changes of Multiple Items isn't something that is included out of the box (as far as I know) with the Nintex Start Conditions. If they were, I could easily say do something along the lines of "If all of the items with the related Order Number have Statues beyond X, then Run this workflow", but this is not the world that we live in. 

 

There are a few ways that I have fiddled around solving something like this, but not a single one of them is completely satisfactory. Thus far I have tried the following. 

 

  1. Once a Line Item reaches the stopping State, have it look around at the other Line Items to see if their statuses are at the same point or beyond, if and only if they are, execute the workflow ONLY on the item doing the checking.
    • This can fail if two (or more) tasks are completed too closely to one another, and they both see all of the other items as being in a state that would let them think that they should run the next step. 
       
  2. Once a Line Item reaches the stopping State, have it increment or modify a column BACK on the Order List Item which will trigger a conditionally started Workflow on the Order to then Query the Line Item List and based on the conditions specified, continue along with the process or stop and wait to be invoked again. 
    • This can fail for many of the same reasons as the method 1 can fail, but with the additional silliness of potentially having to clean up 'bad' increments / updates. If you're incrementing a value of a column named something like [Line Items Completed], you first have to read the value of column from the Line Item, then increment it, then send it back. This can completely fail due to Race Conditions
       

As stated, both of these *can* run into Race Conditions (meaning that there is a chance that two or more items can both reach a valid state at the same time, and attempt to make changes at the same time which will result in one of the updates being *missed* or an error being thrown). While that might seem like a pedantic thing to care about, I would like to build things in such a way as to make sure that the possibility of that happening is reduced to 0. As we have all found out (the hard way):

 

If it can happen, your users will eventually find a way to make it happen!

 

 

Do any of you all have design patterns that you have created to solve this problem in a straight forward and completely air-tight way? Maybe I'm going about it all wrong, but the only way to know is to ask! I believe that I DO have a new approach that will fix it, but it might be a little silly and over the top, so I'd rather ask the community first and if nothing seems satisfactory, I'll just release my own way of solving this even though it's kinda overkill (maybe) happy.png

 

Looking forward to having this discussion. 

 

Thank you all for you time!

icon

Best answer by MegaJerk 15 August 2019, 22:22

View original

6 replies

Userlevel 6
Badge +15

Hmm...

Great write up.  I understand the problem. It's gross, haha.

All of the options that immediately jump to mind won't work because we have an unknown amount of items. 

I have the dumbest idea. What if:

1. Grab all line items

2. Put all line items into new items

3. Grab ID of each, start looping & start workflow on each item ... however - first we make sure we pass a unique ID from our Order Form onto each new line item.

Like, Order OR-123 but Line Item OR-123-01, for example.  Then, of course, you'd have a status column hidden somewhere within each Line Item. 


Then you could have a third workflow - a Site workflow - that runs daily or hourly or whatever, and combs through Orders that are not "Complete", picks up the Order Form ID, queries the Line Items list for that Order ID, then checks the status - and triggers the final workflow if all are equal to "Complete". 

I ... think that would do it? I mean it's a bit messy, but, it gets the job done. And then it's still basically the Order Form managing the Line Items and not the other way around.

Userlevel 5
Badge +14

from my point of view, for this kind of scenario the most suitable approach would be a scheduled site workflow.

it would first check what orders are in an ACTIVE status and then for those check status of single line items. if they already met required stop state then proceed further on with next order processing step.

Userlevel 5
Badge +14

(This is a reply to both Marian Hatala‌ and Rhia Wieclawek‌ - I was on vacation for 2 weeks and so I stayed very very far away from all things Nintex (or at least as far as I could ))


Rhia Wieclawek: Actually, the Line Items from the Repeating Section in the Order are given both a unique ID and are being created as actual List Items on a different site, so that part's done!

Rhia Wieclawek & Marian Hatala: The only problem I have with a scheduled workflow is that it is not immediate. I thought about doing that first, but it wouldn't be acceptable for how work needs to get from point A -> B as quickly as possible. 

That being said though... I guess nothing stops me from using a tighter window for the schedule, but because I've never used this type of workflow, I don't know the impacts or implications for setting it up to run every 5 or 10 minutes. Or is that crazy

----------

In a day or two I'll try to come back here and flesh out my idea for approaching this in as close to real-time as possible. But being that I have just arrived back, it's putting out fires time for me   

Thank you both for your replies! 

Userlevel 5
Badge +14
The only problem I have with a scheduled workflow is that it is not immediate.

IMHO, it's better solution that notifies/advance to next step a minute later but is reliable, than quick unreliable one.

 I don't know the impacts or implications for setting it up to run every 5 or 10 minutes. 

usually that doesn't mean any big (negative) impact. CAML queries are quite fast. I think for simple check of item's status for bunch of order you even not need any looping, it could be done with just two queries.

of course it depends on overall list(s) size, number of open orders/order items, etc. but that's valid in general.

Userlevel 5
Badge +14

After several months, I am finally coming back to this. Around the time I made the original post I had an idea of how I could accomplish this, but it was only until a couple of weeks ago that I have been able to really implement it and test it to the point where I'm comfortable with sharing it. 


 


Though I do not expect my solution to work for every user, I have made it as simple as possible so that it can be used as more of a building block, rather than a 'set' thing. 


 


To recap (briefly) what the problem is that I'm trying to solve...


 


Children Items, Associated to a SINGLE Parent Item, have no clear way of reliably informing the Parent Item that they are finished without potentially running into Race Conditions. 


 


Because Multiple Children could be completed at approximately the same time, it creates the opportunity for one of them to Read / Write data that is in error. 


 


As an example, lets say that when a Child Item is complete, you'd like to increment a Status Column on the Parent that will inform users how many, if any, of the Associated Children Items are complete.


 


Here is how that could go wrong...


 


Scenario 1 - Child Items increment a Column on Parent Item by 1


 



  1. Child Item 1 READS the Value (0) of [Increment Column] on Parent.

  2. Child Item 2 READS the Value (0) of [Increment Column] on Parent 

  3. Child Item 1 ADDS 1 to the Value (1)

  4. Child Item 1 SENDS new Value (1) to Parent

  5. Parent Item's [Increment Column] now equals 1

  6. Child Item 2 ADDS 1 to the Value (1)

  7. Child Item 2 SENDS new Value (1) to the Parent

  8. Parent Item's [Increment Column] now equals 1


 


Scenario 2 - Child Item tries to count other completed Siblings, then sends total to Parent



  1. Child Item 1 - Falls into a Counting State, one state before Completed

  2. Child Item 2 - Falls into a Counting State, one state before Completed

  3. Child Item 1 - Counts siblings that are in Completed State. Returns 0

  4. Child Item 2 - Counts siblings that are in Completed State. Returns 0

  5. Child Item 1 - ADDS 1 to Returned Value -> SENDS Value (1) to Parent

  6. Child Item 2 - ADDS 1 to Returned Value -> SENDS Value (1) to Parent

  7. Parent Item's [Children Completed] Column now equals 1 but should equal 2


-------


My Solution 


-------


 


Stealing a few ideas from Asynchronous programming concepts, Messaging Programming Models, and the behavior of the Call Web Service Action, I have come up with the following UDA: 


 



While the picture above might look complicated, all this UDA does is place a Web Service Call inside of a Loop. If the Web Service Call succeeds (meaning the targeted Workflow was Started), then it exists. If it fails, then it pauses for 5 minutes and will try again, for a maximum of 5 Tries. 


 


You see, when you use the StartWorkflowOnListItem using the Web Service provided by Ninex, it will FAIL if you target an Item and Workflow that already has the named Workflow running on it! This can be leveraged as an advantage because we can essentially create a Queue System that waits for the next available opening to Complete its job! 


 


If you have a bunch of Items that are completing slowly, this runs INSTANTLY, but if you two or more Items that complete at the SAME TIME, then one of them will win the race and will complete instantly,  while the other one will just wait around for a bit before trying again. 


 


Ultimately this allows me to solve my problem and will let things to work as quickly as possible with the only pausing occurring when things actually need to pause. 


 


Attached is a PDF of a more robust example showing how the various parts of this work together (Children Items starting workflows, which in turn start this, which in turn starts a different workflow, and updates the Parent), however I do plan on throwing the UDA and associated workflows in the event someone would want to recreate this on their own. 


 


Any who, see ya! 


 


 

Userlevel 5
Badge +14

I have discovered a bit of missing info from the PDF I attached above, and figured I would make a note of the error here in the event someone happens upon this in the future. I failed to include that the workflow being invoked on the Parent Item (Count Completed Children Items) should have an action which updates the Status of the Child Item that invoked it! This is why it's important to pass the ID of the Child Item *to* the Parent Item's workflow as without it, you would have no way of knowing which Child Item to update, and without updating the Child Item's Status from "Completing" to "Completed" the child workflow will obviously never resolve / change state!

I will try to finally do a full write up about this approach to workflow design soon because I have also changed my own approach a bit in recent times. 

Until then, keep on learning! 

Reply