Browse Source

Lazy fixes.

pull/349/head
Sebastian Stehle 7 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)
{
if (item is JsonNull n)
if (item is JsonNull)
{
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)
{
var canReserve =
!State.Apps.ContainsKey(name) &&
!State.Apps.Any(x => x.Value == appId) &&
!reservedIds.Contains(appId) &&
!reservedNames.Contains(name);
var canReserve = !IsInUse(appId, name) && !IsReserved(appId, name);
if (canReserve)
{
@ -55,6 +51,16 @@ namespace Squidex.Domain.Apps.Entities.Apps.Indexes
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)
{
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
{
private readonly Lazy<IContentRepository> contentRepository;
private readonly Lazy<ICommandBus> commandBus;
private readonly IContentRepository contentRepository;
private readonly ICommandBus commandBus;
private readonly IClock clock;
private readonly ISemanticLog log;
private TaskScheduler scheduler;
public ContentSchedulerGrain(
Lazy<IContentRepository> contentRepository,
Lazy<ICommandBus> commandBus,
IContentRepository contentRepository,
ICommandBus commandBus,
IClock clock,
ISemanticLog log)
{
@ -39,9 +39,11 @@ namespace Squidex.Domain.Apps.Entities.Contents
Guard.NotNull(clock, nameof(clock));
Guard.NotNull(log, nameof(log));
this.contentRepository = contentRepository;
this.commandBus = commandBus;
this.clock = clock;
this.commandBus = commandBus;
this.contentRepository = contentRepository;
this.log = log;
}
@ -66,7 +68,7 @@ namespace Squidex.Domain.Apps.Entities.Contents
{
var now = clock.GetCurrentInstant();
return contentRepository.Value.QueryScheduledWithoutDataAsync(now, content =>
return contentRepository.QueryScheduledWithoutDataAsync(now, content =>
{
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 };
await commandBus.Value.PublishAsync(command);
await commandBus.PublishAsync(command);
}
}
catch (Exception ex)

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

@ -8,6 +8,7 @@
using System;
using System.Linq;
using System.Reflection;
using System.Threading;
using MongoDB.Bson.Serialization;
using MongoDB.Bson.Serialization.Conventions;
using Newtonsoft.Json;
@ -17,36 +18,41 @@ namespace Squidex.Infrastructure.MongoDb
{
public static class BsonJsonConvention
{
private static volatile int isRegistered;
public static void Register(JsonSerializer serializer)
{
var pack = new ConventionPack();
pack.AddMemberMapConvention("JsonBson", memberMap =>
if (Interlocked.Increment(ref isRegistered) == 1)
{
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 bsonSerializer = Activator.CreateInstance(bsonSerializerType, serializer);
var attributes = memberMap.MemberInfo.GetCustomAttributes();
memberMap.SetSerializer((IBsonSerializer)bsonSerializer);
}
else if (memberMap.MemberType == typeof(JToken))
{
memberMap.SetSerializer(JTokenSerializer<JToken>.Instance);
}
else if (memberMap.MemberType == typeof(JObject))
{
memberMap.SetSerializer(JTokenSerializer<JObject>.Instance);
}
else if (memberMap.MemberType == typeof(JValue))
{
memberMap.SetSerializer(JTokenSerializer<JValue>.Instance);
}
});
if (attributes.OfType<BsonJsonAttribute>().Any())
{
var bsonSerializerType = typeof(BsonJsonSerializer<>).MakeGenericType(memberMap.MemberType);
var bsonSerializer = Activator.CreateInstance(bsonSerializerType, serializer);
memberMap.SetSerializer((IBsonSerializer)bsonSerializer);
}
else if (memberMap.MemberType == typeof(JToken))
{
memberMap.SetSerializer(JTokenSerializer<JToken>.Instance);
}
else if (memberMap.MemberType == typeof(JObject))
{
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.
// ==========================================================================
using System;
using System.Threading;
using MongoDB.Bson.Serialization;
using MongoDB.Bson.Serialization.Serializers;
using NodaTime;
@ -14,16 +14,14 @@ namespace Squidex.Infrastructure.MongoDb
{
public sealed class InstantSerializer : SerializerBase<Instant>, IBsonPolymorphicSerializer
{
private static readonly Lazy<bool> Registerer = new Lazy<bool>(() =>
{
BsonSerializer.RegisterSerializer(new InstantSerializer());
return true;
});
private static volatile int isRegistered;
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

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

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

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

@ -5,7 +5,7 @@
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System;
using System.Threading;
using MongoDB.Bson.Serialization;
using MongoDB.Bson.Serialization.Serializers;
@ -13,16 +13,14 @@ namespace Squidex.Infrastructure.MongoDb
{
public class RefTokenSerializer : ClassSerializerBase<RefToken>
{
private static readonly Lazy<bool> Registerer = new Lazy<bool>(() =>
{
BsonSerializer.RegisterSerializer(new RefTokenSerializer());
return true;
});
private static volatile int isRegistered;
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)

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

@ -19,22 +19,19 @@ namespace Squidex.Infrastructure
public sealed class RedisPubSub : IPubSub, IInitializable
{
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 Lazy<ISubscriber> redisSubscriber;
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(redis, nameof(redis));
Guard.NotNull(log, nameof(log));
this.log = log;
redisClient = redis;
redisSubscriber = new Lazy<ISubscriber>(() => redis.Value.GetSubscriber());
this.redis = redis;
this.serializer = serializer;
}
@ -42,13 +39,15 @@ namespace Squidex.Infrastructure
{
try
{
redisClient.Value.GetStatus();
redisSubscriber = redis.GetSubscriber();
redis.GetStatus();
return TaskHelper.Done;
}
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;
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()
{
SixLabors.ImageSharp.Configuration.Default.ImageFormatsManager.AddImageFormat(ImageFormats.Jpeg);
SixLabors.ImageSharp.Configuration.Default.ImageFormatsManager.AddImageFormat(ImageFormats.Png);
Configuration.Default.ImageFormatsManager.AddImageFormat(ImageFormats.Jpeg);
Configuration.Default.ImageFormatsManager.AddImageFormat(ImageFormats.Png);
}
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);
}
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
{
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);
}
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);
}
private string GetLanguageCode(Language language)
private static string GetLanguageCode(Language language)
{
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<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>();
services.AddSingletonAs<FeaturesService>()
@ -48,9 +53,6 @@ namespace Squidex.Config.Domain
services.AddSingletonAs<DeepLTranslator>()
.As<ITranslator>();
services.AddSingletonAs(c => new CachingUsageTracker(c.GetRequiredService<BackgroundUsageTracker>(), c.GetRequiredService<IMemoryCache>()))
.As<IUsageTracker>();
services.AddSingletonAs<AsyncLocalCache>()
.As<ILocalCache>();
@ -68,8 +70,6 @@ namespace Squidex.Config.Domain
services.AddSingletonAs<DefaultXmlRepository>()
.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"))
{
services.AddSingletonAs(JsonLogWriterFactory.Readable())
services.AddSingletonAs(_ => JsonLogWriterFactory.Readable())
.As<IObjectWriterFactory>();
}
else
{
services.AddSingletonAs(JsonLogWriterFactory.Default())
services.AddSingletonAs(_ => JsonLogWriterFactory.Default())
.As<IObjectWriterFactory>();
}
@ -33,16 +33,16 @@ namespace Squidex.Config.Domain
if (!string.IsNullOrWhiteSpace(loggingFile))
{
services.AddSingletonAs(new FileChannel(loggingFile))
services.AddSingletonAs(_ => new FileChannel(loggingFile))
.As<ILogChannel>();
}
var useColors = config.GetValue<bool>("logging:colors");
services.AddSingletonAs(new ConsoleLogChannel(useColors))
services.AddSingletonAs(_ => new ConsoleLogChannel(useColors))
.As<ILogChannel>();
services.AddSingletonAs(c => new ApplicationInfoLogAppender(typeof(Program).Assembly, Guid.NewGuid()))
services.AddSingletonAs(_ => new ApplicationInfoLogAppender(typeof(Program).Assembly, Guid.NewGuid()))
.As<ILogAppender>();
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.AddSingletonAs(c => Singletons<IMongoClient>.GetOrAdd(mongoConfiguration, s => new MongoClient(s)))
services.AddSingletonAs(_ => Singletons<IMongoClient>.GetOrAdd(mongoConfiguration, s => new MongoClient(s)))
.As<IMongoClient>();
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)
{
var fullPath = GetPaths(pluginPath);
foreach (var candidate in GetPaths(pluginPath))
{
if (candidate.Extension.Equals(".dll", StringComparison.OrdinalIgnoreCase))

Loading…
Cancel
Save