mirror of https://github.com/Squidex/squidex.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
105 lines
3.7 KiB
105 lines
3.7 KiB
// ==========================================================================
|
|
// DefaultDomainObjectRepository.cs
|
|
// Squidex Headless CMS
|
|
// ==========================================================================
|
|
// Copyright (c) Squidex Group
|
|
// All rights reserved.
|
|
// ==========================================================================
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Threading.Tasks;
|
|
using Squidex.Infrastructure.CQRS.Events;
|
|
|
|
namespace Squidex.Infrastructure.CQRS.Commands
|
|
{
|
|
public sealed class DefaultDomainObjectRepository : IDomainObjectRepository
|
|
{
|
|
private readonly IStreamNameResolver nameResolver;
|
|
private readonly IDomainObjectFactory factory;
|
|
private readonly IEventStore eventStore;
|
|
private readonly EventDataFormatter formatter;
|
|
|
|
public DefaultDomainObjectRepository(
|
|
IDomainObjectFactory factory,
|
|
IEventStore eventStore,
|
|
IStreamNameResolver nameResolver,
|
|
EventDataFormatter formatter)
|
|
{
|
|
Guard.NotNull(factory, nameof(factory));
|
|
Guard.NotNull(formatter, nameof(formatter));
|
|
Guard.NotNull(eventStore, nameof(eventStore));
|
|
Guard.NotNull(nameResolver, nameof(nameResolver));
|
|
|
|
this.factory = factory;
|
|
this.formatter = formatter;
|
|
this.eventStore = eventStore;
|
|
this.nameResolver = nameResolver;
|
|
}
|
|
|
|
public async Task<TDomainObject> GetByIdAsync<TDomainObject>(Guid id, long? expectedVersion = null) where TDomainObject : class, IAggregate
|
|
{
|
|
var streamName = nameResolver.GetStreamName(typeof(TDomainObject), id);
|
|
|
|
var events = await eventStore.GetEventsAsync(streamName);
|
|
|
|
if (events.Count == 0)
|
|
{
|
|
throw new DomainObjectNotFoundException(id.ToString(), typeof(TDomainObject));
|
|
}
|
|
|
|
var domainObject = (TDomainObject)factory.CreateNew(typeof(TDomainObject), id);
|
|
|
|
foreach (var storedEvent in events)
|
|
{
|
|
var envelope = ParseOrNull(storedEvent);
|
|
|
|
if (envelope != null)
|
|
{
|
|
domainObject.ApplyEvent(envelope);
|
|
}
|
|
}
|
|
|
|
if (expectedVersion != null && domainObject.Version != expectedVersion.Value)
|
|
{
|
|
throw new DomainObjectVersionException(id.ToString(), typeof(TDomainObject), domainObject.Version, expectedVersion.Value);
|
|
}
|
|
|
|
return domainObject;
|
|
}
|
|
|
|
public async Task SaveAsync(IAggregate domainObject, ICollection<Envelope<IEvent>> events, Guid commitId)
|
|
{
|
|
Guard.NotNull(domainObject, nameof(domainObject));
|
|
|
|
var streamName = nameResolver.GetStreamName(domainObject.GetType(), domainObject.Id);
|
|
|
|
var versionCurrent = domainObject.Version;
|
|
var versionExpected = versionCurrent - events.Count;
|
|
|
|
var eventsToSave = events.Select(x => formatter.ToEventData(x, commitId)).ToList();
|
|
|
|
try
|
|
{
|
|
await eventStore.AppendEventsAsync(commitId, streamName, versionExpected, eventsToSave);
|
|
}
|
|
catch (WrongEventVersionException)
|
|
{
|
|
throw new DomainObjectVersionException(domainObject.Id.ToString(), domainObject.GetType(), versionCurrent, versionExpected);
|
|
}
|
|
}
|
|
|
|
private Envelope<IEvent> ParseOrNull(StoredEvent storedEvent)
|
|
{
|
|
try
|
|
{
|
|
return formatter.Parse(storedEvent.Data);
|
|
}
|
|
catch (TypeNameNotFoundException)
|
|
{
|
|
return null;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|