Skip to content

Instantly share code, notes, and snippets.

@patrickhuber
Last active March 25, 2025 01:58
Show Gist options
  • Save patrickhuber/31e8f9f0ce3ea94d36b139d31bad4d54 to your computer and use it in GitHub Desktop.
Save patrickhuber/31e8f9f0ce3ea94d36b139d31bad4d54 to your computer and use it in GitHub Desktop.
using System;
using System.Collections.Concurrent;
public class Program
{
public static void Main()
{
ILogger logger = new ConsoleLogger();
IServicePartitionResolver servicePartitionResolver = new ServicePartitionResolver();
servicePartitionResolver = new ResilientServicePartitionResolver(servicePartitionResolver, 3);
servicePartitionResolver = new CachingServicePartitionResolver(servicePartitionResolver);
servicePartitionResolver = new LoggingServicePartitionResolver(servicePartitionResolver, logger);
logger.Log(servicePartitionResolver.ResolveServicePartition(new Uri("http://www.google.com")));
}
}
public interface IServicePartitionResolver
{
string ResolveServicePartition(Uri serviceURI);
}
public class ServicePartitionResolver : IServicePartitionResolver
{
public string ResolveServicePartition(Uri serviceURI)
{
return serviceURI.ToString();
}
}
public class ResilientServicePartitionResolver : IServicePartitionResolver
{
IServicePartitionResolver servicePartitionResolver;
int retryCount;
public ResilientServicePartitionResolver(IServicePartitionResolver servicePartitionResolver, int retryCount = 1)
{
this.servicePartitionResolver = servicePartitionResolver;
this.retryCount = retryCount;
}
public string ResolveServicePartition(Uri serviceURI)
{
int currentAttempt = 0;
while (true)
{
try
{
return this.servicePartitionResolver.ResolveServicePartition(serviceURI);
}
catch (Exception)
{
if (currentAttempt <= this.retryCount)
{
continue;
}
throw;
}
}
}
}
public interface ILogger
{
void Log(string message);
void LogError(Exception ex);
}
public class ConsoleLogger : ILogger
{
public void Log(string message)
{
Console.WriteLine(message);
}
public void LogError(Exception ex)
{
Console.Error.WriteLine(ex.Message);
}
}
public class LoggingServicePartitionResolver : IServicePartitionResolver
{
IServicePartitionResolver servicePartitionResolver;
ILogger logger;
public LoggingServicePartitionResolver(IServicePartitionResolver servicePartitionResolver, ILogger logger)
{
this.servicePartitionResolver = servicePartitionResolver;
this.logger = logger;
}
public string ResolveServicePartition(Uri serviceURI)
{
this.logger.Log($"{nameof(IServicePartitionResolver)}.{nameof(ResolveServicePartition)}({nameof(serviceURI)}: {serviceURI})");
try
{
return this.servicePartitionResolver.ResolveServicePartition(serviceURI);
}
catch (Exception ex)
{
this.logger.LogError(ex);
throw;
}
}
}
public class CachingServicePartitionResolver : IServicePartitionResolver
{
IServicePartitionResolver servicePartitionResolver;
ConcurrentDictionary<Uri, string> cache;
public CachingServicePartitionResolver(IServicePartitionResolver servicePartitionResolver)
{
this.servicePartitionResolver = servicePartitionResolver;
this.cache = new ConcurrentDictionary<Uri, string>();
}
public string ResolveServicePartition(Uri serviceURI)
{
return this.cache.GetOrAdd(serviceURI, (uri) => this.servicePartitionResolver.ResolveServicePartition(uri));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment