public async Task StoreAsync(PersistedGrant grant) { if (grant == null) { throw new ArgumentNullException(nameof(grant)); } try { var data = grant.Serialize(); var grantKey = GetKey(grant.Key); var expiresIn = grant.Expiration - clock.UtcNow; if (!string.IsNullOrEmpty(grant.SubjectId)) { var setKey = GetSetKey(grant.SubjectId, grant.ClientId, grant.Type); var setKeyforSubject = GetSetKey(grant.SubjectId); var setKeyforClient = GetSetKey(grant.SubjectId, grant.ClientId); //get keys to clean, if any var(_, keysToDelete) = await GetGrants(setKeyforSubject).ConfigureAwait(false); var transaction = database.CreateTransaction(); transaction.StringSetAsync(grantKey, data, expiresIn); transaction.SetAddAsync(setKeyforSubject, grantKey); transaction.SetAddAsync(setKeyforClient, grantKey); transaction.SetAddAsync(setKey, grantKey); transaction.KeyExpireAsync(setKey, expiresIn); if (keysToDelete.Any())//cleanup sets while persisting new grant { transaction.SetRemoveAsync(setKey, keysToDelete.ToArray()); transaction.SetRemoveAsync(setKeyforSubject, keysToDelete.ToArray()); transaction.SetRemoveAsync(setKeyforClient, keysToDelete.ToArray()); } await transaction.ExecuteAsync().ConfigureAwait(false); } else { await database.StringSetAsync(grantKey, data, expiresIn).ConfigureAwait(false); } logger.LogDebug($"grant for subject {grant.SubjectId}, clientId {grant.ClientId}, grantType {grant.Type} persisted successfully"); } catch (Exception ex) { logger.LogWarning($"exception storing persisted grant to Redis database for subject {grant.SubjectId}, clientId {grant.ClientId}, grantType {grant.Type} : {ex.Message}"); } }