mirror of https://github.com/Squidex/squidex.git
20 changed files with 467 additions and 408 deletions
@ -0,0 +1,67 @@ |
|||||
|
// ==========================================================================
|
||||
|
// MongoAppRepository_SnapshotStore.cs
|
||||
|
// Squidex Headless CMS
|
||||
|
// ==========================================================================
|
||||
|
// Copyright (c) Squidex Group
|
||||
|
// All rights reserved.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
using System; |
||||
|
using System.Linq; |
||||
|
using System.Threading.Tasks; |
||||
|
using MongoDB.Driver; |
||||
|
using Squidex.Domain.Apps.Entities.Apps.State; |
||||
|
using Squidex.Infrastructure; |
||||
|
using Squidex.Infrastructure.States; |
||||
|
|
||||
|
namespace Squidex.Domain.Apps.Entities.MongoDb.Apps |
||||
|
{ |
||||
|
public sealed partial class MongoAppRepository : ISnapshotStore<AppState, Guid> |
||||
|
{ |
||||
|
public async Task<(AppState Value, long Version)> ReadAsync(Guid key) |
||||
|
{ |
||||
|
var existing = |
||||
|
await Collection.Find(x => x.Id == key) |
||||
|
.FirstOrDefaultAsync(); |
||||
|
|
||||
|
if (existing != null) |
||||
|
{ |
||||
|
return (existing.State, existing.Version); |
||||
|
} |
||||
|
|
||||
|
return (null, EtagVersion.NotFound); |
||||
|
} |
||||
|
|
||||
|
public async Task WriteAsync(Guid key, AppState value, long oldVersion, long newVersion) |
||||
|
{ |
||||
|
try |
||||
|
{ |
||||
|
await Collection.UpdateOneAsync(x => x.Id == key && x.Version == oldVersion, |
||||
|
Update |
||||
|
.Set(x => x.UserIds, value.Contributors.Keys.ToArray()) |
||||
|
.Set(x => x.Name, value.Name) |
||||
|
.Set(x => x.State, value) |
||||
|
.Set(x => x.Version, newVersion), |
||||
|
Upsert); |
||||
|
} |
||||
|
catch (MongoWriteException ex) |
||||
|
{ |
||||
|
if (ex.WriteError.Category == ServerErrorCategory.DuplicateKey) |
||||
|
{ |
||||
|
var existingVersion = |
||||
|
await Collection.Find(x => x.Id == key) |
||||
|
.Project<MongoAppEntity>(Projection.Exclude(x => x.Id)).FirstOrDefaultAsync(); |
||||
|
|
||||
|
if (existingVersion != null) |
||||
|
{ |
||||
|
throw new InconsistentStateException(existingVersion.Version, oldVersion, ex); |
||||
|
} |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
throw; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,65 @@ |
|||||
|
// ==========================================================================
|
||||
|
// MongoAssetRepository_SnapshotStore.cs
|
||||
|
// Squidex Headless CMS
|
||||
|
// ==========================================================================
|
||||
|
// Copyright (c) Squidex Group
|
||||
|
// All rights reserved.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
using System; |
||||
|
using System.Threading.Tasks; |
||||
|
using MongoDB.Driver; |
||||
|
using Squidex.Domain.Apps.Entities.Assets.State; |
||||
|
using Squidex.Infrastructure; |
||||
|
using Squidex.Infrastructure.MongoDb; |
||||
|
using Squidex.Infrastructure.States; |
||||
|
|
||||
|
namespace Squidex.Domain.Apps.Entities.MongoDb.Assets |
||||
|
{ |
||||
|
public sealed partial class MongoAssetRepository : ISnapshotStore<AssetState, Guid> |
||||
|
{ |
||||
|
public async Task<(AssetState Value, long Version)> ReadAsync(Guid key) |
||||
|
{ |
||||
|
var existing = |
||||
|
await Collection.Find(x => x.Id == key) |
||||
|
.FirstOrDefaultAsync(); |
||||
|
|
||||
|
if (existing != null) |
||||
|
{ |
||||
|
return (existing.State, existing.Version); |
||||
|
} |
||||
|
|
||||
|
return (null, EtagVersion.NotFound); |
||||
|
} |
||||
|
|
||||
|
public async Task WriteAsync(Guid key, AssetState value, long oldVersion, long newVersion) |
||||
|
{ |
||||
|
try |
||||
|
{ |
||||
|
await Collection.UpdateOneAsync(x => x.Id == key && x.Version == oldVersion, |
||||
|
Update |
||||
|
.Set(x => x.State, value) |
||||
|
.Set(x => x.Version, newVersion), |
||||
|
Upsert); |
||||
|
} |
||||
|
catch (MongoWriteException ex) |
||||
|
{ |
||||
|
if (ex.WriteError.Category == ServerErrorCategory.DuplicateKey) |
||||
|
{ |
||||
|
var existingVersion = |
||||
|
await Collection.Find(x => x.Id == key).Only(x => x.Id, x => x.Version) |
||||
|
.FirstOrDefaultAsync(); |
||||
|
|
||||
|
if (existingVersion != null) |
||||
|
{ |
||||
|
throw new InconsistentStateException(existingVersion["Version"].AsInt64, oldVersion, ex); |
||||
|
} |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
throw; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,98 @@ |
|||||
|
// ==========================================================================
|
||||
|
// MongoContentRepository_SnapshotStore.cs
|
||||
|
// Squidex Headless CMS
|
||||
|
// ==========================================================================
|
||||
|
// Copyright (c) Squidex Group
|
||||
|
// All rights reserved.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
using System; |
||||
|
using System.Threading.Tasks; |
||||
|
using MongoDB.Driver; |
||||
|
using Squidex.Domain.Apps.Core.ConvertContent; |
||||
|
using Squidex.Domain.Apps.Entities.Contents.State; |
||||
|
using Squidex.Infrastructure; |
||||
|
using Squidex.Infrastructure.MongoDb; |
||||
|
using Squidex.Infrastructure.Reflection; |
||||
|
using Squidex.Infrastructure.States; |
||||
|
|
||||
|
namespace Squidex.Domain.Apps.Entities.MongoDb.Contents |
||||
|
{ |
||||
|
public partial class MongoContentRepository : ISnapshotStore<ContentState, Guid> |
||||
|
{ |
||||
|
public async Task<(ContentState Value, long Version)> ReadAsync(Guid key) |
||||
|
{ |
||||
|
var contentEntity = |
||||
|
await Collection.Find(x => x.Id == key).SortByDescending(x => x.Version) |
||||
|
.FirstOrDefaultAsync(); |
||||
|
|
||||
|
if (contentEntity != null) |
||||
|
{ |
||||
|
var schema = await appProvider.GetSchemaAsync(contentEntity.AppId, contentEntity.SchemaId, true); |
||||
|
|
||||
|
if (schema == null) |
||||
|
{ |
||||
|
throw new InvalidOperationException($"Cannot find schema {contentEntity.SchemaId}"); |
||||
|
} |
||||
|
|
||||
|
contentEntity?.ParseData(schema.SchemaDef); |
||||
|
|
||||
|
return (SimpleMapper.Map(contentEntity, new ContentState()), contentEntity.Version); |
||||
|
} |
||||
|
|
||||
|
return (null, EtagVersion.NotFound); |
||||
|
} |
||||
|
|
||||
|
public async Task WriteAsync(Guid key, ContentState value, long oldVersion, long newVersion) |
||||
|
{ |
||||
|
var documentId = $"{key}_{newVersion}"; |
||||
|
|
||||
|
if (value.SchemaId == Guid.Empty) |
||||
|
{ |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
var schema = await appProvider.GetSchemaAsync(value.AppId, value.SchemaId, true); |
||||
|
|
||||
|
if (schema == null) |
||||
|
{ |
||||
|
throw new InvalidOperationException($"Cannot find schema {value.SchemaId}"); |
||||
|
} |
||||
|
|
||||
|
var idData = value.Data?.ToIdModel(schema.SchemaDef, true); |
||||
|
|
||||
|
var document = SimpleMapper.Map(value, new MongoContentEntity |
||||
|
{ |
||||
|
DocumentId = documentId, |
||||
|
DataText = idData?.ToFullText(), |
||||
|
DataByIds = idData, |
||||
|
IsLatest = !value.IsDeleted, |
||||
|
ReferencedIds = idData?.ToReferencedIds(schema.SchemaDef), |
||||
|
}); |
||||
|
|
||||
|
try |
||||
|
{ |
||||
|
await Collection.InsertOneAsync(document); |
||||
|
await Collection.UpdateManyAsync(x => x.Id == value.Id && x.Version < value.Version, Update.Set(x => x.IsLatest, false)); |
||||
|
} |
||||
|
catch (MongoWriteException ex) |
||||
|
{ |
||||
|
if (ex.WriteError.Category == ServerErrorCategory.DuplicateKey) |
||||
|
{ |
||||
|
var existingVersion = |
||||
|
await Collection.Find(x => x.Id == value.Id && x.IsLatest).Only(x => x.Id, x => x.Version) |
||||
|
.FirstOrDefaultAsync(); |
||||
|
|
||||
|
if (existingVersion != null) |
||||
|
{ |
||||
|
throw new InconsistentStateException(existingVersion["vs"].AsInt64, oldVersion, ex); |
||||
|
} |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
throw; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,67 @@ |
|||||
|
// ==========================================================================
|
||||
|
// MongoRuleRepository_SnapshotStore.cs
|
||||
|
// Squidex Headless CMS
|
||||
|
// ==========================================================================
|
||||
|
// Copyright (c) Squidex Group
|
||||
|
// All rights reserved.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
using System; |
||||
|
using System.Threading.Tasks; |
||||
|
using MongoDB.Driver; |
||||
|
using Squidex.Domain.Apps.Entities.Rules.State; |
||||
|
using Squidex.Infrastructure; |
||||
|
using Squidex.Infrastructure.MongoDb; |
||||
|
using Squidex.Infrastructure.States; |
||||
|
|
||||
|
namespace Squidex.Domain.Apps.Entities.MongoDb.Rules |
||||
|
{ |
||||
|
public sealed partial class MongoRuleRepository : ISnapshotStore<RuleState, Guid> |
||||
|
{ |
||||
|
public async Task<(RuleState Value, long Version)> ReadAsync(Guid key) |
||||
|
{ |
||||
|
var existing = |
||||
|
await Collection.Find(x => x.Id == key) |
||||
|
.FirstOrDefaultAsync(); |
||||
|
|
||||
|
if (existing != null) |
||||
|
{ |
||||
|
return (existing.State, existing.Version); |
||||
|
} |
||||
|
|
||||
|
return (null, EtagVersion.NotFound); |
||||
|
} |
||||
|
|
||||
|
public async Task WriteAsync(Guid key, RuleState value, long oldVersion, long newVersion) |
||||
|
{ |
||||
|
try |
||||
|
{ |
||||
|
await Collection.UpdateOneAsync(x => x.Id == key && x.Version == oldVersion, |
||||
|
Update |
||||
|
.Set(x => x.State, value) |
||||
|
.Set(x => x.AppId, value.AppId) |
||||
|
.Set(x => x.IsDeleted, value.IsDeleted) |
||||
|
.Set(x => x.Version, newVersion), |
||||
|
Upsert); |
||||
|
} |
||||
|
catch (MongoWriteException ex) |
||||
|
{ |
||||
|
if (ex.WriteError.Category == ServerErrorCategory.DuplicateKey) |
||||
|
{ |
||||
|
var existingVersion = |
||||
|
await Collection.Find(x => x.Id == key).Only(x => x.Id, x => x.Version) |
||||
|
.FirstOrDefaultAsync(); |
||||
|
|
||||
|
if (existingVersion != null) |
||||
|
{ |
||||
|
throw new InconsistentStateException(existingVersion["Version"].AsInt64, oldVersion, ex); |
||||
|
} |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
throw; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,67 @@ |
|||||
|
// ==========================================================================
|
||||
|
// MongoSchemaRepository_SnapshotStore.cs
|
||||
|
// Squidex Headless CMS
|
||||
|
// ==========================================================================
|
||||
|
// Copyright (c) Squidex Group
|
||||
|
// All rights reserved.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
using System; |
||||
|
using System.Threading.Tasks; |
||||
|
using MongoDB.Driver; |
||||
|
using Squidex.Domain.Apps.Entities.Schemas.State; |
||||
|
using Squidex.Infrastructure; |
||||
|
using Squidex.Infrastructure.MongoDb; |
||||
|
using Squidex.Infrastructure.States; |
||||
|
|
||||
|
namespace Squidex.Domain.Apps.Entities.MongoDb.Schemas |
||||
|
{ |
||||
|
public sealed partial class MongoSchemaRepository : ISnapshotStore<SchemaState, Guid> |
||||
|
{ |
||||
|
public async Task<(SchemaState Value, long Version)> ReadAsync(Guid key) |
||||
|
{ |
||||
|
var existing = |
||||
|
await Collection.Find(x => x.Id == key) |
||||
|
.FirstOrDefaultAsync(); |
||||
|
|
||||
|
if (existing != null) |
||||
|
{ |
||||
|
return (existing.State, existing.Version); |
||||
|
} |
||||
|
|
||||
|
return (null, EtagVersion.NotFound); |
||||
|
} |
||||
|
|
||||
|
public async Task WriteAsync(Guid key, SchemaState value, long oldVersion, long newVersion) |
||||
|
{ |
||||
|
try |
||||
|
{ |
||||
|
await Collection.UpdateOneAsync(x => x.Id == key && x.Version == oldVersion, |
||||
|
Update |
||||
|
.Set(x => x.State, value) |
||||
|
.Set(x => x.AppId, value.AppId) |
||||
|
.Set(x => x.Name, value.Name) |
||||
|
.Set(x => x.Version, newVersion), |
||||
|
Upsert); |
||||
|
} |
||||
|
catch (MongoWriteException ex) |
||||
|
{ |
||||
|
if (ex.WriteError.Category == ServerErrorCategory.DuplicateKey) |
||||
|
{ |
||||
|
var existingVersion = |
||||
|
await Collection.Find(x => x.Id == key).Only(x => x.Version) |
||||
|
.FirstOrDefaultAsync(); |
||||
|
|
||||
|
if (existingVersion != null) |
||||
|
{ |
||||
|
throw new InconsistentStateException(existingVersion["Version"].AsInt64, oldVersion, ex); |
||||
|
} |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
throw; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue