Contended Transaction trying to update Record

When I run the following function async a few times, so the same function is getting called many times in parallel, I’m running into Contended Transaction

export const GetTest = function (size: number) {
    return Map(
      Select(
        ["data"],
        Paginate(
          Join(
            Range(
              Match(Index(Thing_Indexes.THINGS_BY_TIME)),
              [],
              Now()
            ),
            Lambda(["time", "ref"], Match(Index(Thing_Indexes.THINGS_BY_SERVED), Var("ref")))),
          { size: size })
      ),
      Lambda([ThingModel.COUNT_SERVED, "ref"],
        Let({
          updateCount: Update(Var("ref"), {
            data: {
              [ThingModel.COUNT_SERVED]: Add(Select(["data", ThingModel.COUNT_SERVED], Get(Var("ref"))), 1)
            },
          })
        }, Var("updateCount"))
      )
    )
  };

in parallel, I’m seeing

   "code": "contended transaction",\n' +
      '      "description": "Transaction was aborted due to detection of concurrent modification."\n' +

Now, let me explain the reason for this query.

I don’t actually care, at this point in time, about tracking COUNT_SERVED. This was an attempt to ensure that my Things are served evenly. Eg if I have 10 things, I want all 10 of them to get equal exposure if only 2 of them are being served at at time.

My preferred solution would be to use a randomizer and randomly select a Thing to be served. This would also solve my use case, because over a large number of queries the Things would be served evenly.

And I’m currently investigating faunadb-fql-lib/RandomString.ts at master · shiftx/faunadb-fql-lib · GitHub which I found from Random number generation

It does seem like this issue falls into Best practices :: Fauna Documentation and Scaling write throughput :: Fauna Documentation

But if I can get a quick win with the random approach, I’ll be sticking to that. Wondering if there are any thoughts? Thank you

Do not attempt to create random numbers in a query. Doing so will lead to disappointment and problems.

Fauna achieves its distributed consistency in two phases:

  1. Transactions are ordered in the transaction log by a consensus of log-handling nodes in a region group.
  2. Query-handling nodes then process the transaction log. At this point, processing must be deterministic so that all nodes perform the same operations: their side effects must be equivalent at all times.

Instead, create the random values you need in your application logic, and embed those in your queries. You still get the randomness you require without breaking the determinism needed for query processing.

1 Like

Please forgive me if I am going down the same path, one more try, maybe it is different:

Now()'s timestamp “2022-08-15T18:09:06.805753Z” the last 5 digits are random enough serve as a seed to access my Things in a random manner. Would this violate any of the deterministic requirements?

Provided that your use of Now()'s output is used to compute a seed within application logic, and not within a query, that should be fine.

1 Like

Ok, I hear you loud and clear. As long as the randomness comes from outside of an FQL query then things should be ok.

My plan would be to supply the random number from application logic first, then give that to the query as you suggested above. Thank you!

This topic was automatically closed 2 days after the last reply. New replies are no longer allowed.