SOLVED

Can I avoid race conditions when using static lists as a task queue?

Go to solution
Jon_Wu
Level 4

Re: Can I avoid race conditions when using static lists as a task queue?

Thanks for the advice! While normally, I think readability is king, I was opting for the positive lookup to go along with the Smart List Best Practices #3:

Use positive over negative operators - While "not" filters are available, they have to search the entire data set in your instance, which can be extremely time-consuming. Positive "is" filters are able to leverage more effective search algorithms.

As long as we had good docs on how to set things up correctly, I'm hoping the confusion won't be too bad and that the potential performance will be worth it.

Thinking about the backend, they probably make this recommendation because it's common that databases can't use an index for a negation query, but they can for instantaneous lookup for an equals query. https://stackoverflow.com/questions/1759476/database-index-not-used-if-the-where-criteria-is​ discusses this for SQL. I'm not sure what database Marketo Static Lists are stored in and if the same issue applies, but it seems like better safe than sorry when working with potentially millions of things.

SanfordWhiteman
Level 10 - Community Moderator

Re: Can I avoid race conditions when using static lists as a task queue?

Hey Jon, I definitely think this is overkill now, and causing more harm than good. The more steps you have, the more unsynchronized operations there are, and the greater capacity for race conditions. (Because again, the steps of a single flow are not wrapped in a transaction or lock.)

If you're willing to have a Smart Campaign that's this obscure, but with dubious (maybe even negative) effects, why not go for an actual Compare-and-Swap via a webhook? That'll guarantee you will not have a race condition.

databases can't use an index for a negation query, but they can for instantaneous lookup for an equals query

Even if it's called Not in List in the UI, doesn't have to be materialized as a inequality query. It can just as easily be SELECT ID FROM LISTS WHERE ID = ? AND LIST = 22, checking for no result set. That's a standard equality query and will use an index.

Jon_Wu
Level 4

Re: Can I avoid race conditions when using static lists as a task queue?

Hi Sanford. It seems like what I have down gives some balance between adding a little safety and not increasing complexity too much, adding external dependencies, or slowing down performance by more than a couple hundred ms, but I'd love to hear more about your thoughts on compare-and-swap via webhook.

First, I think what I have now in the screenshot reduces the race condition window to a reasonable size. There's probably a 50-100 ms window between where we check to remove them from the flow and when we actually get them removed from the list. Not ideal, but I don't expect too much concurrency except when a cron / scheduled Smart Campaign overlaps with triggers. As I'm typing this, another way I could reduce the likeliness of a race condition is to add a wait step before putting people into a cron list, so that the cron is truly more of a fallback and won't compete with triggered campaigns that execute immediately, but that would add yet another step. When new leads are created OR when leads are associated, I try to kick off actions to send emails that were triggered by activity that was logged while the lead was anonymous. The ideal scenario is that I can use a trigger on a server-side form post that I use to associate leads, but if that fails or if I'm associating via REST API, I depend on 24 scheduled batches (running once per hour) to try and flush the queues out as a fallback. If any of those scheduled campaigns run at the same time as the lead association, that's where the race is most likely to happen.

The super ugly part with all of this is that I'd have to have our marketing team implement all of these things every time the want to set a triggered email, which seems tedious. If I was using a webhook to do a lock externally, I'd need to set up another service, have a key/value store with tracking for every campaign that's running, and then I think I'd be writing back to a Marketo field with the result by campaign, so I'd need a new lead field for every campaign that I run. Or this kind of what you're thinking with a compare-and-swap via webhook? If so, I think that's probably too much. Worst case if the race condition happens, is somebody gets 2 emails. If that happens 1 in 100,000 times that's probably not a huge deal.

While I agree the smart thing to do would be to never use an inequality query, but I was imagining if that were the case, the Smart List Best Practices doc wouldn't need to recommend use positive over negative operators, but this is just speculation of course. Either way, I think these lists will probably be small so Denise's advice to go with more readable solution may be the most practical if I was keeping this strategy.