Browse Source

Not everything was pushed

pull/1/head
Sebastian 9 years ago
parent
commit
ff5dac51f4
  1. 11
      src/Squidex.Core/Schemas/FieldRegistry.cs
  2. 14
      src/Squidex.Infrastructure.MongoDb/EventStore/MongoEventStore.cs
  3. 5
      src/Squidex.Infrastructure.MongoDb/MongoRepositoryBase.cs
  4. 54
      src/Squidex.Infrastructure.RabbitMq/RabbitMqEventBus.cs
  5. 7
      src/Squidex.Infrastructure/CQRS/Events/EventReceiver.cs
  6. 32
      src/Squidex.Infrastructure/CQRS/Events/InMemoryEventBus.cs
  7. 9
      src/Squidex.Infrastructure/CQRS/Replay/ReplayGenerator.cs
  8. 29
      src/Squidex.Infrastructure/ConfigurationException.cs
  9. 10
      src/Squidex.Infrastructure/ICliCommand.cs
  10. 15
      src/Squidex.Infrastructure/IExternalSystem.cs
  11. 100
      src/Squidex.Read.MongoDb/MongoDbModule.cs
  12. 38
      src/Squidex.Read.MongoDb/MongoDbStoresExternalSystem.cs
  13. 1
      src/Squidex.Read.MongoDb/project.json
  14. 2
      src/Squidex/Config/Identity/MyIdentityOptions.cs
  15. 2
      tests/Squidex.Core.Tests/Contents/ContentDataTests.cs

11
src/Squidex.Core/Schemas/FieldRegistry.cs

@ -51,9 +51,14 @@ namespace Squidex.Core.Schemas
public FieldRegistry() public FieldRegistry()
{ {
Add<BooleanFieldProperties>((id, name, properties) => new BooleanField(id, name, (BooleanFieldProperties)properties)); Add<BooleanFieldProperties>(
Add<NumberFieldProperties>((id, name, properties) => new NumberField(id, name, (NumberFieldProperties)properties)); (id, name, p) => new BooleanField(id, name, (BooleanFieldProperties)p));
Add<StringFieldProperties>((id, name, properties) => new StringField(id, name, (StringFieldProperties)properties));
Add<NumberFieldProperties>(
(id, name, p) => new NumberField(id, name, (NumberFieldProperties)p));
Add<StringFieldProperties>(
(id, name, p) => new StringField(id, name, (StringFieldProperties)p));
} }
public void Add<TFieldProperties>(FactoryFunction fieldFactory) public void Add<TFieldProperties>(FactoryFunction fieldFactory)

14
src/Squidex.Infrastructure.MongoDb/EventStore/MongoEventStore.cs

@ -22,7 +22,7 @@ using Squidex.Infrastructure.Reflection;
namespace Squidex.Infrastructure.MongoDb.EventStore namespace Squidex.Infrastructure.MongoDb.EventStore
{ {
public class MongoEventStore : MongoRepositoryBase<MongoEventCommit>, IEventStore public class MongoEventStore : MongoRepositoryBase<MongoEventCommit>, IEventStore, IExternalSystem
{ {
private sealed class EventCountEntity private sealed class EventCountEntity
{ {
@ -51,6 +51,18 @@ namespace Squidex.Infrastructure.MongoDb.EventStore
return collection.Indexes.CreateOneAsync(IndexKeys.Ascending(x => x.EventStream).Ascending(x => x.EventsVersion), new CreateIndexOptions { Unique = true }); return collection.Indexes.CreateOneAsync(IndexKeys.Ascending(x => x.EventStream).Ascending(x => x.EventsVersion), new CreateIndexOptions { Unique = true });
} }
public void CheckConnection()
{
try
{
Database.ListCollections();
}
catch (Exception e)
{
throw new ConfigurationException($"MongoDb Event Store failed to connect to database {Database.DatabaseNamespace.DatabaseName}", e);
}
}
public IObservable<EventData> GetEventsAsync(string streamName) public IObservable<EventData> GetEventsAsync(string streamName)
{ {
Guard.NotNullOrEmpty(streamName, nameof(streamName)); Guard.NotNullOrEmpty(streamName, nameof(streamName));

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

@ -84,6 +84,11 @@ namespace Squidex.Infrastructure.MongoDb
} }
} }
static MongoRepositoryBase()
{
RefTokenSerializer.Register();
}
protected MongoRepositoryBase(IMongoDatabase database) protected MongoRepositoryBase(IMongoDatabase database)
{ {
Guard.NotNull(database, nameof(database)); Guard.NotNull(database, nameof(database));

54
src/Squidex.Infrastructure.RabbitMq/RabbitMqEventChannel.cs → src/Squidex.Infrastructure.RabbitMq/RabbitMqEventBus.cs

@ -16,32 +16,58 @@ using Squidex.Infrastructure.CQRS.Events;
namespace Squidex.Infrastructure.RabbitMq namespace Squidex.Infrastructure.RabbitMq
{ {
public sealed class RabbitMqEventChannel : DisposableObject, IEventPublisher, IEventStream public sealed class RabbitMqEventBus : DisposableObject, IEventPublisher, IEventStream, IExternalSystem
{ {
private readonly bool isPersistent;
private const string Exchange = "Squidex"; private const string Exchange = "Squidex";
private readonly IConnection connection; private readonly IConnectionFactory connectionFactory;
private readonly IModel channel; private readonly Lazy<IConnection> connection;
private readonly Lazy<IModel> channel;
private EventingBasicConsumer consumer; private EventingBasicConsumer consumer;
public RabbitMqEventChannel(IConnectionFactory connectionFactory) public RabbitMqEventBus(IConnectionFactory connectionFactory, bool isPersistent)
{ {
Guard.NotNull(connectionFactory, nameof(connectionFactory)); Guard.NotNull(connectionFactory, nameof(connectionFactory));
connection = connectionFactory.CreateConnection(); this.connectionFactory = connectionFactory;
channel = CreateChannel(connection);
connection = new Lazy<IConnection>(connectionFactory.CreateConnection);
channel = new Lazy<IModel>(() => CreateChannel(connection.Value));
this.isPersistent = isPersistent;
} }
protected override void DisposeObject(bool disposing) protected override void DisposeObject(bool disposing)
{ {
connection.Close(); if (connection.IsValueCreated)
connection.Dispose(); {
connection.Value.Close();
connection.Value.Dispose();
}
} }
public void Publish(EventData eventData) public void Publish(EventData eventData)
{ {
ThrowIfDisposed(); ThrowIfDisposed();
channel.BasicPublish(Exchange, string.Empty, null, Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(eventData))); channel.Value.BasicPublish(Exchange, string.Empty, null, Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(eventData)));
}
public void CheckConnection()
{
try
{
var currentConnection = connection.Value;
if (!currentConnection.IsOpen)
{
throw new ConfigurationException($"RabbitMq event bus failed to connect to {connectionFactory.VirtualHost}");
}
}
catch (Exception e)
{
throw new ConfigurationException($"RabbitMq event bus failed to connect to {connectionFactory.VirtualHost}", e);
}
} }
public void Connect(string queueName, Action<EventData> received) public void Connect(string queueName, Action<EventData> received)
@ -51,14 +77,16 @@ namespace Squidex.Infrastructure.RabbitMq
lock (connection) lock (connection)
{ {
var currentChannel = channel.Value;
ThrowIfConnected(); ThrowIfConnected();
queueName = $"{queueName}_{Environment.MachineName}"; queueName = $"{queueName}_{Environment.MachineName}";
channel.QueueDeclare(queueName, true, false, false); currentChannel.QueueDeclare(queueName, isPersistent, false, !isPersistent);
channel.QueueBind(queueName, Exchange, string.Empty); currentChannel.QueueBind(queueName, Exchange, string.Empty);
consumer = new EventingBasicConsumer(channel); consumer = new EventingBasicConsumer(currentChannel);
consumer.Received += (model, e) => consumer.Received += (model, e) =>
{ {
@ -67,7 +95,7 @@ namespace Squidex.Infrastructure.RabbitMq
received(eventData); received(eventData);
}; };
channel.BasicConsume(queueName, true, consumer); currentChannel.BasicConsume(queueName, true, consumer);
} }
} }

7
src/Squidex.Infrastructure/CQRS/Events/EventReceiver.cs

@ -20,6 +20,7 @@ namespace Squidex.Infrastructure.CQRS.Events
public sealed class EventReceiver public sealed class EventReceiver
{ {
private readonly EventDataFormatter formatter; private readonly EventDataFormatter formatter;
private readonly bool canCatch;
private readonly IEnumerable<ILiveEventConsumer> liveConsumers; private readonly IEnumerable<ILiveEventConsumer> liveConsumers;
private readonly IEnumerable<ICatchEventConsumer> catchConsumers; private readonly IEnumerable<ICatchEventConsumer> catchConsumers;
private readonly IEventStream eventStream; private readonly IEventStream eventStream;
@ -31,7 +32,8 @@ namespace Squidex.Infrastructure.CQRS.Events
IEventStream eventStream, IEventStream eventStream,
IEnumerable<ILiveEventConsumer> liveConsumers, IEnumerable<ILiveEventConsumer> liveConsumers,
IEnumerable<ICatchEventConsumer> catchConsumers, IEnumerable<ICatchEventConsumer> catchConsumers,
EventDataFormatter formatter) EventDataFormatter formatter,
bool canCatch = true)
{ {
Guard.NotNull(logger, nameof(logger)); Guard.NotNull(logger, nameof(logger));
Guard.NotNull(formatter, nameof(formatter)); Guard.NotNull(formatter, nameof(formatter));
@ -41,6 +43,7 @@ namespace Squidex.Infrastructure.CQRS.Events
this.logger = logger; this.logger = logger;
this.formatter = formatter; this.formatter = formatter;
this.canCatch = canCatch;
this.eventStream = eventStream; this.eventStream = eventStream;
this.liveConsumers = liveConsumers; this.liveConsumers = liveConsumers;
this.catchConsumers = catchConsumers; this.catchConsumers = catchConsumers;
@ -70,7 +73,7 @@ namespace Squidex.Infrastructure.CQRS.Events
{ {
DispatchConsumers(catchConsumers.OfType<IEventConsumer>().Union(liveConsumers), @event); DispatchConsumers(catchConsumers.OfType<IEventConsumer>().Union(liveConsumers), @event);
} }
else else if (canCatch)
{ {
DispatchConsumers(catchConsumers, @event); DispatchConsumers(catchConsumers, @event);
} }

32
src/Squidex.Infrastructure/CQRS/Events/InMemoryEventBus.cs

@ -0,0 +1,32 @@
// ==========================================================================
// InMemoryEventBus.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using System;
using System.Reactive.Subjects;
namespace Squidex.Infrastructure.CQRS.Events
{
public class InMemoryEventBus : IEventPublisher, IEventStream
{
private readonly Subject<EventData> subject = new Subject<EventData>();
public void Dispose()
{
}
public void Publish(EventData eventData)
{
subject.OnNext(eventData);
}
public void Connect(string queueName, Action<EventData> received)
{
subject.Subscribe(received);
}
}
}

9
src/Squidex.Infrastructure/CQRS/Replay/ReplayGenerator.cs

@ -15,13 +15,15 @@ using Squidex.Infrastructure.CQRS.Events;
namespace Squidex.Infrastructure.CQRS.Replay namespace Squidex.Infrastructure.CQRS.Replay
{ {
public sealed class ReplayGenerator public sealed class ReplayGenerator : ICliCommand
{ {
private readonly ILogger<ReplayGenerator> logger; private readonly ILogger<ReplayGenerator> logger;
private readonly IEventStore eventStore; private readonly IEventStore eventStore;
private readonly IEventPublisher eventPublisher; private readonly IEventPublisher eventPublisher;
private readonly IEnumerable<IReplayableStore> stores; private readonly IEnumerable<IReplayableStore> stores;
public string Name { get; } = "replay";
public ReplayGenerator( public ReplayGenerator(
ILogger<ReplayGenerator> logger, ILogger<ReplayGenerator> logger,
IEventStore eventStore, IEventStore eventStore,
@ -39,6 +41,11 @@ namespace Squidex.Infrastructure.CQRS.Replay
this.eventPublisher = eventPublisher; this.eventPublisher = eventPublisher;
} }
public void Execute(string[] args)
{
ReplayAllAsync().Wait();
}
public async Task ReplayAllAsync() public async Task ReplayAllAsync()
{ {
logger.LogDebug("Starting to replay all events"); logger.LogDebug("Starting to replay all events");

29
src/Squidex.Infrastructure/ConfigurationException.cs

@ -0,0 +1,29 @@
// ==========================================================================
// ConfigurationException.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using System;
namespace Squidex.Infrastructure
{
public sealed class ConfigurationException : Exception
{
public ConfigurationException()
{
}
public ConfigurationException(string message)
: base(message)
{
}
public ConfigurationException(string message, Exception inner)
: base(message, inner)
{
}
}
}

10
src/Squidex.Read.MongoDb/MyMongoDbOptions.cs → src/Squidex.Infrastructure/ICliCommand.cs

@ -1,17 +1,17 @@
// ========================================================================== // ==========================================================================
// MyMongoDbOptions.cs // ICommand.cs
// Squidex Headless CMS // Squidex Headless CMS
// ========================================================================== // ==========================================================================
// Copyright (c) Squidex Group // Copyright (c) Squidex Group
// All rights reserved. // All rights reserved.
// ========================================================================== // ==========================================================================
namespace Squidex.Read.MongoDb namespace Squidex.Infrastructure
{ {
public class MyMongoDbOptions public interface ICliCommand
{ {
public string ConnectionString { get; set; } string Name { get; }
public string DatabaseName { get; set; } void Execute(string[] args);
} }
} }

15
src/Squidex.Infrastructure/IExternalSystem.cs

@ -0,0 +1,15 @@
// ==========================================================================
// IExternalSystem.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
namespace Squidex.Infrastructure
{
public interface IExternalSystem
{
void CheckConnection();
}
}

100
src/Squidex.Read.MongoDb/MongoDbModule.cs

@ -1,100 +0,0 @@
// ==========================================================================
// MongoDbModule.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using Autofac;
using IdentityServer4.Stores;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.MongoDB;
using Microsoft.Extensions.Options;
using MongoDB.Driver;
using Squidex.Infrastructure.CQRS.Events;
using Squidex.Infrastructure.CQRS.Replay;
using Squidex.Infrastructure.MongoDb;
using Squidex.Read.Apps.Repositories;
using Squidex.Read.Contents.Repositories;
using Squidex.Read.History.Repositories;
using Squidex.Read.MongoDb.Apps;
using Squidex.Read.MongoDb.Contents;
using Squidex.Read.MongoDb.History;
using Squidex.Read.MongoDb.Infrastructure;
using Squidex.Read.MongoDb.Schemas;
using Squidex.Read.MongoDb.Users;
using Squidex.Read.Schemas.Repositories;
using Squidex.Read.Users.Repositories;
namespace Squidex.Read.MongoDb
{
public class MongoDbModule : Module
{
protected override void Load(ContainerBuilder builder)
{
RefTokenSerializer.Register();
builder.Register(context =>
{
var options = context.Resolve<IOptions<MyMongoDbOptions>>().Value;
var mongoDbClient = new MongoClient(options.ConnectionString);
var mongoDatabase = mongoDbClient.GetDatabase(options.DatabaseName);
return mongoDatabase;
}).SingleInstance();
builder.Register<IUserStore<IdentityUser>>(context =>
{
var usersCollection = context.Resolve<IMongoDatabase>().GetCollection<IdentityUser>("Identity_Users");
IndexChecks.EnsureUniqueIndexOnNormalizedEmail(usersCollection);
IndexChecks.EnsureUniqueIndexOnNormalizedUserName(usersCollection);
return new UserStore<IdentityUser>(usersCollection);
}).SingleInstance();
builder.Register<IRoleStore<IdentityRole>>(context =>
{
var rolesCollection = context.Resolve<IMongoDatabase>().GetCollection<IdentityRole>("Identity_Roles");
IndexChecks.EnsureUniqueIndexOnNormalizedRoleName(rolesCollection);
return new RoleStore<IdentityRole>(rolesCollection);
}).SingleInstance();
builder.RegisterType<MongoPersistedGrantStore>()
.As<IPersistedGrantStore>()
.SingleInstance();
builder.RegisterType<MongoUserRepository>()
.As<IUserRepository>()
.InstancePerLifetimeScope();
builder.RegisterType<MongoContentRepository>()
.As<IContentRepository>()
.As<ICatchEventConsumer>()
.As<IReplayableStore>()
.SingleInstance();
builder.RegisterType<MongoHistoryEventRepository>()
.As<IHistoryEventRepository>()
.As<ICatchEventConsumer>()
.As<IReplayableStore>()
.SingleInstance();
builder.RegisterType<MongoSchemaRepository>()
.As<ISchemaRepository>()
.As<ICatchEventConsumer>()
.As<IReplayableStore>()
.SingleInstance();
builder.RegisterType<MongoAppRepository>()
.As<IAppRepository>()
.As<ICatchEventConsumer>()
.As<IReplayableStore>()
.SingleInstance();
}
}
}

38
src/Squidex.Read.MongoDb/MongoDbStoresExternalSystem.cs

@ -0,0 +1,38 @@
// ==========================================================================
// MongoDbStoresExternalSystem.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using System;
using MongoDB.Driver;
using Squidex.Infrastructure;
namespace Squidex.Read.MongoDb
{
public sealed class MongoDbStoresExternalSystem : IExternalSystem
{
private readonly IMongoDatabase database;
public MongoDbStoresExternalSystem(IMongoDatabase database)
{
Guard.NotNull(database, nameof(database));
this.database = database;
}
public void CheckConnection()
{
try
{
database.ListCollections();
}
catch (Exception e)
{
throw new ConfigurationException($"MongoDb Event Store failed to connect to database {database.DatabaseNamespace.DatabaseName}", e);
}
}
}
}

1
src/Squidex.Read.MongoDb/project.json

@ -1,6 +1,5 @@
{ {
"dependencies": { "dependencies": {
"Autofac": "4.3.0",
"IdentityServer4": "1.0.2", "IdentityServer4": "1.0.2",
"Microsoft.AspNetCore.Identity": "1.1.0", "Microsoft.AspNetCore.Identity": "1.1.0",
"Microsoft.AspNetCore.Identity.MongoDB": "1.0.2", "Microsoft.AspNetCore.Identity.MongoDB": "1.0.2",

2
src/Squidex/Config/Identity/MyIdentityOptions.cs

@ -18,8 +18,6 @@ namespace Squidex.Config.Identity
public string GoogleSecret { get; set; } public string GoogleSecret { get; set; }
public string KeysFolder { get; set; }
public bool RequiresHttps { get; set; } public bool RequiresHttps { get; set; }
} }
} }

2
tests/Squidex.Core.Tests/Contents/ContentDataTests.cs

@ -239,7 +239,7 @@ namespace Squidex.Core.Contents
{ {
{ "field1", 1 }, { "field1", 1 },
{ "field2", 4 }, { "field2", 4 },
{ "field3", 6 }, { "field3", 6 }
}; };
Assert.True(expected.EqualsDictionary(output)); Assert.True(expected.EqualsDictionary(output));

Loading…
Cancel
Save