Skip to content

Commit 2f70168

Browse files
AnkoSklChaosEngine
authored andcommitted
Fix deadlock caused by mix of sync and async code execution (#15)
1 parent 3c9bcce commit 2f70168

1 file changed

Lines changed: 19 additions & 9 deletions

File tree

src/Pomelo.Extensions.Caching.MySql/MySqlCache.cs

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ public byte[] Get(string key)
102102

103103
var value = _dbOperations.GetCacheItem(key);
104104

105-
ScanForExpiredItemsIfRequired().Wait();
105+
ScanForExpiredItemsIfRequired();
106106

107107
return value;
108108
}
@@ -117,7 +117,7 @@ public byte[] Get(string key)
117117
token.ThrowIfCancellationRequested();
118118

119119
var value = await _dbOperations.GetCacheItemAsync(key, token: token);
120-
await ScanForExpiredItemsIfRequired();
120+
await ScanForExpiredItemsIfRequiredAsync();
121121

122122
return value;
123123
}
@@ -131,7 +131,7 @@ public void Refresh(string key)
131131

132132
_dbOperations.RefreshCacheItem(key);
133133

134-
ScanForExpiredItemsIfRequired().Wait();
134+
ScanForExpiredItemsIfRequired();
135135
}
136136

137137
public async Task RefreshAsync(string key, CancellationToken token = default(CancellationToken))
@@ -145,7 +145,7 @@ public void Refresh(string key)
145145

146146
await _dbOperations.RefreshCacheItemAsync(key, token: token);
147147

148-
await ScanForExpiredItemsIfRequired();
148+
await ScanForExpiredItemsIfRequiredAsync();
149149
}
150150

151151
public void Remove(string key)
@@ -157,7 +157,7 @@ public void Remove(string key)
157157

158158
_dbOperations.DeleteCacheItem(key);
159159

160-
ScanForExpiredItemsIfRequired().Wait();
160+
ScanForExpiredItemsIfRequired();
161161
}
162162

163163
public async Task RemoveAsync(string key, CancellationToken token = default(CancellationToken))
@@ -171,7 +171,7 @@ public void Remove(string key)
171171

172172
await _dbOperations.DeleteCacheItemAsync(key, token: token);
173173

174-
await ScanForExpiredItemsIfRequired();
174+
await ScanForExpiredItemsIfRequiredAsync();
175175
}
176176

177177
public void Set(string key, byte[] value, DistributedCacheEntryOptions options)
@@ -195,7 +195,7 @@ public void Set(string key, byte[] value, DistributedCacheEntryOptions options)
195195

196196
_dbOperations.SetCacheItem(key, value, options);
197197

198-
ScanForExpiredItemsIfRequired().Wait();
198+
ScanForExpiredItemsIfRequired();
199199
}
200200

201201
public async Task SetAsync(
@@ -225,12 +225,12 @@ public async Task SetAsync(
225225

226226
await _dbOperations.SetCacheItemAsync(key, value, options, token);
227227

228-
await ScanForExpiredItemsIfRequired();
228+
await ScanForExpiredItemsIfRequiredAsync();
229229
}
230230

231231
// Called by multiple actions to see how long it's been since we last checked for expired items.
232232
// If sufficient time has elapsed then a scan is initiated on a background task.
233-
private async Task ScanForExpiredItemsIfRequired()
233+
private async Task ScanForExpiredItemsIfRequiredAsync()
234234
{
235235
var utcNow = _systemClock.UtcNow;
236236
// TODO: Multiple threads could trigger this scan which leads to multiple calls to database.
@@ -246,6 +246,16 @@ private async Task ScanForExpiredItemsIfRequired()
246246
}
247247
}
248248

249+
private void ScanForExpiredItemsIfRequired()
250+
{
251+
var utcNow = _systemClock.UtcNow;
252+
if ((utcNow - _lastExpirationScan) > _expiredItemsDeletionInterval)
253+
{
254+
_lastExpirationScan = utcNow;
255+
_deleteExpiredCachedItemsDelegate.Invoke();
256+
}
257+
}
258+
249259
private void GetOptions(ref DistributedCacheEntryOptions options)
250260
{
251261
if (!options.AbsoluteExpiration.HasValue

0 commit comments

Comments
 (0)