Skip to content
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

refactor: Register the implementation of IRecordStorage with services #39

Merged
merged 2 commits into from
Aug 6, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 7 additions & 6 deletions samples/HelloRin/Startup.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
Expand Down Expand Up @@ -35,15 +35,16 @@ public void ConfigureServices(IServiceCollection services)

services.AddRin(options =>
{
// Optional: Use Redis as storage
// options.RequestRecorder.StorageFactory = Rin.Storage.Redis.RedisRecordStorage.DefaultFactoryWithOptions(redisOptions =>
// {
// redisOptions.ConnectionConfiguration = "[host]";
// });
options.RequestRecorder.RetentionMaxRequests = 100;
options.RequestRecorder.Excludes.Add(request => request.Path.Value.EndsWith(".js") || request.Path.Value.EndsWith(".css") || request.Path.Value.EndsWith(".svg"));
options.Inspector.ResponseBodyDataTransformers.Add(new RinCustomContentTypeTransformer());
});

// Optional: Use Redis as storage
//services.AddRinRedisStorage(options =>
//{
// options.ConnectionConfiguration = "localhost:6379";
//});
}

// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
Expand Down
24 changes: 8 additions & 16 deletions src/Rin.Storage.Redis/RedisRecordStorage.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection;
using Newtonsoft.Json;
using Rin.Core;
using Rin.Core.Event;
Expand All @@ -8,6 +8,7 @@
using System;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.Options;

namespace Rin.Storage.Redis
{
Expand All @@ -20,25 +21,14 @@ public class RedisRecordStorage : IRecordStorage
private static readonly string _serializeVersion;
private const string RedisSubscriptionKey = "RedisRecordStorage-Subscription";

private readonly RinOptions _rinOptions;
private readonly RedisRecordStorageOptions _options;
private readonly string _eventSourceKey = Guid.NewGuid().ToString();
private readonly IMessageEventBus<RequestEventMessage> _eventBus;
private readonly ConnectionMultiplexer _redisConnection;
private readonly IDatabase _redis;
private ISubscriber _redisSubscriber;

public static Func<IServiceProvider, IRecordStorage> DefaultFactoryWithOptions(Action<RedisRecordStorageOptions> configure)
{
return (services) =>
{
var retentionMaxRequests = services.GetService<RinOptions>().RequestRecorder.RetentionMaxRequests;
var options = new RedisRecordStorageOptions() { RetentionMaxRequests = retentionMaxRequests };
configure?.Invoke(options);

return new RedisRecordStorage(options, services.GetService<IMessageEventBus<RequestEventMessage>>());
};
}

static RedisRecordStorage()
{
_jsonSerializerSettings = new JsonSerializerSettings();
Expand All @@ -52,9 +42,11 @@ static RedisRecordStorage()
_serializeVersion = typeof(Rin.Core.Record.HttpRequestRecord).Assembly.GetName().Version.ToString();
}

public RedisRecordStorage(RedisRecordStorageOptions options, IMessageEventBus<RequestEventMessage> eventBus)
public RedisRecordStorage(IOptions<RedisRecordStorageOptions> options, IOptions<RinOptions> rinOptions, IMessageEventBus<RequestEventMessage> eventBus)
{
_options = options;
_options = options.Value;
_rinOptions = rinOptions.Value;

_eventBus = eventBus;
_redisConnection = ConnectionMultiplexer.Connect(_options.ConnectionConfiguration);
_redis = _redisConnection.GetDatabase(_options.Database);
Expand Down Expand Up @@ -84,7 +76,7 @@ await Task.WhenAll(
_redis.StringSetAsync(GetRedisKey($"RecordEntryInfo?{entry.Id}"), Serialize(HttpRequestRecordInfo.CreateFromRecord(entry)), _options.Expiry)
);
await Task.WhenAll(
_redis.ListTrimAsync(GetRedisKey($"Records"), 0, _options.RetentionMaxRequests),
_redis.ListTrimAsync(GetRedisKey($"Records"), 0, _rinOptions.RequestRecorder.RetentionMaxRequests),
_redis.KeyExpireAsync(GetRedisKey($"Records"), _options.Expiry)
);
}
Expand Down
7 changes: 1 addition & 6 deletions src/Rin.Storage.Redis/RedisRecordStorageOptions.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System;
using System;

namespace Rin.Storage.Redis
{
Expand All @@ -14,11 +14,6 @@ public class RedisRecordStorageOptions
/// </summary>
public string KeyPrefix { get; set; } = "Rin.Storage.";

/// <summary>
/// Maximum count of requests retention.
/// </summary>
public int RetentionMaxRequests { get; set; } = 100;

/// <summary>
/// Redis database for Rin records.
/// </summary>
Expand Down
25 changes: 25 additions & 0 deletions src/Rin.Storage.Redis/RinRedisRecordStorageServiceExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Rin.Core.Record;
using Rin.Storage.Redis;

namespace Microsoft.Extensions.DependencyInjection
{
public static class RinRedisRecordStorageServiceExtensions
{
/// <summary>
/// Add the Redis-backed <see cref="IRecordStorage"/> service and options.
/// </summary>
/// <param name="services"></param>
/// <param name="configure"></param>
public static void AddRinRedisStorage(this IServiceCollection services, Action<RedisRecordStorageOptions>? configure = null)
{
services.AddOptions<RedisRecordStorageOptions>();
services.Configure<RedisRecordStorageOptions>(configure);

services.Replace(new ServiceDescriptor(typeof(IRecordStorage), typeof(RedisRecordStorage), ServiceLifetime.Singleton));
}
}
}
4 changes: 1 addition & 3 deletions src/Rin/Core/RequestRecorderOptions.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http;
using Rin.Core.Record;
using Rin.Core.Storage;
using System;
Expand All @@ -15,7 +15,5 @@ public class RequestRecorderOptions
public bool EnableBodyCapturing { get; set; } = true;

public bool AllowRunningOnProduction { get; set; } = false;

public Func<IServiceProvider, IRecordStorage> StorageFactory { get; set; } = InMemoryRecordStorage.Factory;
}
}
20 changes: 8 additions & 12 deletions src/Rin/Core/Storage/InMemoryRecordStorage.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection;
using Rin.Core.Event;
using Rin.Core.Record;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Options;

namespace Rin.Core.Storage
{
Expand All @@ -14,19 +15,14 @@ namespace Rin.Core.Storage
/// </summary>
public class InMemoryRecordStorage : IRecordStorage
{
private Dictionary<string, RecordEntry> _entries = new Dictionary<string, RecordEntry>();
private Queue<string> _entryIds = new Queue<string>();
private int _retentionMaxRequests = 100;
private ReaderWriterLockSlim _lock = new ReaderWriterLockSlim();
private readonly Dictionary<string, RecordEntry> _entries = new Dictionary<string, RecordEntry>();
private readonly Queue<string> _entryIds = new Queue<string>();
private readonly int _retentionMaxRequests = 100;
private readonly ReaderWriterLockSlim _lock = new ReaderWriterLockSlim();

public static readonly Func<IServiceProvider, IRecordStorage> Factory = (services) =>
public InMemoryRecordStorage(IOptions<RinOptions> options)
{
return new InMemoryRecordStorage(services.GetService<RinOptions>().RequestRecorder.RetentionMaxRequests);
};

public InMemoryRecordStorage(int retentionMaxRequests)
{
_retentionMaxRequests = retentionMaxRequests;
_retentionMaxRequests = options.Value.RequestRecorder.RetentionMaxRequests;
}

public Task AddAsync(HttpRequestRecord record)
Expand Down
5 changes: 3 additions & 2 deletions src/Rin/Extensions/RinSerivceExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using Rin.Channel;
using Rin.Channel;
using Rin.Core;
using Rin.Core.Event;
using Rin.Core.Record;
Expand All @@ -8,6 +8,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Rin.Features;

namespace Microsoft.Extensions.DependencyInjection
Expand All @@ -28,7 +29,7 @@ public static void AddRin(this IServiceCollection services, Action<RinOptions>?
var transformers = serviceProvider.GetServices<IBodyDataTransformer>().ToArray();
return new BodyDataTransformerSet(new BodyDataTransformerPipeline(transformers), new BodyDataTransformerPipeline(transformers));
});
services.AddSingleton<IRecordStorage>(options.RequestRecorder.StorageFactory);
services.TryAddSingleton<IRecordStorage, InMemoryRecordStorage>();
services.AddSingleton<IMessageEventBus<RequestEventMessage>>(new MessageEventBus<RequestEventMessage>());
services.AddSingleton<IMessageEventBus<StoreBodyEventMessage>>(new MessageEventBus<StoreBodyEventMessage>());
services.AddSingleton<RinOptions>(options);
Expand Down
2 changes: 1 addition & 1 deletion src/Rin/Middlewares/RequestRecorderMiddleware.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using Microsoft.AspNetCore.Diagnostics;
using Microsoft.AspNetCore.Diagnostics;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Rin.Channel;
Expand Down