Browse Source

Started with event enricher.

pull/306/head
Sebastian 8 years ago
parent
commit
91cd235c02
  1. 2
      src/Squidex.Domain.Apps.Core.Model/Rules/Triggers/ContentChangedTriggerSchema.cs
  2. 2
      src/Squidex.Domain.Apps.Core.Operations/HandleRules/Actions/AlgoliaActionHandler.cs
  3. 6
      src/Squidex.Domain.Apps.Core.Operations/HandleRules/Actions/ElasticSearchActionHandler.cs
  4. 3
      src/Squidex.Domain.Apps.Core.Operations/HandleRules/EnrichedEvents/EnrichedContentEventAction.cs
  5. 34
      src/Squidex.Domain.Apps.Core.Operations/HandleRules/Triggers/ContentChangedTriggerHandler.cs
  6. 33
      src/Squidex.Domain.Apps.Entities/Contents/ContentVersionLoader.cs
  7. 123
      src/Squidex.Domain.Apps.Entities/Rules/EventEnricher.cs
  8. 5
      src/Squidex/Areas/Api/Controllers/Rules/Models/Triggers/ContentChangedTriggerSchemaDto.cs

2
src/Squidex.Domain.Apps.Core.Model/Rules/Triggers/ContentChangedTriggerSchema.cs

@ -20,5 +20,7 @@ namespace Squidex.Domain.Apps.Core.Rules.Triggers
public bool SendDelete { get; set; } public bool SendDelete { get; set; }
public bool SendPublish { get; set; } public bool SendPublish { get; set; }
public bool SendUnpublish { get; set; }
} }
} }

2
src/Squidex.Domain.Apps.Core.Operations/HandleRules/Actions/AlgoliaActionHandler.cs

@ -68,7 +68,7 @@ namespace Squidex.Domain.Apps.Core.HandleRules.Actions
}; };
if (contentEvent.Action == EnrichedContentEventAction.Deleted || if (contentEvent.Action == EnrichedContentEventAction.Deleted ||
contentEvent.Action == EnrichedContentEventAction.Archived) contentEvent.Action == EnrichedContentEventAction.Unpublished)
{ {
ruleDescription = $"Delete entry from Algolia index: {action.IndexName}"; ruleDescription = $"Delete entry from Algolia index: {action.IndexName}";
} }

6
src/Squidex.Domain.Apps.Core.Operations/HandleRules/Actions/ElasticSearchActionHandler.cs

@ -78,13 +78,13 @@ namespace Squidex.Domain.Apps.Core.HandleRules.Actions
}; };
if (contentEvent.Action == EnrichedContentEventAction.Deleted || if (contentEvent.Action == EnrichedContentEventAction.Deleted ||
contentEvent.Action == EnrichedContentEventAction.Archived) contentEvent.Action == EnrichedContentEventAction.Unpublished)
{ {
ruleDescription = $"Delete entry from Algolia index: {action.IndexName}"; ruleDescription = $"Delete entry index: {action.IndexName}";
} }
else else
{ {
ruleDescription = $"Upsert to ES index: {action.IndexName}"; ruleDescription = $"Upsert to index: {action.IndexName}";
ruleJob.Content = formatter.ToPayload(contentEvent); ruleJob.Content = formatter.ToPayload(contentEvent);
ruleJob.Content["objectID"] = contentId; ruleJob.Content["objectID"] = contentId;

3
src/Squidex.Domain.Apps.Core.Operations/HandleRules/EnrichedEvents/EnrichedContentEventAction.cs

@ -9,11 +9,10 @@ namespace Squidex.Domain.Apps.Core.HandleRules.EnrichedEvents
{ {
public enum EnrichedContentEventAction public enum EnrichedContentEventAction
{ {
Archived,
Created, Created,
Deleted, Deleted,
Published, Published,
Restored, Unpublished,
Updated Updated
} }
} }

34
src/Squidex.Domain.Apps.Core.Operations/HandleRules/Triggers/ContentChangedTriggerHandler.cs

@ -44,10 +44,36 @@ namespace Squidex.Domain.Apps.Core.HandleRules.Triggers
private static bool MatchsType(ContentChangedTriggerSchema schema, SchemaEvent @event) private static bool MatchsType(ContentChangedTriggerSchema schema, SchemaEvent @event)
{ {
return return
(schema.SendCreate && @event is ContentCreated) || IsCreate(schema, @event) ||
(schema.SendUpdate && @event is ContentUpdated) || IsUpdate(schema, @event) ||
(schema.SendDelete && @event is ContentDeleted) || IsDelete(schema, @event) ||
(schema.SendPublish && @event is ContentStatusChanged statusChanged && statusChanged.Status == Status.Published); IsPublished(schema, @event) ||
IsUnpublished(schema, @event);
}
private static bool IsPublished(ContentChangedTriggerSchema schema, SchemaEvent @event)
{
return schema.SendPublish && @event is ContentStatusChanged statusChanged && statusChanged.Status == Status.Published;
}
private static bool IsUnpublished(ContentChangedTriggerSchema schema, SchemaEvent @event)
{
return schema.SendUnpublish && @event is ContentStatusChanged statusChanged && statusChanged.Status != Status.Published;
}
private static bool IsCreate(ContentChangedTriggerSchema schema, SchemaEvent @event)
{
return schema.SendCreate && @event is ContentCreated;
}
private static bool IsUpdate(ContentChangedTriggerSchema schema, SchemaEvent @event)
{
return schema.SendUpdate && @event is ContentUpdated || schema.SendUpdate && @event is ContentChangesPublished;
}
private static bool IsDelete(ContentChangedTriggerSchema schema, SchemaEvent @event)
{
return (schema.SendDelete && @event is ContentDeleted);
} }
} }
} }

33
src/Squidex.Domain.Apps.Entities/Contents/ContentVersionLoader.cs

@ -7,52 +7,37 @@
using System; using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using Squidex.Domain.Apps.Core.Schemas; using Orleans;
using Squidex.Domain.Apps.Entities.Contents.State;
using Squidex.Infrastructure; using Squidex.Infrastructure;
using Squidex.Infrastructure.Log; using Squidex.Infrastructure.Log;
using Squidex.Infrastructure.States;
namespace Squidex.Domain.Apps.Entities.Contents namespace Squidex.Domain.Apps.Entities.Contents
{ {
public sealed class ContentVersionLoader : IContentVersionLoader public sealed class ContentVersionLoader : IContentVersionLoader
{ {
private readonly IStore<Guid> store; private readonly IGrainFactory grainFactory;
private readonly FieldRegistry registry;
public ContentVersionLoader(IStore<Guid> store, FieldRegistry registry) public ContentVersionLoader(IGrainFactory grainFactory)
{ {
Guard.NotNull(store, nameof(store)); Guard.NotNull(grainFactory, nameof(grainFactory));
Guard.NotNull(registry, nameof(registry));
this.store = store; this.grainFactory = grainFactory;
this.registry = registry;
} }
public async Task<IContentEntity> LoadAsync(Guid id, long version) public async Task<IContentEntity> LoadAsync(Guid id, long version)
{ {
using (Profiler.TraceMethod<ContentVersionLoader>()) using (Profiler.TraceMethod<ContentVersionLoader>())
{ {
var content = new ContentState(); var grain = grainFactory.GetGrain<IContentGrain>(id);
var persistence = store.WithEventSourcing<ContentGrain, Guid>(id, e =>
{
if (content.Version < version)
{
content = content.Apply(e);
content.Version++;
}
});
await persistence.ReadAsync(); var content = await grain.GetStateAsync(version);
if (content.Version != version) if (content.Value == null || content.Value.Version != version)
{ {
throw new DomainObjectNotFoundException(id.ToString(), typeof(IContentEntity)); throw new DomainObjectNotFoundException(id.ToString(), typeof(IContentEntity));
} }
return content; return content.Value;
} }
} }
} }

123
src/Squidex.Domain.Apps.Entities/Rules/EventEnricher.cs

@ -0,0 +1,123 @@
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System;
using System.Threading.Tasks;
using NodaTime;
using Orleans;
using Squidex.Domain.Apps.Core.Contents;
using Squidex.Domain.Apps.Core.HandleRules;
using Squidex.Domain.Apps.Core.HandleRules.EnrichedEvents;
using Squidex.Domain.Apps.Entities.Contents;
using Squidex.Domain.Apps.Events;
using Squidex.Domain.Apps.Events.Assets;
using Squidex.Domain.Apps.Events.Contents;
using Squidex.Infrastructure;
using Squidex.Infrastructure.EventSourcing;
using Squidex.Infrastructure.Reflection;
namespace Squidex.Domain.Apps.Entities.Rules
{
public sealed class EventEnricher : IEventEnricher
{
private readonly IGrainFactory grainFactory;
private readonly IClock clock;
public EventEnricher(IGrainFactory grainFactory, IClock clock)
{
Guard.NotNull(grainFactory, nameof(grainFactory));
Guard.NotNull(clock, nameof(clock));
this.grainFactory = grainFactory;
this.clock = clock;
}
public Task<EnrichedEvent> EnrichAsync(Envelope<AppEvent> @event)
{
Guard.NotNull(@event, nameof(@event));
if (@event.Payload is ContentEvent contentEvent)
{
return CreateContentEventAsync(contentEvent, @event);
}
if (@event.Payload is AssetEvent assetEvent)
{
}
return Task.FromResult<EnrichedEvent>(null);
}
private async Task<EnrichedEvent> CreateContentEventAsync(ContentEvent contentEvent, Envelope<AppEvent> @event)
{
var result = new EnrichedContentEvent();
var content =
(await grainFactory
.GetGrain<IContentGrain>(contentEvent.ContentId)
.GetStateAsync(@event.Headers.EventStreamNumber())).Value;
SimpleMapper.Map(content, result);
result.Data = content.Data ?? content.DataDraft;
switch (contentEvent)
{
case ContentCreated e:
result.Action = EnrichedContentEventAction.Created;
break;
case ContentDeleted e:
result.Action = EnrichedContentEventAction.Deleted;
break;
case ContentUpdated e:
result.Action = EnrichedContentEventAction.Updated;
break;
case ContentStatusChanged e:
if (e.Status == Status.Published)
{
result.Action = EnrichedContentEventAction.Published;
}
else
{
result.Action = EnrichedContentEventAction.Unpublished;
}
break;
}
result.Name = $"{content.SchemaId.Name.ToPascalCase()}{result.Action}";
SetDefault(result, @event);
return result;
}
private void SetDefault(EnrichedEvent result, Envelope<AppEvent> @event)
{
result.Timestamp =
@event.Headers.Contains(CommonHeaders.Timestamp) ?
@event.Headers.Timestamp() :
clock.GetCurrentInstant();
result.AggregateId =
@event.Headers.Contains(CommonHeaders.AggregateId) ?
@event.Headers.AggregateId() :
Guid.NewGuid();
if (@event.Payload is SquidexEvent squidexEvent)
{
result.Actor = squidexEvent.Actor;
}
if (@event.Payload is AppEvent appEvent)
{
result.AppId = appEvent.AppId;
}
}
}
}

5
src/Squidex/Areas/Api/Controllers/Rules/Models/Triggers/ContentChangedTriggerSchemaDto.cs

@ -35,5 +35,10 @@ namespace Squidex.Areas.Api.Controllers.Rules.Models.Triggers
/// Determines whether to handle the event when a content is published. /// Determines whether to handle the event when a content is published.
/// </summary> /// </summary>
public bool SendPublish { get; set; } public bool SendPublish { get; set; }
/// <summary>
/// Determines whether to handle the event when a content is unpublished.
/// </summary>
public bool SendUnpublish { get; set; }
} }
} }

Loading…
Cancel
Save