private async Task <ParatextAccessLock> GetParatextAccessLock(string userId) { SemaphoreSlim semaphore = _tokenRefreshSemaphores.GetOrAdd(userId, (string key) => new SemaphoreSlim(1, 1)); await semaphore.WaitAsync(); try { Attempt <UserSecret> attempt = await _userSecretRepository.TryGetAsync(userId); if (!attempt.TryResult(out UserSecret userSecret)) { throw new DataNotFoundException("Could not find user secrets for " + userId); } if (!userSecret.ParatextTokens.ValidateLifetime()) { Tokens refreshedUserTokens = await _jwtTokenHelper.RefreshAccessTokenAsync(_paratextOptions.Value, userSecret.ParatextTokens, _registryClient); userSecret = await _userSecretRepository.UpdateAsync(userId, b => b.Set(u => u.ParatextTokens, refreshedUserTokens)); } return(new ParatextAccessLock(semaphore, userSecret)); } catch { // If an exception is thrown between awaiting the semaphore and returning the ParatextAccessLock, the // caller of the method will not get a reference to a ParatextAccessLock and can't release the semaphore. semaphore.Release(); throw; } }
private async Task RefreshAccessTokenAsync(UserSecret userSecret) { ParatextOptions options = _paratextOptions.Value; userSecret.ParatextTokens = await _jwtTokenHelper.RefreshAccessTokenAsync(options, userSecret.ParatextTokens, _registryClient); await _userSecretRepository.UpdateAsync(userSecret, b => b.Set(u => u.ParatextTokens, userSecret.ParatextTokens)); }