Optimistic Concurrency Control in the Okta API - ETags


#1

I use Okta as a persistent store for my user and group entities. In my system, there are multiple services that update these entities in parallel. Without some sort of optimistic concurrency control such as ETags, I am worried I will have to synchronize these updates on my own.

I wrote a simple console app against the user api and could not find any ETag headers in the GET responses. I have also confirmed that I am at risk of a concurrency bug. For Example:

User_Initial
{
    FirstName: Foo
    LastName: Bar
}

Process1_GetUser

Process2_GetUser

Process1_UpdateUser: FirstName = Foo2

Process2_UpdateUser: LastName = Bar2

User_Final
{
    FirstName: Foo
    LastName: Bar2
}

All requests return 200, but I have lost the update that process 1 did to ‘FirstName’.

I have considered two solutions to this problem

  1. Do not process updates in parallel.

    • Add a custom attribute to the entity and treat it as an ETag.
    • Put all updates into a single queue for processing (if it is a partitioned queue, all updates for a given user need to go to the same partition of the queue. All we really care about here is that updates to a single user are serialized, not updates to all users).
    • To process entity updates, peek the top of the update request queue, and GET the entity from Okta
      • If the ETag attributes do NOT match, fail the update request. The requestor will have to GET the entity again and re-queue the update with the current ETag attribute
      • If the ETag attributes do match, apply the updated attributes to the entity, change the ETag attribute to a new value, and update the entity in Okta
      • Delete the update request off of the queue…it has been processed
  2. I could add a leasing mechanism.

    • Add a custom attribute to the entity and treat it as an ETag
    • Each update request acquires a lease on the entity being updated.
    • If the lease is taken, fail the update request. The requestor should GET the entity again and retry the update.
    • If the lease is NOT taken, GET the entity from Okta.
      • If the ETag attributes do NOT match, fail the update request. The requestor will have to GET the entity again and retry the update
      • If the ETag attributes do match, apply the updated attributes to the entity, change the ETag attribute to a new value, and update the entity in Okta
      • Release the lease on the entity that was just updated

NOTE: If the process crashes while the lease is taken, the lease will eventually expire, and other update requests can fight for the next lease.

Neither of these solutions are particularly scalable, and would add a lot more room for bugs in my code. Is there something that I am missing? Is there a solution for this scenario?

Recommendations are welcome
Thanks


#2

ETags would definitely be the solution to the issue.

We are adding caching to the Okta SDKs. This should help with some of these issues if you connect everythign to a distributed cache, like memcached or redis. We are aiming for the work to be done sometime in Feb. You would still need to do your updates in serial though.

I’m going to move this to feature requests. I do have this on my radar, I don’t have any timelines for ETags though.


#3

is the Etags are supported in Okta org? If Yes, Do we need to enable it at org level?