-
Notifications
You must be signed in to change notification settings - Fork 19
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement Asynchronous Operations for Cache Repositories #562
base: main
Are you sure you want to change the base?
Changes from all commits
93243a0
587e44e
545a52a
065e147
79d359f
881bf37
0c78634
bb6897e
51e123d
1636cd4
24e874f
98a4bf0
c2f6569
b5cba17
8c09fd3
0a57595
abb8458
1e436b6
e56a544
c1ce45f
f0266bd
a3abef8
9ab6038
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -38,16 +38,16 @@ | |||||
/// Finally, it converts the filtered results to a list and returns the count of those documents. | ||||||
/// This is useful for determining how many valid instances of a specific document type exist in the database. | ||||||
/// </remarks> | ||||||
public int GetDocCount<T>() | ||||||
public async Task<int> GetDocCountAsync<T>() | ||||||
Check warning Code scanning / Sonarcsharp (reported by Codacy) Refactor this method to use all type parameters in the parameter list to enable type inference. Warning
Refactor this method to use all type parameters in the parameter list to enable type inference.
|
||||||
where T : CouchDBCacheDocument | ||||||
{ | ||||||
return ResolveDatabase<T>().Where(x => x.Id != null).ToList().Count; | ||||||
return (await ResolveDatabaseAsync<T>()).Where(x => x.Id != null).ToList().Count; | ||||||
} | ||||||
|
||||||
/// <inheritdoc /> | ||||||
public void Clear() | ||||||
public async Task ClearAsync() | ||||||
{ | ||||||
Clear<CouchDBCacheDocument>(); | ||||||
await Task.Run(() => ClearAsync<CouchDBCacheDocument>()); | ||||||
} | ||||||
|
||||||
/// <summary> | ||||||
|
@@ -62,12 +62,12 @@ | |||||
/// This method does not return any value and modifies the state of the database by removing documents. | ||||||
/// </remarks> | ||||||
/// <exception cref="Exception">Thrown when an error occurs during the deletion process, unless exceptions are suppressed.</exception> | ||||||
public void Clear<T>() | ||||||
public async Task ClearAsync<T>() | ||||||
where T : CouchDBCacheDocument | ||||||
{ | ||||||
try | ||||||
{ | ||||||
var db = ResolveDatabase<T>(); | ||||||
var db = await ResolveDatabaseAsync<T>(); | ||||||
var docs = db.Where(x => x.Id != null).ToList(); | ||||||
var tasks = new List<Task>(docs.Count); | ||||||
|
||||||
|
@@ -76,7 +76,7 @@ | |||||
tasks.Add(db.DeleteAsync(doc)); | ||||||
} | ||||||
|
||||||
Task.WaitAll(tasks.ToArray()); | ||||||
await Task.Run(() => tasks.ToArray()); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use In the Apply this diff to correct the implementation: - await Task.Run(() => tasks.ToArray());
+ await Task.WhenAll(tasks); 📝 Committable suggestion
Suggested change
|
||||||
} | ||||||
catch (Exception e) | ||||||
{ | ||||||
|
@@ -90,14 +90,14 @@ | |||||
} | ||||||
|
||||||
/// <inheritdoc /> | ||||||
public T Get<T>(string key) | ||||||
public async Task<T> GetAsync<T>(string key) | ||||||
Check warning Code scanning / Sonarcsharp (reported by Codacy) Refactor this method to use all type parameters in the parameter list to enable type inference. Warning
Refactor this method to use all type parameters in the parameter list to enable type inference.
|
||||||
{ | ||||||
if (!typeof(CouchDBCacheDocument).IsAssignableFrom(typeof(T))) | ||||||
{ | ||||||
return default; | ||||||
} | ||||||
|
||||||
return (T)(object)GetSpecific<CouchDBCacheDocument>(key); | ||||||
return (T)(object)await GetSpecificAsync<CouchDBCacheDocument>(key); | ||||||
Comment on lines
+93
to
+100
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Refactor The method 🧰 Tools🪛 GitHub Check: Sonarcsharp (reported by Codacy)
|
||||||
} | ||||||
|
||||||
/// <summary> | ||||||
|
@@ -111,37 +111,38 @@ | |||||
/// </returns> | ||||||
/// <remarks> | ||||||
/// This method checks if the specified type <typeparamref name="T"/> is assignable from <see cref="CouchDBCacheDocument"/>. | ||||||
/// If it is, it calls the method <see cref="GetSpecific{CouchDBCacheDocument}"/> to retrieve the cached document associated with the provided keys. | ||||||
/// If it is, it calls the method <see cref="GetSpecificAsync{CouchDBCacheDocument}"/> to retrieve the cached document associated with the provided keys. | ||||||
/// If the type is not assignable, it returns the default value for that type, which could be null for reference types or zero for numeric types. | ||||||
/// This method is useful for retrieving cached data in a type-safe manner, ensuring that only compatible types are processed. | ||||||
/// </remarks> | ||||||
public T Get<T>(string key, string subKey) | ||||||
public async Task<T> GetAsync<T>(string key, string subKey) | ||||||
Check warning Code scanning / Sonarcsharp (reported by Codacy) Refactor this method to use all type parameters in the parameter list to enable type inference. Warning
Refactor this method to use all type parameters in the parameter list to enable type inference.
|
||||||
{ | ||||||
if (!typeof(CouchDBCacheDocument).IsAssignableFrom(typeof(T))) | ||||||
{ | ||||||
return default; | ||||||
} | ||||||
|
||||||
return (T)(object)GetSpecific<CouchDBCacheDocument>(key, subKey); | ||||||
return (T)(object)await Task.FromResult(GetSpecificAsync<CouchDBCacheDocument>(key, subKey)); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Simplify redundant use of At line 125, Apply this diff to simplify the code: - return (T)(object)await Task.FromResult(GetSpecificAsync<CouchDBCacheDocument>(key, subKey));
+ return (T)(object)await GetSpecificAsync<CouchDBCacheDocument>(key, subKey); 📝 Committable suggestion
Suggested change
|
||||||
} | ||||||
|
||||||
|
||||||
/// <summary> | ||||||
/// Gets from a class specified database instead of the general <see cref="CouchDBCacheDocument"/> database. | ||||||
/// </summary> | ||||||
/// <typeparam name="T">Type T with base type <see cref="CouchDBCacheDocument"/>.</typeparam> | ||||||
/// <param name="key">A uniquely identifiable key to get document from the specified database.</param> | ||||||
/// <returns>The document if found.</returns> | ||||||
/// <exception cref="InvalidOperationException">Thrown in case the operation fails.</exception> | ||||||
public T GetSpecific<T>(string key) | ||||||
public async Task<T> GetSpecificAsync<T>(string key) | ||||||
Check warning Code scanning / Sonarcsharp (reported by Codacy) Refactor this method to use all type parameters in the parameter list to enable type inference. Warning
Refactor this method to use all type parameters in the parameter list to enable type inference.
|
||||||
where T : CouchDBCacheDocument | ||||||
{ | ||||||
try | ||||||
{ | ||||||
var doc = ResolveDatabase<T>().Where(x => x.Key == key).FirstOrDefault(); | ||||||
var doc = (await ResolveDatabaseAsync<T>()).Where(x => x.Key == key).FirstOrDefault(); | ||||||
|
||||||
if (doc != default && doc.ExpiresAt != default && doc.ExpiresAt <= DateTime.UtcNow) | ||||||
{ | ||||||
RemoveSpecific<T>(key); | ||||||
await RemoveSpecificAsync<T>(key); | ||||||
return default; | ||||||
} | ||||||
|
||||||
|
@@ -175,18 +176,16 @@ | |||||
/// If no document is found and no exceptions are thrown, an <see cref="InvalidOperationException"/> is thrown indicating that the item could not be retrieved. | ||||||
/// </remarks> | ||||||
/// <exception cref="InvalidOperationException">Thrown when unable to retrieve the item with the specified key and sub key.</exception> | ||||||
public T GetSpecific<T>(string key, string subKey) | ||||||
public async Task<T> GetSpecificAsync<T>(string key, string subKey) | ||||||
Check warning Code scanning / Sonarcsharp (reported by Codacy) Refactor this method to use all type parameters in the parameter list to enable type inference. Warning
Refactor this method to use all type parameters in the parameter list to enable type inference.
|
||||||
where T : CouchDBCacheDocument | ||||||
{ | ||||||
try | ||||||
{ | ||||||
var doc = ResolveDatabase<T>() | ||||||
.Where(x => x.Key == key && x.SubKey == subKey) | ||||||
.FirstOrDefault(); | ||||||
var doc = (await ResolveDatabaseAsync<T>()).Where(x => x.Key == key && x.SubKey == subKey).FirstOrDefault(); | ||||||
|
||||||
if (doc != default && doc.ExpiresAt != default && doc.ExpiresAt <= DateTime.UtcNow) | ||||||
{ | ||||||
RemoveSpecific<T>(key, subKey); | ||||||
await RemoveSpecificAsync<T>(key, subKey); | ||||||
return default; | ||||||
} | ||||||
|
||||||
|
@@ -208,10 +207,7 @@ | |||||
} | ||||||
|
||||||
/// <inheritdoc /> | ||||||
public void Remove(string key) | ||||||
{ | ||||||
RemoveSpecific<CouchDBCacheDocument>(key); | ||||||
} | ||||||
public async Task RemoveAsync(string key) => await RemoveSpecificAsync<CouchDBCacheDocument>(key); | ||||||
|
||||||
/// <summary> | ||||||
/// Removes a specific entry from the cache based on the provided key and subKey. | ||||||
|
@@ -224,17 +220,14 @@ | |||||
/// It is important to ensure that both keys are correctly specified to successfully remove the intended entry from the cache. | ||||||
/// If the specified entry does not exist, no action will be taken, and no exceptions will be thrown. | ||||||
/// </remarks> | ||||||
public void Remove(string key, string subKey) | ||||||
{ | ||||||
RemoveSpecific<CouchDBCacheDocument>(key, subKey); | ||||||
} | ||||||
public async Task RemoveAsync(string key, string subKey) => await RemoveSpecificAsync<CouchDBCacheDocument>(key, subKey); | ||||||
|
||||||
/// <summary> | ||||||
/// Removes from a class specified database instead of the general <see cref="CouchDBCacheDocument"/> database. | ||||||
/// </summary> | ||||||
/// <typeparam name="T">Type T with base type <see cref="CouchDBCacheDocument"/>.</typeparam> | ||||||
/// <param name="key">A uniquely identifiable key to remove document from the specified database.</param> | ||||||
public void RemoveSpecific<T>(string key) | ||||||
public async Task RemoveSpecificAsync<T>(string key) | ||||||
Check warning Code scanning / Sonarcsharp (reported by Codacy) Refactor this method to use all type parameters in the parameter list to enable type inference. Warning
Refactor this method to use all type parameters in the parameter list to enable type inference.
|
||||||
where T : CouchDBCacheDocument | ||||||
{ | ||||||
try | ||||||
|
@@ -244,7 +237,7 @@ | |||||
|
||||||
if (doc != default) | ||||||
{ | ||||||
db.DeleteAsync(doc).Wait(); | ||||||
await db.DeleteAsync(doc); | ||||||
} | ||||||
} | ||||||
catch (Exception e) | ||||||
|
@@ -271,7 +264,7 @@ | |||||
/// <see cref="ShouldPropagateExceptions"/>. If exceptions are not propagated, they are logged using the | ||||||
/// <see cref="LogConsumer"/>. This method does not return any value. | ||||||
/// </remarks> | ||||||
public void RemoveSpecific<T>(string key, string subKey) | ||||||
public async Task RemoveSpecificAsync<T>(string key, string subKey) | ||||||
Check warning Code scanning / Sonarcsharp (reported by Codacy) Refactor this method to use all type parameters in the parameter list to enable type inference. Warning
Refactor this method to use all type parameters in the parameter list to enable type inference.
|
||||||
where T : CouchDBCacheDocument | ||||||
{ | ||||||
try | ||||||
|
@@ -281,7 +274,7 @@ | |||||
|
||||||
if (doc != default) | ||||||
{ | ||||||
db.DeleteAsync(doc).Wait(); | ||||||
await db.DeleteAsync(doc); | ||||||
} | ||||||
} | ||||||
catch (Exception e) | ||||||
|
@@ -296,14 +289,14 @@ | |||||
} | ||||||
|
||||||
/// <inheritdoc /> | ||||||
public void Set<T>(T value, string key, TimeSpan? ttl = null) | ||||||
public async Task SetAsync<T>(T value, string key, TimeSpan? ttl = null) | ||||||
Check warning Code scanning / Sonarcsharp (reported by Codacy) Use the overloading mechanism instead of the optional parameters. Warning
Use the overloading mechanism instead of the optional parameters.
|
||||||
{ | ||||||
if (!typeof(CouchDBCacheDocument).IsAssignableFrom(typeof(T))) | ||||||
{ | ||||||
return; | ||||||
} | ||||||
|
||||||
SetSpecific((CouchDBCacheDocument)(object)value, key, ttl); | ||||||
await SetSpecificAsync((CouchDBCacheDocument)(object)value, key, ttl); | ||||||
Comment on lines
+292
to
+299
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Use method overloading instead of optional parameters The method 🧰 Tools🪛 GitHub Check: Sonarcsharp (reported by Codacy)
|
||||||
} | ||||||
|
||||||
/// <summary> | ||||||
|
@@ -316,17 +309,17 @@ | |||||
/// <remarks> | ||||||
/// This method checks if the provided type <typeparamref name="T"/> is assignable from <see cref="CouchDBCacheDocument"/>. | ||||||
/// If it is not, the method returns without performing any action. | ||||||
/// If the type is valid, it calls the <see cref="SetSpecific"/> method to set the value in the cache. | ||||||
/// If the type is valid, it calls the <see cref="SetSpecificAsync"/> method to set the value in the cache. | ||||||
/// This allows for type-safe caching of documents that inherit from <see cref="CouchDBCacheDocument"/>. | ||||||
/// </remarks> | ||||||
public void Set<T>(T value, string key, string subKey) | ||||||
public async Task SetAsync<T>(T value, string key, string subKey) | ||||||
{ | ||||||
if (!typeof(CouchDBCacheDocument).IsAssignableFrom(typeof(T))) | ||||||
{ | ||||||
return; | ||||||
} | ||||||
|
||||||
SetSpecific((CouchDBCacheDocument)(object)value, key, subKey); | ||||||
await SetSpecificAsync((CouchDBCacheDocument)(object)value, key, subKey); | ||||||
} | ||||||
|
||||||
/// <summary> | ||||||
|
@@ -336,7 +329,7 @@ | |||||
/// <param name="value">The value of type T to be persisted.</param> | ||||||
/// <param name="key">A uniquely identifiable key to remove document from the specified database.</param> | ||||||
/// <param name="ttl">How long the value should be stored.</param> | ||||||
public void SetSpecific<T>(T value, string key, TimeSpan? ttl = null) | ||||||
public async Task SetSpecificAsync<T>(T value, string key, TimeSpan? ttl = null) | ||||||
Check warning Code scanning / Sonarcsharp (reported by Codacy) Use the overloading mechanism instead of the optional parameters. Warning
Use the overloading mechanism instead of the optional parameters.
|
||||||
where T : CouchDBCacheDocument | ||||||
{ | ||||||
try | ||||||
|
@@ -349,7 +342,7 @@ | |||||
value.ExpiresAt = DateTime.UtcNow.Add(ttl.Value); | ||||||
} | ||||||
|
||||||
ResolveDatabase<T>().CreateAsync(value).Wait(); | ||||||
await (await ResolveDatabaseAsync<T>()).CreateAsync(value); | ||||||
} | ||||||
catch (Exception e) | ||||||
{ | ||||||
|
@@ -377,15 +370,15 @@ | |||||
/// is rethrown; otherwise, it is logged using the LogConsumer. | ||||||
/// </remarks> | ||||||
/// <exception cref="Exception">Thrown when an error occurs during the database operation, unless exceptions are suppressed.</exception> | ||||||
public void SetSpecific<T>(T value, string key, string subKey) | ||||||
public async Task SetSpecificAsync<T>(T value, string key, string subKey) | ||||||
where T : CouchDBCacheDocument | ||||||
{ | ||||||
try | ||||||
{ | ||||||
value.Key = key; | ||||||
value.SubKey = subKey; | ||||||
|
||||||
ResolveDatabase<T>().CreateOrUpdateAsync(value).Wait(); | ||||||
await (await ResolveDatabaseAsync<T>()).CreateOrUpdateAsync(value); | ||||||
} | ||||||
catch (Exception e) | ||||||
{ | ||||||
|
@@ -399,18 +392,18 @@ | |||||
} | ||||||
|
||||||
/// <inheritdoc /> | ||||||
public bool TryGet<T>(string key, out T value) | ||||||
public async Task<(bool Exists, T value)> TryGetAsync<T>(string key) | ||||||
Check warning Code scanning / Sonarcsharp (reported by Codacy) Refactor this method to use all type parameters in the parameter list to enable type inference. Warning
Refactor this method to use all type parameters in the parameter list to enable type inference.
|
||||||
{ | ||||||
var get = Get<CouchDBCacheDocument>(key); | ||||||
|
||||||
var get = await GetAsync<CouchDBCacheDocument>(key); | ||||||
T value; | ||||||
if (get != default) | ||||||
{ | ||||||
value = (T)(object)get; | ||||||
return true; | ||||||
return (true, value); | ||||||
} | ||||||
|
||||||
value = default; | ||||||
return false; | ||||||
return (false, value); | ||||||
} | ||||||
|
||||||
/// <summary> | ||||||
|
@@ -427,18 +420,18 @@ | |||||
/// If no document is found, <paramref name="value"/> is set to its default value, and the method returns false. | ||||||
/// This is useful for safely attempting to retrieve values without throwing exceptions if the keys do not exist in the cache. | ||||||
/// </remarks> | ||||||
public bool TryGet<T>(string key, string subKey, out T value) | ||||||
public async Task<(bool Exists, T value)> TryGetAsync<T>(string key, string subKey) | ||||||
Check warning Code scanning / Sonarcsharp (reported by Codacy) Refactor this method to use all type parameters in the parameter list to enable type inference. Warning
Refactor this method to use all type parameters in the parameter list to enable type inference.
|
||||||
{ | ||||||
var get = Get<CouchDBCacheDocument>(key, subKey); | ||||||
|
||||||
var get = await GetAsync<CouchDBCacheDocument>(key, subKey); | ||||||
T value; | ||||||
if (get != default) | ||||||
{ | ||||||
value = (T)(object)get; | ||||||
return true; | ||||||
return (true, value); | ||||||
} | ||||||
|
||||||
value = default; | ||||||
return false; | ||||||
return (false, value); | ||||||
} | ||||||
|
||||||
/// <summary> | ||||||
|
@@ -454,9 +447,10 @@ | |||||
/// This method assumes that the key exists in the cache; if it does not, the behavior will depend | ||||||
/// on the implementation of the Get method. | ||||||
/// </remarks> | ||||||
public TimeSpan TTL(string key) | ||||||
public async Task<TimeSpan> TTLAsync(string key) | ||||||
Check warning Code scanning / Sonarcsharp (reported by Codacy) Rename method 'TTLAsync' to match pascal case naming rules, consider using 'TtlAsync'. Warning
Rename method 'TTLAsync' to match pascal case naming rules, consider using 'TtlAsync'.
|
||||||
{ | ||||||
return Get<CouchDBCacheDocument>(key).TTL; | ||||||
var result = await GetAsync<CouchDBCacheDocument>(key); | ||||||
return result.TTL; | ||||||
Comment on lines
+452
to
+453
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add null check to prevent potential In the Apply this change to handle the null case: var result = await GetAsync<CouchDBCacheDocument>(key);
if (result == null)
{
// Handle the null case appropriately
return TimeSpan.Zero; // or throw an exception if preferred
}
return result.TTL; |
||||||
} | ||||||
|
||||||
/// <summary> | ||||||
|
@@ -471,16 +465,16 @@ | |||||
/// ensuring that it handles database creation and retrieval efficiently. The use of generics allows for flexibility in specifying the type of documents | ||||||
/// that will be stored in the database, making this method suitable for various CouchDBCacheDocument types. | ||||||
/// </remarks> | ||||||
private CouchDatabase<T> ResolveDatabase<T>(string dbName = default) | ||||||
private async Task<CouchDatabase<T>> ResolveDatabaseAsync<T>(string dbName = default) | ||||||
Check warning Code scanning / Sonarcsharp (reported by Codacy) Refactor this method to use all type parameters in the parameter list to enable type inference. Warning
Refactor this method to use all type parameters in the parameter list to enable type inference.
|
||||||
where T : CouchDBCacheDocument | ||||||
{ | ||||||
if (string.IsNullOrEmpty(dbName)) | ||||||
{ | ||||||
dbName = $"{typeof(T).Name.ToLowerInvariant()}s"; | ||||||
} | ||||||
|
||||||
return !_connector.CouchDBClient.GetDatabasesNamesAsync().Result.Contains(dbName) | ||||||
? _connector.CouchDBClient.CreateDatabaseAsync<T>().Result | ||||||
return !(await _connector.CouchDBClient.GetDatabasesNamesAsync()).Contains(dbName) | ||||||
? (await _connector.CouchDBClient.CreateDatabaseAsync<T>()) | ||||||
Comment on lines
+468
to
+477
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Refactor method to enable type inference for generic type parameter The method 🧰 Tools🪛 GitHub Check: Sonarcsharp (reported by Codacy)
|
||||||
: _connector.CouchDBClient.GetDatabase<T>(); | ||||||
} | ||||||
|
||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Refactor method to enable type inference for generic type parameter
The method
GetDocCountAsync<T>()
does not utilize the type parameterT
in its parameters in a way that allows for type inference. This may require callers to explicitly specify the type parameter when invoking the method. Consider modifying the method to includeT
in the parameter list or refactor the method to eliminate the unnecessary generic type parameter.🧰 Tools
🪛 GitHub Check: Sonarcsharp (reported by Codacy)