/// <summary> /// 内容に変更があっても、表示の更新及びChanged イベントが発生しない様にします。 /// </summary> public System.IDisposable Lock() { if (this.locked == 0) { this.sbuffer = new System.Text.StringBuilder(); } this.locked++; return(lock_rel ?? (lock_rel = new LockReleaser(this))); }
public void TestDoubleRelease() { using (AsyncLocker locker = new AsyncLocker()) { using (LockReleaser l = locker.Lock()) { l.Dispose(); } } }
internal void DequeueAndEnter(LockReleaser releaser) { Debug.Assert(Monitor.IsEntered(_context._syncObj), "Выполнять можно только в блокировке"); Debug.Assert(_queue.Count > 0); // Взять первый поток в очереди. var tcs = _queue.Dequeue(); bool success = tcs.TrySetResult(releaser); Debug.Assert(success); }
public async Task <ManagedToken> AddManagedTokenAsync(string key, ManagedToken managedToken) { LockReleaser releaser = await _lock.Lock(new TimeSpan(0, 0, 30)); try { return(await AddUnSafeManagedTokenAsync(key, managedToken)); } finally { releaser.Dispose(); } }
public async Task RemoveManagedTokenAsync(string key) { LockReleaser releaser = await _lock.Lock(new TimeSpan(0, 0, 30)); try { await _tokenStorage.RemoveManagedTokenAsync(key); } finally { releaser.Dispose(); } }
public async Task RemoveConcurrentManagedTokenAsync(string key) { LockReleaser releaser = await _lock.Lock(new TimeSpan(0, 0, 30)); try { _managedTokens.TryRemove(key, out _); } finally { releaser.Dispose(); } }
public async Task RemoveAllConcurrentManagedTokenAsync() { LockReleaser releaser = await _lock.Lock(new TimeSpan(0, 0, 30)); try { _managedTokens.Clear(); } finally { releaser.Dispose(); } }
public async Task AddCredentialsAsync(string key, OAuth2Credentials creds) { LockReleaser releaser = await _lock.Lock(new TimeSpan(0, 0, 30)); try { var memKey = $"{PreKeyName}.{key}"; _memoryCache.Set(memKey, creds); } finally { releaser.Dispose(); } }
public async Task <ManagedToken> AddConcurrentManagedTokenAsync(string key, ManagedToken managedToken) { LockReleaser releaser = await _lock.Lock(new TimeSpan(0, 0, 30)); try { managedToken.StartDate = DateTimeOffset.UtcNow; managedToken.ExpirationDate = managedToken.StartDate.AddSeconds(managedToken.ExpiresIn); _managedTokens[key] = managedToken; return(managedToken); } finally { releaser.Dispose(); } }
public async Task <OAuth2Credentials> GetOAuth2CredentialsAsync(string key) { LockReleaser releaser = await _lock.Lock(new TimeSpan(0, 0, 30)); try { var memKey = $"{PreKeyName}.{key}"; OAuth2Credentials creds; if (_memoryCache.TryGetValue(memKey, out creds)) { if (creds.DiscoveryDocumentResponse == null) { // pull it. HttpClient client = null; if (string.IsNullOrEmpty(creds.HttpClientName)) { client = new HttpClient(); } else { client = _clientFactory.CreateClient(creds.HttpClientName); } var disco = await client.GetDiscoveryDocumentAsync(creds.Authority); if (disco.IsError) { throw new Exception(disco.Error); } creds.DiscoveryDocumentResponse = disco; _memoryCache.Set(memKey, creds); } return(creds); } _logger.LogError($"OAuth2 Credentials is not in cache: key={key}"); return(null); } catch (Exception ex) { _logger.LogError(ex.Message); return(null); } finally { releaser.Dispose(); } }
private async Task <ManagedToken> GetConcurrentManagedTokenAsync(string key) { LockReleaser releaser = await _lock.Lock(new TimeSpan(0, 0, 30)); try { ManagedToken managedToken; if (_managedTokens.TryGetValue(key, out managedToken)) { return(managedToken); } return(null); } finally { releaser.Dispose(); } }
public async Task <string> AcquireAccessTokenAsync() { var utcNow = DateTime.UtcNow; int result = DateTime.Compare(_expiration, utcNow); if (string.IsNullOrWhiteSpace(_token) || result <= 0) { LockReleaser releaser = await _lock.Lock(new TimeSpan(0, 0, 30)); try { var clientId = Environment.GetEnvironmentVariable("ARM_CLIENT_ID"); var clientSecret = Environment.GetEnvironmentVariable("ARM_CLIENT_SECRET"); var subscriptionId = Environment.GetEnvironmentVariable("ARM_SUBSCRIPTION_ID"); var tenantId = Environment.GetEnvironmentVariable("ARM_TENANT_ID"); var client = new HttpClient(); var response = await client.RequestTokenAsync(new TokenRequest { Address = $"https://login.microsoftonline.com/{tenantId}/oauth2/token?api-version=1.0", GrantType = "client_credentials", ClientId = clientId, ClientSecret = clientSecret, Parameters = { { "resource", "https://management.core.windows.net/" } } }); _token = response.AccessToken; _expiration = DateTime.UtcNow.AddSeconds(response.ExpiresIn - 60); // 1 minute grace. } finally { releaser.Dispose(); } } return(_token); }
public async Task <OpenIdConnectConfiguration> GetOpenIdConnectConfigurationAsync(string issuer) { LockReleaser releaser = await _lock.Lock(new TimeSpan(0, 0, 30)); try { OpenIdConnectConfiguration openIdConfig; if (_cache.TryGetValue(issuer, out openIdConfig)) { return(openIdConfig); } IConfigurationManager <OpenIdConnectConfiguration> configurationManager = new ConfigurationManager <OpenIdConnectConfiguration>($"{issuer}/.well-known/openid-configuration", new OpenIdConnectConfigurationRetriever()); openIdConfig = await configurationManager.GetConfigurationAsync(CancellationToken.None); _cache.Set(issuer, openIdConfig, new TimeSpan(1, 0, 0, 0)); // cache for 1 day return(openIdConfig); } finally { releaser.Dispose(); } }
public void ReleaseLocks() { if (this.ContextLocks != null) { foreach (var entityId in this.ContextLocks) { var instance = new OrchestrationInstance() { InstanceId = EntityId.GetSchedulerIdFromEntityId(entityId) }; var message = new ReleaseMessage() { ParentInstanceId = this.InstanceId, LockRequestId = this.LockRequestId, }; this.SendEntityMessage(instance, "release", message); } this.ContextLocks = null; this.lockReleaser = null; this.LockRequestId = null; } }
public AsyncLock() { _semaphore = new SemaphoreSlim(1, 1); _lockReleaser = new LockReleaser(_semaphore); }
public async Task <ManagedToken> GetManagedTokenAsync(string key, bool forceRefresh = false, CancellationToken cancellationToken = default) { LockReleaser releaser = await _lock.Lock(new TimeSpan(0, 0, 30)); try { var managedToken = await GetUnSafeManagedTokenAsync(key); if (managedToken == null) { return(null); } if (string.IsNullOrEmpty(managedToken.RefreshToken)) { if (forceRefresh) { var func = _customTokenRequest.GetTokenRequestFunc(managedToken.RequestFunctionKey); if (func == null) { throw new Exception($"forceRefresh requested, but no token request function exists. RequestFunctionKey={managedToken.RequestFunctionKey}"); } var mT = await func(managedToken, _serviceProvider, _oAuth2CredentialManager, cancellationToken); if (mT == null) { throw new Exception($"Custom Token Request function return a null. RequestFunctionKey={managedToken.RequestFunctionKey}"); } managedToken = await AddUnSafeManagedTokenAsync(key, mT); } return(managedToken); } DateTimeOffset now = DateTimeOffset.UtcNow; if (!forceRefresh) { if (managedToken.ExpirationDate > now || string.IsNullOrWhiteSpace(managedToken.RefreshToken)) { return(managedToken); } } var creds = await _oAuth2CredentialManager.GetOAuth2CredentialsAsync(managedToken.CredentialsKey); if (creds == null) { throw new Exception($"GetOAuth2CredentialsAsync failed: key={managedToken.CredentialsKey}"); } var client = new HttpClient(); var response = await client.RequestRefreshTokenAsync(new RefreshTokenRequest { Address = creds.DiscoveryDocumentResponse.TokenEndpoint, ClientId = creds.ClientId, ClientSecret = creds.ClientSecret, RefreshToken = managedToken.RefreshToken }); if (response.IsError) { // REMOVE the managed token, because the refresh failed await _tokenStorage.RemoveManagedTokensAsync(); throw new Exception($"RequestRefreshTokenAsync failed for key={key}", new Exception(response.Error)); } managedToken.RefreshToken = response.RefreshToken; managedToken.AccessToken = response.AccessToken; managedToken.ExpiresIn = response.ExpiresIn; managedToken = await AddUnSafeManagedTokenAsync(key, managedToken); return(managedToken); } catch (Exception ex) { _logger.LogError(ex.Message); return(null); } finally { releaser.Dispose(); } }
/// <inheritdoc/> async Task <IDisposable> IDurableOrchestrationContext.LockAsync(params EntityId[] entities) { this.ThrowIfInvalidAccess(); if (this.ContextLocks != null) { throw new LockingRulesViolationException("Cannot acquire more locks when already holding some locks."); } if (entities == null || entities.Length == 0) { throw new ArgumentException("The list of entities to lock must not be null or empty.", nameof(entities)); } // acquire the locks in a globally fixed order to avoid deadlocks Array.Sort(entities); // remove duplicates if necessary. Probably quite rare, so no need to optimize more. for (int i = 0; i < entities.Length - 1; i++) { if (entities[i].Equals(entities[i + 1])) { entities = entities.Distinct().ToArray(); break; } } // use a deterministically replayable unique ID for this lock request, and to receive the response var lockRequestId = this.NewGuid(); // All the entities in entity[] need to be locked, but to avoid deadlock, the locks have to be acquired // sequentially, in order. So, we send the lock request to the first entity; when the first lock // is granted by the first entity, the first entity will forward the lock request to the second entity, // and so on; after the last entity grants the last lock, a response is sent back here. // send lock request to first entity in the lock set var target = new OrchestrationInstance() { InstanceId = EntityId.GetSchedulerIdFromEntityId(entities[0]) }; var request = new RequestMessage() { Id = lockRequestId, ParentInstanceId = this.InstanceId, LockSet = entities, Position = 0, }; this.LockRequestId = lockRequestId.ToString(); this.SendEntityMessage(target, "op", request); // wait for the response from the last entity in the lock set await this.WaitForExternalEvent <ResponseMessage>(this.LockRequestId, "LockAcquisitionCompleted"); this.ContextLocks = new List <EntityId>(entities); // return an IDisposable that releases the lock this.lockReleaser = new LockReleaser(this); return(this.lockReleaser); }