Note that there are some explanatory texts on larger screens.

plurals
  1. POHow to make a threadsafe call to a 3rd party API (OAuth)?
    primarykey
    data
    text
    <p>I'm calling a 3rd party API that uses OAuth for authentication, and I'm wondering how to make this threadsafe:</p> <pre><code>var token = _tokenService.GetCurrentToken(); // eg token could be "ABCDEF" var newToken = oauth.RenewAccessToken(token); // eg newToken could be "123456" _tokenService.UpdateCurrentToken(newToken); // save newToken to the database </code></pre> <p>What this does is to use the previous token every time <code>RenewAccessToken()</code> is called. But there is a problem if two users initiate this at the same time (two different threads will run the code at the same time), and we end up with that code executed in this order:</p> <pre><code>[Thread 1] var token = _tokenService.GetCurrentToken(); // returns "ABCDEF" [Thread 2] var token = _tokenService.GetCurrentToken(); // returns "ABCDEF" [Thread 1] var newToken = oauth.RenewAccessToken("ABCDEF"); // returns "123456" [Thread 2] var newToken = oauth.RenewAccessToken("ABCDEF"); // throws an invalid token exception </code></pre> <p>What has happened is that in thread 2, it should actually be calling <code>oauth.RenewAccessToken("123456");</code> (because that is the latest token value. But the latest token hasnt even been saved to the database yet, so thread 2 always has the wrong value for current token.</p> <p>What can I do to fix this?</p> <p>Edit: It has been suggested to use a lock like this:</p> <pre><code>private object tokenLock = new object(); lock(tokenLock) { var token = _tokenService.GetCurrentToken(); var newToken = oauth.RenewAccessToken(token); _tokenService.UpdateCurrentToken(newToken); } </code></pre> <p>Edit 2: The lock didn't actually work anyway, this is from my logs:</p> <pre><code>[43 22:38:26:9963] Renewing now using token JHCBTW1ZI96FF [36 22:38:26:9963] Renewing now using token JHCBTW1ZI96FF [36 22:38:29:1790] OAuthException exception </code></pre> <p>The first number is the thread id and the second is a timestamp. Both threads executed at the exact same time down to the milliseconds. I don't know why the lock failed to stop thread 36 until after thread 43 had finished.</p> <p>Edit 3: And again, this time after changing the <code>object tokenLock</code> to be a class variable instead of a local variable, the lock did not work.</p> <pre><code>[25 10:53:58:3870] Renewing now using token N95984XVORY [9 10:53:58:3948] Renewing now using token N95984XVORY [9 10:54:55:7981] OAuthException exception </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload