Create a memory cache. It's main API - method GetOrAdd(key, valueFactory, token)
. Cache should return value by key, if the value is present. Otherwise, it should asynchronously invoke valueFactory
to get value, and store value that was returned.
If second call with same key is performed, while first call is still executing, it should not perform additional valueFactory
invocation.
public interface ICache<TValue>
{
Task<TValue?> GetOrAdd(string key, Func<CancellationToken, Task<TValue>> valueFactory, CancellationToken token);
bool TryGet(string key, out TValue? value);
bool Remove(string key);
}
Would be great if your implementation supports:
- TTL configuration (passing TTL options in ctor, and/or in
GetOrAdd
method) - Error handling (including different strategies to cache failures along with successfully returned values)
- Multithreading support
- Logging
You are allowed to add/modify the interface if needed.
Create a wrapper/httphandler for default HttpClient
.
It should reduce number of parallel request, re-using response of requests that are already in process,
to calls that are requested when initial request is still being executed.
You need to think over a strategy of detecting, which requests can be "re-used". See: Idempotence.
Design a 'service discovery' web service. It should be able to provide information about all instances of applications in network, about their statuses (healthy/degraded/down). You can provide a solution in C# code, pseudocode, diagram or just as description in words.