Browse Source

Lazy fixes.

pull/349/head
Sebastian Stehle 8 years ago
parent
commit
a5d170283d
  1. 2
      src/Squidex.Domain.Apps.Core.Operations/ValidateContent/JsonValueConverter.cs
  2. 16
      src/Squidex.Domain.Apps.Entities/Apps/Indexes/AppsByNameIndexGrain.cs
  3. 18
      src/Squidex.Domain.Apps.Entities/Contents/ContentSchedulerGrain.cs
  4. 52
      src/Squidex.Infrastructure.MongoDb/MongoDb/BsonJsonConvention.cs
  5. 16
      src/Squidex.Infrastructure.MongoDb/MongoDb/InstantSerializer.cs
  6. 1
      src/Squidex.Infrastructure.MongoDb/MongoDb/MongoRepositoryBase.cs
  7. 16
      src/Squidex.Infrastructure.MongoDb/MongoDb/RefTokenSerializer.cs
  8. 19
      src/Squidex.Infrastructure.Redis/RedisPubSub.cs
  9. 4
      src/Squidex.Infrastructure/Assets/ImageSharp/ImageSharpAssetThumbnailGenerator.cs
  10. 9
      src/Squidex.Infrastructure/DependencyInjection/DependencyInjectionExtensions.cs
  11. 20
      src/Squidex.Infrastructure/Lazier.cs
  12. 5
      src/Squidex.Infrastructure/Singletons.cs
  13. 2
      src/Squidex.Infrastructure/Translations/DeepLTranslator.cs
  14. 12
      src/Squidex/Config/Domain/InfrastructureServices.cs
  15. 10
      src/Squidex/Config/Domain/LoggingServices.cs
  16. 2
      src/Squidex/Config/Domain/StoreServices.cs
  17. 2
      src/Squidex/Pipeline/Plugins/PluginExtensions.cs

2
src/Squidex.Domain.Apps.Core.Operations/ValidateContent/JsonValueConverter.cs

@ -179,7 +179,7 @@ namespace Squidex.Domain.Apps.Core.ValidateContent
foreach (var item in array) foreach (var item in array)
{ {
if (item is JsonNull n) if (item is JsonNull)
{ {
result.Add(null); result.Add(null);
} }

16
src/Squidex.Domain.Apps.Entities/Apps/Indexes/AppsByNameIndexGrain.cs

@ -40,11 +40,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Indexes
public Task<bool> ReserveAppAsync(Guid appId, string name) public Task<bool> ReserveAppAsync(Guid appId, string name)
{ {
var canReserve = var canReserve = !IsInUse(appId, name) && !IsReserved(appId, name);
!State.Apps.ContainsKey(name) &&
!State.Apps.Any(x => x.Value == appId) &&
!reservedIds.Contains(appId) &&
!reservedNames.Contains(name);
if (canReserve) if (canReserve)
{ {
@ -55,6 +51,16 @@ namespace Squidex.Domain.Apps.Entities.Apps.Indexes
return Task.FromResult(canReserve); return Task.FromResult(canReserve);
} }
private bool IsInUse(Guid appId, string name)
{
return State.Apps.ContainsKey(name) || State.Apps.All(x => x.Value == appId);
}
private bool IsReserved(Guid appId, string name)
{
return reservedIds.Contains(appId) || reservedNames.Contains(name);
}
public Task RemoveReservationAsync(Guid appId, string name) public Task RemoveReservationAsync(Guid appId, string name)
{ {
reservedIds.Remove(appId); reservedIds.Remove(appId);

18
src/Squidex.Domain.Apps.Entities/Contents/ContentSchedulerGrain.cs

@ -22,15 +22,15 @@ namespace Squidex.Domain.Apps.Entities.Contents
{ {
public sealed class ContentSchedulerGrain : Grain, IContentSchedulerGrain, IRemindable public sealed class ContentSchedulerGrain : Grain, IContentSchedulerGrain, IRemindable
{ {
private readonly Lazy<IContentRepository> contentRepository; private readonly IContentRepository contentRepository;
private readonly Lazy<ICommandBus> commandBus; private readonly ICommandBus commandBus;
private readonly IClock clock; private readonly IClock clock;
private readonly ISemanticLog log; private readonly ISemanticLog log;
private TaskScheduler scheduler; private TaskScheduler scheduler;
public ContentSchedulerGrain( public ContentSchedulerGrain(
Lazy<IContentRepository> contentRepository, IContentRepository contentRepository,
Lazy<ICommandBus> commandBus, ICommandBus commandBus,
IClock clock, IClock clock,
ISemanticLog log) ISemanticLog log)
{ {
@ -39,9 +39,11 @@ namespace Squidex.Domain.Apps.Entities.Contents
Guard.NotNull(clock, nameof(clock)); Guard.NotNull(clock, nameof(clock));
Guard.NotNull(log, nameof(log)); Guard.NotNull(log, nameof(log));
this.contentRepository = contentRepository;
this.commandBus = commandBus;
this.clock = clock; this.clock = clock;
this.commandBus = commandBus;
this.contentRepository = contentRepository;
this.log = log; this.log = log;
} }
@ -66,7 +68,7 @@ namespace Squidex.Domain.Apps.Entities.Contents
{ {
var now = clock.GetCurrentInstant(); var now = clock.GetCurrentInstant();
return contentRepository.Value.QueryScheduledWithoutDataAsync(now, content => return contentRepository.QueryScheduledWithoutDataAsync(now, content =>
{ {
return Dispatch(async () => return Dispatch(async () =>
{ {
@ -78,7 +80,7 @@ namespace Squidex.Domain.Apps.Entities.Contents
{ {
var command = new ChangeContentStatus { ContentId = content.Id, Status = job.Status, Actor = job.ScheduledBy, JobId = job.Id }; var command = new ChangeContentStatus { ContentId = content.Id, Status = job.Status, Actor = job.ScheduledBy, JobId = job.Id };
await commandBus.Value.PublishAsync(command); await commandBus.PublishAsync(command);
} }
} }
catch (Exception ex) catch (Exception ex)

52
src/Squidex.Infrastructure.MongoDb/MongoDb/BsonJsonConvention.cs

@ -8,6 +8,7 @@
using System; using System;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Threading;
using MongoDB.Bson.Serialization; using MongoDB.Bson.Serialization;
using MongoDB.Bson.Serialization.Conventions; using MongoDB.Bson.Serialization.Conventions;
using Newtonsoft.Json; using Newtonsoft.Json;
@ -17,36 +18,41 @@ namespace Squidex.Infrastructure.MongoDb
{ {
public static class BsonJsonConvention public static class BsonJsonConvention
{ {
private static volatile int isRegistered;
public static void Register(JsonSerializer serializer) public static void Register(JsonSerializer serializer)
{ {
var pack = new ConventionPack(); if (Interlocked.Increment(ref isRegistered) == 1)
pack.AddMemberMapConvention("JsonBson", memberMap =>
{ {
var attributes = memberMap.MemberInfo.GetCustomAttributes(); var pack = new ConventionPack();
if (attributes.OfType<BsonJsonAttribute>().Any()) pack.AddMemberMapConvention("JsonBson", memberMap =>
{ {
var bsonSerializerType = typeof(BsonJsonSerializer<>).MakeGenericType(memberMap.MemberType); var attributes = memberMap.MemberInfo.GetCustomAttributes();
var bsonSerializer = Activator.CreateInstance(bsonSerializerType, serializer);
memberMap.SetSerializer((IBsonSerializer)bsonSerializer); if (attributes.OfType<BsonJsonAttribute>().Any())
} {
else if (memberMap.MemberType == typeof(JToken)) var bsonSerializerType = typeof(BsonJsonSerializer<>).MakeGenericType(memberMap.MemberType);
{ var bsonSerializer = Activator.CreateInstance(bsonSerializerType, serializer);
memberMap.SetSerializer(JTokenSerializer<JToken>.Instance);
} memberMap.SetSerializer((IBsonSerializer)bsonSerializer);
else if (memberMap.MemberType == typeof(JObject)) }
{ else if (memberMap.MemberType == typeof(JToken))
memberMap.SetSerializer(JTokenSerializer<JObject>.Instance); {
} memberMap.SetSerializer(JTokenSerializer<JToken>.Instance);
else if (memberMap.MemberType == typeof(JValue)) }
{ else if (memberMap.MemberType == typeof(JObject))
memberMap.SetSerializer(JTokenSerializer<JValue>.Instance); {
} memberMap.SetSerializer(JTokenSerializer<JObject>.Instance);
}); }
else if (memberMap.MemberType == typeof(JValue))
{
memberMap.SetSerializer(JTokenSerializer<JValue>.Instance);
}
});
ConventionRegistry.Register("json", pack, t => true); ConventionRegistry.Register("json", pack, t => true);
}
} }
} }
} }

16
src/Squidex.Infrastructure.MongoDb/MongoDb/InstantSerializer.cs

@ -5,7 +5,7 @@
// All rights reserved. Licensed under the MIT license. // All rights reserved. Licensed under the MIT license.
// ========================================================================== // ==========================================================================
using System; using System.Threading;
using MongoDB.Bson.Serialization; using MongoDB.Bson.Serialization;
using MongoDB.Bson.Serialization.Serializers; using MongoDB.Bson.Serialization.Serializers;
using NodaTime; using NodaTime;
@ -14,16 +14,14 @@ namespace Squidex.Infrastructure.MongoDb
{ {
public sealed class InstantSerializer : SerializerBase<Instant>, IBsonPolymorphicSerializer public sealed class InstantSerializer : SerializerBase<Instant>, IBsonPolymorphicSerializer
{ {
private static readonly Lazy<bool> Registerer = new Lazy<bool>(() => private static volatile int isRegistered;
{
BsonSerializer.RegisterSerializer(new InstantSerializer());
return true;
});
public static bool Register() public static void Register()
{ {
return !Registerer.IsValueCreated && Registerer.Value; if (Interlocked.Increment(ref isRegistered) == 1)
{
BsonSerializer.RegisterSerializer(new InstantSerializer());
}
} }
public bool IsDiscriminatorCompatibleWithObjectSerializer public bool IsDiscriminatorCompatibleWithObjectSerializer

1
src/Squidex.Infrastructure.MongoDb/MongoDb/MongoRepositoryBase.cs

@ -44,6 +44,7 @@ namespace Squidex.Infrastructure.MongoDb
static MongoRepositoryBase() static MongoRepositoryBase()
{ {
RefTokenSerializer.Register(); RefTokenSerializer.Register();
InstantSerializer.Register(); InstantSerializer.Register();
} }

16
src/Squidex.Infrastructure.MongoDb/MongoDb/RefTokenSerializer.cs

@ -5,7 +5,7 @@
// All rights reserved. Licensed under the MIT license. // All rights reserved. Licensed under the MIT license.
// ========================================================================== // ==========================================================================
using System; using System.Threading;
using MongoDB.Bson.Serialization; using MongoDB.Bson.Serialization;
using MongoDB.Bson.Serialization.Serializers; using MongoDB.Bson.Serialization.Serializers;
@ -13,16 +13,14 @@ namespace Squidex.Infrastructure.MongoDb
{ {
public class RefTokenSerializer : ClassSerializerBase<RefToken> public class RefTokenSerializer : ClassSerializerBase<RefToken>
{ {
private static readonly Lazy<bool> Registerer = new Lazy<bool>(() => private static volatile int isRegistered;
{
BsonSerializer.RegisterSerializer(new RefTokenSerializer());
return true;
});
public static bool Register() public static void Register()
{ {
return !Registerer.IsValueCreated && Registerer.Value; if (Interlocked.Increment(ref isRegistered) == 1)
{
BsonSerializer.RegisterSerializer(new RefTokenSerializer());
}
} }
protected override RefToken DeserializeValue(BsonDeserializationContext context, BsonDeserializationArgs args) protected override RefToken DeserializeValue(BsonDeserializationContext context, BsonDeserializationArgs args)

19
src/Squidex.Infrastructure.Redis/RedisPubSub.cs

@ -19,22 +19,19 @@ namespace Squidex.Infrastructure
public sealed class RedisPubSub : IPubSub, IInitializable public sealed class RedisPubSub : IPubSub, IInitializable
{ {
private readonly ConcurrentDictionary<string, object> subscriptions = new ConcurrentDictionary<string, object>(); private readonly ConcurrentDictionary<string, object> subscriptions = new ConcurrentDictionary<string, object>();
private readonly Lazy<IConnectionMultiplexer> redisClient; private readonly IConnectionMultiplexer redis;
private readonly IJsonSerializer serializer; private readonly IJsonSerializer serializer;
private readonly Lazy<ISubscriber> redisSubscriber;
private readonly ISemanticLog log; private readonly ISemanticLog log;
private ISubscriber redisSubscriber;
public RedisPubSub(Lazy<IConnectionMultiplexer> redis, IJsonSerializer serializer, ISemanticLog log) public RedisPubSub(IConnectionMultiplexer redis, IJsonSerializer serializer, ISemanticLog log)
{ {
Guard.NotNull(serializer, nameof(serializer)); Guard.NotNull(serializer, nameof(serializer));
Guard.NotNull(redis, nameof(redis)); Guard.NotNull(redis, nameof(redis));
Guard.NotNull(log, nameof(log)); Guard.NotNull(log, nameof(log));
this.log = log; this.log = log;
this.redis = redis;
redisClient = redis;
redisSubscriber = new Lazy<ISubscriber>(() => redis.Value.GetSubscriber());
this.serializer = serializer; this.serializer = serializer;
} }
@ -42,13 +39,15 @@ namespace Squidex.Infrastructure
{ {
try try
{ {
redisClient.Value.GetStatus(); redisSubscriber = redis.GetSubscriber();
redis.GetStatus();
return TaskHelper.Done; return TaskHelper.Done;
} }
catch (Exception ex) catch (Exception ex)
{ {
throw new ConfigurationException($"Redis connection failed to connect to database {redisClient.Value.Configuration}", ex); throw new ConfigurationException($"Redis connection failed to connect to database {redis.Configuration}", ex);
} }
} }
@ -66,7 +65,7 @@ namespace Squidex.Infrastructure
{ {
var typeName = typeof(T).FullName; var typeName = typeof(T).FullName;
return (RedisSubscription<T>)subscriptions.GetOrAdd(typeName, this, (k, c) => new RedisSubscription<T>(c.redisSubscriber.Value, serializer, k, c.log)); return (RedisSubscription<T>)subscriptions.GetOrAdd(typeName, this, (k, c) => new RedisSubscription<T>(c.redisSubscriber, serializer, k, c.log));
} }
} }
} }

4
src/Squidex.Infrastructure/Assets/ImageSharp/ImageSharpAssetThumbnailGenerator.cs

@ -19,8 +19,8 @@ namespace Squidex.Infrastructure.Assets.ImageSharp
{ {
public ImageSharpAssetThumbnailGenerator() public ImageSharpAssetThumbnailGenerator()
{ {
SixLabors.ImageSharp.Configuration.Default.ImageFormatsManager.AddImageFormat(ImageFormats.Jpeg); Configuration.Default.ImageFormatsManager.AddImageFormat(ImageFormats.Jpeg);
SixLabors.ImageSharp.Configuration.Default.ImageFormatsManager.AddImageFormat(ImageFormats.Png); Configuration.Default.ImageFormatsManager.AddImageFormat(ImageFormats.Png);
} }
public Task CreateThumbnailAsync(Stream source, Stream destination, int? width, int? height, string mode) public Task CreateThumbnailAsync(Stream source, Stream destination, int? width, int? height, string mode)

9
src/Squidex.Infrastructure/DependencyInjection/DependencyInjectionExtensions.cs

@ -72,15 +72,6 @@ namespace Microsoft.Extensions.DependencyInjection
return new InterfaceRegistrator<T>(services); return new InterfaceRegistrator<T>(services);
} }
public static InterfaceRegistrator<T> AddSingletonAs<T>(this IServiceCollection services, T instance) where T : class
{
services.AddSingleton(typeof(T), instance);
RegisterDefaults<T>(services);
return new InterfaceRegistrator<T>(services);
}
public static InterfaceRegistrator<T> AddSingletonAs<T>(this IServiceCollection services) where T : class public static InterfaceRegistrator<T> AddSingletonAs<T>(this IServiceCollection services) where T : class
{ {
services.AddSingleton<T, T>(); services.AddSingleton<T, T>();

20
src/Squidex.Infrastructure/Lazier.cs

@ -1,20 +0,0 @@
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System;
using Microsoft.Extensions.DependencyInjection;
namespace Squidex.Infrastructure
{
public sealed class Lazier<T> : Lazy<T> where T : class
{
public Lazier(IServiceProvider provider)
: base(provider.GetRequiredService<T>)
{
}
}
}

5
src/Squidex.Infrastructure/Singletons.cs

@ -18,10 +18,5 @@ namespace Squidex.Infrastructure
{ {
return Instances.GetOrAdd(key, factory); return Instances.GetOrAdd(key, factory);
} }
public static Lazy<T> GetOrAddLazy(string key, Func<string, T> factory)
{
return new Lazy<T>(() => Instances.GetOrAdd(key, factory));
}
} }
} }

2
src/Squidex.Infrastructure/Translations/DeepLTranslator.cs

@ -87,7 +87,7 @@ namespace Squidex.Infrastructure.Translations
return new Translation(TranslationResult.Failed, resultText: responseString); return new Translation(TranslationResult.Failed, resultText: responseString);
} }
private string GetLanguageCode(Language language) private static string GetLanguageCode(Language language)
{ {
return language.Iso2Code.Substring(0, 2).ToUpperInvariant(); return language.Iso2Code.Substring(0, 2).ToUpperInvariant();
} }

12
src/Squidex/Config/Domain/InfrastructureServices.cs

@ -36,7 +36,12 @@ namespace Squidex.Config.Domain
.AddCheck<OrleansHealthCheck>("Orleans", tags: new[] { "cluster" }) .AddCheck<OrleansHealthCheck>("Orleans", tags: new[] { "cluster" })
.AddCheck<OrleansAppsHealthCheck>("Orleans App", tags: new[] { "cluster" }); .AddCheck<OrleansAppsHealthCheck>("Orleans App", tags: new[] { "cluster" });
services.AddSingletonAs(SystemClock.Instance) services.AddSingletonAs(c => new CachingUsageTracker(
c.GetRequiredService<BackgroundUsageTracker>(),
c.GetRequiredService<IMemoryCache>()))
.As<IUsageTracker>();
services.AddSingletonAs(_ => SystemClock.Instance)
.As<IClock>(); .As<IClock>();
services.AddSingletonAs<FeaturesService>() services.AddSingletonAs<FeaturesService>()
@ -48,9 +53,6 @@ namespace Squidex.Config.Domain
services.AddSingletonAs<DeepLTranslator>() services.AddSingletonAs<DeepLTranslator>()
.As<ITranslator>(); .As<ITranslator>();
services.AddSingletonAs(c => new CachingUsageTracker(c.GetRequiredService<BackgroundUsageTracker>(), c.GetRequiredService<IMemoryCache>()))
.As<IUsageTracker>();
services.AddSingletonAs<AsyncLocalCache>() services.AddSingletonAs<AsyncLocalCache>()
.As<ILocalCache>(); .As<ILocalCache>();
@ -68,8 +70,6 @@ namespace Squidex.Config.Domain
services.AddSingletonAs<DefaultXmlRepository>() services.AddSingletonAs<DefaultXmlRepository>()
.As<IXmlRepository>(); .As<IXmlRepository>();
services.AddTransient(typeof(Lazy<>), typeof(Lazier<>));
} }
} }
} }

10
src/Squidex/Config/Domain/LoggingServices.cs

@ -20,12 +20,12 @@ namespace Squidex.Config.Domain
{ {
if (config.GetValue<bool>("logging:human")) if (config.GetValue<bool>("logging:human"))
{ {
services.AddSingletonAs(JsonLogWriterFactory.Readable()) services.AddSingletonAs(_ => JsonLogWriterFactory.Readable())
.As<IObjectWriterFactory>(); .As<IObjectWriterFactory>();
} }
else else
{ {
services.AddSingletonAs(JsonLogWriterFactory.Default()) services.AddSingletonAs(_ => JsonLogWriterFactory.Default())
.As<IObjectWriterFactory>(); .As<IObjectWriterFactory>();
} }
@ -33,16 +33,16 @@ namespace Squidex.Config.Domain
if (!string.IsNullOrWhiteSpace(loggingFile)) if (!string.IsNullOrWhiteSpace(loggingFile))
{ {
services.AddSingletonAs(new FileChannel(loggingFile)) services.AddSingletonAs(_ => new FileChannel(loggingFile))
.As<ILogChannel>(); .As<ILogChannel>();
} }
var useColors = config.GetValue<bool>("logging:colors"); var useColors = config.GetValue<bool>("logging:colors");
services.AddSingletonAs(new ConsoleLogChannel(useColors)) services.AddSingletonAs(_ => new ConsoleLogChannel(useColors))
.As<ILogChannel>(); .As<ILogChannel>();
services.AddSingletonAs(c => new ApplicationInfoLogAppender(typeof(Program).Assembly, Guid.NewGuid())) services.AddSingletonAs(_ => new ApplicationInfoLogAppender(typeof(Program).Assembly, Guid.NewGuid()))
.As<ILogAppender>(); .As<ILogAppender>();
services.AddSingletonAs<ActionContextLogAppender>() services.AddSingletonAs<ActionContextLogAppender>()

2
src/Squidex/Config/Domain/StoreServices.cs

@ -50,7 +50,7 @@ namespace Squidex.Config.Domain
services.AddSingleton(typeof(ISnapshotStore<,>), typeof(MongoSnapshotStore<,>)); services.AddSingleton(typeof(ISnapshotStore<,>), typeof(MongoSnapshotStore<,>));
services.AddSingletonAs(c => Singletons<IMongoClient>.GetOrAdd(mongoConfiguration, s => new MongoClient(s))) services.AddSingletonAs(_ => Singletons<IMongoClient>.GetOrAdd(mongoConfiguration, s => new MongoClient(s)))
.As<IMongoClient>(); .As<IMongoClient>();
services.AddSingletonAs(c => c.GetRequiredService<IMongoClient>().GetDatabase(mongoDatabaseName)) services.AddSingletonAs(c => c.GetRequiredService<IMongoClient>().GetDatabase(mongoDatabaseName))

2
src/Squidex/Pipeline/Plugins/PluginExtensions.cs

@ -83,8 +83,6 @@ namespace Squidex.Pipeline.Plugins
private static PluginLoader LoadPlugin(string pluginPath) private static PluginLoader LoadPlugin(string pluginPath)
{ {
var fullPath = GetPaths(pluginPath);
foreach (var candidate in GetPaths(pluginPath)) foreach (var candidate in GetPaths(pluginPath))
{ {
if (candidate.Extension.Equals(".dll", StringComparison.OrdinalIgnoreCase)) if (candidate.Extension.Equals(".dll", StringComparison.OrdinalIgnoreCase))

Loading…
Cancel
Save