Browse Source

Got rid of archive

pull/282/head
Sebastian 8 years ago
parent
commit
eef11abdfa
  1. 35
      src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentRepository.cs
  2. 2
      src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentRepository_SnapshotStore.cs
  3. 7
      src/Squidex.Domain.Apps.Entities/Contents/ContentQueryService.cs
  4. 95
      src/Squidex.Domain.Apps.Entities/Contents/ContentVersionLoader.cs
  5. 2
      src/Squidex.Domain.Apps.Entities/Contents/IContentQueryService.cs
  6. 18
      src/Squidex.Domain.Apps.Entities/Contents/IContentVersionLoader.cs
  7. 2
      src/Squidex.Domain.Apps.Entities/Contents/Repositories/IContentRepository.cs
  8. 2
      src/Squidex.Domain.Apps.Entities/DomainObjectState.cs
  9. 5
      src/Squidex/Areas/Api/Controllers/Content/ContentsController.cs
  10. 8
      tests/Squidex.Domain.Apps.Entities.Tests/Contents/GraphQL/GraphQLQueriesTests.cs

35
src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentRepository.cs

@ -26,12 +26,6 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents
public partial class MongoContentRepository : MongoRepositoryBase<MongoContentEntity>, IContentRepository
{
private readonly IAppProvider appProvider;
private readonly IMongoCollection<MongoContentEntity> archiveCollection;
protected IMongoCollection<MongoContentEntity> ArchiveCollection
{
get { return archiveCollection; }
}
public MongoContentRepository(IMongoDatabase database, IAppProvider appProvider)
: base(database)
@ -39,8 +33,6 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents
Guard.NotNull(appProvider, nameof(appProvider));
this.appProvider = appProvider;
archiveCollection = database.GetCollection<MongoContentEntity>("States_Contents_Archive");
}
protected override string CollectionName()
@ -52,15 +44,6 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents
{
await collection.Indexes.TryDropOneAsync("si_1_st_1_dl_1_dt_text");
await archiveCollection.Indexes.CreateOneAsync(
Index
.Ascending(x => x.ScheduledTo));
await archiveCollection.Indexes.CreateOneAsync(
Index
.Ascending(x => x.Id)
.Ascending(x => x.Version));
await collection.Indexes.CreateOneAsync(
Index
.Text(x => x.DataText)
@ -150,17 +133,6 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents
return ids.Except(contentEntities.Select(x => Guid.Parse(x["id"].AsString))).ToList();
}
public async Task<IContentEntity> FindContentAsync(IAppEntity app, ISchemaEntity schema, Guid id, long version)
{
var contentEntity =
await ArchiveCollection.Find(x => x.Id == id && x.Version >= version).SortBy(x => x.Version)
.FirstOrDefaultAsync();
contentEntity?.ParseData(schema.SchemaDef);
return contentEntity;
}
public async Task<IContentEntity> FindContentAsync(IAppEntity app, ISchemaEntity schema, Guid id)
{
var contentEntity =
@ -180,12 +152,5 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents
callback(c);
});
}
public override async Task ClearAsync()
{
await Database.DropCollectionAsync("States_Contents_Archive");
await base.ClearAsync();
}
}
}

2
src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentRepository_SnapshotStore.cs

@ -88,8 +88,6 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents
}
document.DocumentId = $"{key}_{newVersion}";
await ArchiveCollection.ReplaceOneAsync(x => x.DocumentId == document.DocumentId, document, Upsert);
}
private async Task<ISchemaEntity> GetSchemaAsync(Guid appId, Guid schemaId)

7
src/Squidex.Domain.Apps.Entities/Contents/ContentQueryService.cs

@ -48,7 +48,7 @@ namespace Squidex.Domain.Apps.Entities.Contents
this.modelBuilder = modelBuilder;
}
public async Task<(ISchemaEntity Schema, IContentEntity Content)> FindContentAsync(IAppEntity app, string schemaIdOrName, ClaimsPrincipal user, Guid id, long version = -1)
public async Task<(ISchemaEntity Schema, IContentEntity Content)> FindContentAsync(IAppEntity app, string schemaIdOrName, ClaimsPrincipal user, Guid id)
{
Guard.NotNull(app, nameof(app));
Guard.NotNull(user, nameof(user));
@ -58,10 +58,7 @@ namespace Squidex.Domain.Apps.Entities.Contents
var schema = await FindSchemaAsync(app, schemaIdOrName);
var content =
version > EtagVersion.Empty ?
await contentRepository.FindContentAsync(app, schema, id, version) :
await contentRepository.FindContentAsync(app, schema, id);
var content = await contentRepository.FindContentAsync(app, schema, id);
if (content == null || (content.Status != Status.Published && !isFrontendClient))
{

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

@ -0,0 +1,95 @@
// ==========================================================================
// 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 Squidex.Domain.Apps.Core.Schemas;
using Squidex.Domain.Apps.Entities.Contents.State;
using Squidex.Domain.Apps.Entities.Schemas;
using Squidex.Domain.Apps.Entities.Schemas.State;
using Squidex.Infrastructure;
using Squidex.Infrastructure.States;
namespace Squidex.Domain.Apps.Entities.Contents
{
public sealed class ContentVersionLoader : IContentVersionLoader
{
private readonly IStore<Guid> store;
private readonly FieldRegistry registry;
public ContentVersionLoader(IStore<Guid> store, FieldRegistry registry)
{
Guard.NotNull(store, nameof(store));
Guard.NotNull(registry, nameof(registry));
this.store = store;
this.registry = registry;
}
public async Task<(ISchemaEntity Schema, IContentEntity Content)> LoadAsync(Guid id, int version)
{
var content = new ContentState();
var persistence = store.WithEventSourcing<ContentGrain, Guid>(id, e =>
{
if (content.Version < version)
{
content = content.Apply(e);
}
});
await persistence.ReadAsync();
if (content.Version != version)
{
throw new DomainObjectNotFoundException(id.ToString(), typeof(IContentEntity));
}
var (now, then) = await ReadSchema(content.SchemaId.Id, content.LastModified);
foreach (var key in content.Data.Keys)
{
if (IsFieldRemovedOrChanged(then.SchemaDef, now.SchemaDef, key))
{
content.Data.Remove(key);
}
}
return (then, content);
}
private static bool IsFieldRemovedOrChanged(Schema schemaThen, Schema schemaNow, string key)
{
return
!schemaThen.FieldsByName.TryGetValue(key, out var fieldThen) ||
!schemaNow.FieldsByName.TryGetValue(key, out var fieldNow) ||
fieldThen.GetType() != fieldNow.GetType();
}
private async Task<(ISchemaEntity, ISchemaEntity)> ReadSchema(Guid schemaId, Instant lastUpdate)
{
var state = new SchemaState();
var stateAtVersion = (SchemaState)null;
var persistence = store.WithEventSourcing<SchemaGrain, Guid>(schemaId, e =>
{
state = state.Apply(e, registry);
if (state.LastModified < lastUpdate)
{
stateAtVersion = state;
}
});
await persistence.ReadAsync();
return (state, stateAtVersion);
}
}
}

2
src/Squidex.Domain.Apps.Entities/Contents/IContentQueryService.cs

@ -21,7 +21,7 @@ namespace Squidex.Domain.Apps.Entities.Contents
Task<(ISchemaEntity Schema, IResultList<IContentEntity> Contents)> QueryAsync(IAppEntity app, string schemaIdOrName, ClaimsPrincipal user, bool archived, string query);
Task<(ISchemaEntity Schema, IContentEntity Content)> FindContentAsync(IAppEntity app, string schemaIdOrName, ClaimsPrincipal user, Guid id, long version = EtagVersion.Any);
Task<(ISchemaEntity Schema, IContentEntity Content)> FindContentAsync(IAppEntity app, string schemaIdOrName, ClaimsPrincipal user, Guid id);
Task<ISchemaEntity> FindSchemaAsync(IAppEntity app, string schemaIdOrName);
}

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

@ -0,0 +1,18 @@
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System;
using System.Threading.Tasks;
using Squidex.Domain.Apps.Entities.Schemas;
namespace Squidex.Domain.Apps.Entities.Contents
{
public interface IContentVersionLoader
{
Task<(ISchemaEntity Schema, IContentEntity Content)> LoadAsync(Guid id, int version);
}
}

2
src/Squidex.Domain.Apps.Entities/Contents/Repositories/IContentRepository.cs

@ -27,8 +27,6 @@ namespace Squidex.Domain.Apps.Entities.Contents.Repositories
Task<IContentEntity> FindContentAsync(IAppEntity app, ISchemaEntity schema, Guid id);
Task<IContentEntity> FindContentAsync(IAppEntity app, ISchemaEntity schema, Guid id, long version);
Task QueryScheduledWithoutDataAsync(Instant now, Func<IContentEntity, Task> callback);
}
}

2
src/Squidex.Domain.Apps.Entities/DomainObjectState.cs

@ -40,7 +40,7 @@ namespace Squidex.Domain.Apps.Entities
public Instant LastModified { get; set; }
[JsonProperty]
public long Version { get; set; }
public long Version { get; set; } = EtagVersion.Empty;
public T Clone()
{

5
src/Squidex/Areas/Api/Controllers/Content/ContentsController.cs

@ -32,14 +32,17 @@ namespace Squidex.Areas.Api.Controllers.Contents
public sealed class ContentsController : ApiController
{
private readonly IContentQueryService contentQuery;
private readonly IContentVersionLoader contentVersionLoader;
private readonly IGraphQLService graphQl;
public ContentsController(ICommandBus commandBus,
IContentQueryService contentQuery,
IContentVersionLoader contentVersionLoader,
IGraphQLService graphQl)
: base(commandBus)
{
this.contentQuery = contentQuery;
this.contentVersionLoader = contentVersionLoader;
this.graphQl = graphQl;
}
@ -195,7 +198,7 @@ namespace Squidex.Areas.Api.Controllers.Contents
[ApiCosts(1)]
public async Task<IActionResult> GetContentVersion(string app, string name, Guid id, int version)
{
var content = await contentQuery.FindContentAsync(App, name, User, id, version);
var content = await contentVersionLoader.LoadAsync(id, version);
var response = SimpleMapper.Map(content.Content, new ContentDto());

8
tests/Squidex.Domain.Apps.Entities.Tests/Contents/GraphQL/GraphQLQueriesTests.cs

@ -517,7 +517,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL
}}
}}";
A.CallTo(() => contentQuery.FindContentAsync(app, schema.Id.ToString(), user, contentId, EtagVersion.Any))
A.CallTo(() => contentQuery.FindContentAsync(app, schema.Id.ToString(), user, contentId))
.Returns((schema, content));
var result = await sut.QueryAsync(app, user, new GraphQLQuery { Query = query });
@ -610,7 +610,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL
var refContents = new List<IContentEntity> { contentRef };
A.CallTo(() => contentQuery.FindContentAsync(app, schema.Id.ToString(), user, contentId, EtagVersion.Any))
A.CallTo(() => contentQuery.FindContentAsync(app, schema.Id.ToString(), user, contentId))
.Returns((schema, content));
A.CallTo(() => contentQuery.QueryAsync(app, schema.Id.ToString(), user, false, A<HashSet<Guid>>.That.Matches(x => x.Contains(contentRefId))))
@ -670,7 +670,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL
var refAssets = new List<IAssetEntity> { assetRef };
A.CallTo(() => contentQuery.FindContentAsync(app, schema.Id.ToString(), user, contentId, EtagVersion.Any))
A.CallTo(() => contentQuery.FindContentAsync(app, schema.Id.ToString(), user, contentId))
.Returns((schema, content));
A.CallTo(() => assetRepository.QueryAsync(app.Id, A<HashSet<Guid>>.That.Matches(x => x.Contains(assetRefId))))
@ -729,7 +729,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL
}}
}}";
A.CallTo(() => contentQuery.FindContentAsync(app, schema.Id.ToString(), user, contentId, EtagVersion.Any))
A.CallTo(() => contentQuery.FindContentAsync(app, schema.Id.ToString(), user, contentId))
.Returns((schema, content));
var result = await sut.QueryAsync(app, user, new GraphQLQuery { Query = query });

Loading…
Cancel
Save