mirror of https://github.com/Squidex/squidex.git
11 changed files with 290 additions and 6 deletions
@ -0,0 +1,40 @@ |
|||
// ==========================================================================
|
|||
// MongoAssetStatsEntity.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using MongoDB.Bson; |
|||
using MongoDB.Bson.Serialization.Attributes; |
|||
using Squidex.Read.Assets; |
|||
|
|||
namespace Squidex.Read.MongoDb.Assets |
|||
{ |
|||
public sealed class MongoAssetStatsEntity : IAssetStatsEntity |
|||
{ |
|||
[BsonId] |
|||
[BsonElement] |
|||
[BsonRepresentation(BsonType.String)] |
|||
public string Id { get; set; } |
|||
|
|||
[BsonRequired] |
|||
[BsonElement] |
|||
[BsonDateTimeOptions(DateOnly = true)] |
|||
public DateTime Date { get; set; } |
|||
|
|||
[BsonRequired] |
|||
[BsonElement] |
|||
public Guid AppId { get; set; } |
|||
|
|||
[BsonRequired] |
|||
[BsonElement] |
|||
public long TotalSize { get; set; } |
|||
|
|||
[BsonRequired] |
|||
[BsonElement] |
|||
public long TotalCount { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,91 @@ |
|||
// ==========================================================================
|
|||
// MongoAssetStatsRepository.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 MongoDB.Driver; |
|||
using Squidex.Infrastructure; |
|||
using Squidex.Infrastructure.CQRS.Events; |
|||
using Squidex.Infrastructure.MongoDb; |
|||
using Squidex.Read.Assets; |
|||
using Squidex.Read.Assets.Repositories; |
|||
|
|||
namespace Squidex.Read.MongoDb.Assets |
|||
{ |
|||
public partial class MongoAssetStatsRepository : MongoRepositoryBase<MongoAssetStatsEntity>, IAssetStatsRepository, IEventConsumer |
|||
{ |
|||
public MongoAssetStatsRepository(IMongoDatabase database) |
|||
: base(database) |
|||
{ |
|||
} |
|||
|
|||
protected override string CollectionName() |
|||
{ |
|||
return "Projections_AssetStats"; |
|||
} |
|||
|
|||
protected override Task SetupCollectionAsync(IMongoCollection<MongoAssetStatsEntity> collection) |
|||
{ |
|||
return Task.WhenAll( |
|||
collection.Indexes.CreateOneAsync(IndexKeys.Ascending(x => x.AppId).Ascending(x => x.Date)), |
|||
collection.Indexes.CreateOneAsync(IndexKeys.Ascending(x => x.AppId).Descending(x => x.Date))); |
|||
} |
|||
|
|||
public async Task<IReadOnlyList<IAssetStatsEntity>> QueryAsync(Guid appId, DateTime fromDate, DateTime toDate) |
|||
{ |
|||
var originalSizes = await Collection.Find(x => x.AppId == appId && x.Date >= fromDate && x.Date <= toDate).SortBy(x => x.Date).ToListAsync(); |
|||
var enrichedSizes = new List<MongoAssetStatsEntity>(); |
|||
|
|||
var sizesDictionary = originalSizes.ToDictionary(x => x.Date); |
|||
|
|||
var previousSize = long.MinValue; |
|||
var previousCount = long.MinValue; |
|||
|
|||
for (var date = fromDate; date <= toDate; date = date.AddDays(1)) |
|||
{ |
|||
var size = sizesDictionary.GetOrDefault(date); |
|||
|
|||
if (size != null) |
|||
{ |
|||
previousSize = size.TotalSize; |
|||
previousCount = size.TotalCount; |
|||
} |
|||
else |
|||
{ |
|||
if (previousSize < 0) |
|||
{ |
|||
var firstBeforeRange = await Collection.Find(x => x.AppId == appId && x.Date < fromDate).SortByDescending(x => x.Date).FirstOrDefaultAsync(); |
|||
|
|||
previousSize = firstBeforeRange?.TotalSize ?? 0L; |
|||
previousCount = firstBeforeRange?.TotalCount ?? 0L; |
|||
} |
|||
|
|||
size = new MongoAssetStatsEntity |
|||
{ |
|||
Date = date, |
|||
TotalSize = previousSize, |
|||
TotalCount = previousCount |
|||
}; |
|||
} |
|||
|
|||
enrichedSizes.Add(size); |
|||
} |
|||
|
|||
return enrichedSizes; |
|||
} |
|||
|
|||
public async Task<long> GetTotalSizeAsync(Guid appId) |
|||
{ |
|||
var entity = await Collection.Find(x => x.AppId == appId).SortByDescending(x => x.Date).FirstOrDefaultAsync(); |
|||
|
|||
return entity?.TotalSize ?? 0; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,78 @@ |
|||
// ==========================================================================
|
|||
// MongoAssetStatsRepository_EventHandling.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Threading.Tasks; |
|||
using MongoDB.Driver; |
|||
using Squidex.Events.Assets; |
|||
using Squidex.Infrastructure.CQRS.Events; |
|||
using Squidex.Infrastructure.Dispatching; |
|||
|
|||
namespace Squidex.Read.MongoDb.Assets |
|||
{ |
|||
public partial class MongoAssetStatsRepository |
|||
{ |
|||
private static readonly UpdateOptions Upsert = new UpdateOptions { IsUpsert = true }; |
|||
|
|||
public string Name |
|||
{ |
|||
get { return GetType().Name; } |
|||
} |
|||
|
|||
public string EventsFilter |
|||
{ |
|||
get { return "^asset-"; } |
|||
} |
|||
|
|||
public Task On(Envelope<IEvent> @event) |
|||
{ |
|||
return this.DispatchActionAsync(@event.Payload, @event.Headers); |
|||
} |
|||
|
|||
protected Task On(AssetCreated @event, EnvelopeHeaders headers) |
|||
{ |
|||
return UpdateSizeAsync(@event.AppId.Id, headers.Timestamp().ToDateTimeUtc().Date, @event.FileSize, 1); |
|||
} |
|||
|
|||
protected Task On(AssetUpdated @event, EnvelopeHeaders headers) |
|||
{ |
|||
return UpdateSizeAsync(@event.AppId.Id, headers.Timestamp().ToDateTimeUtc().Date, @event.FileSize, 0); |
|||
} |
|||
|
|||
protected Task On(AssetDeleted @event, EnvelopeHeaders headers) |
|||
{ |
|||
return UpdateSizeAsync(@event.AppId.Id, headers.Timestamp().ToDateTimeUtc().Date, -@event.DeletedSize, -1); |
|||
} |
|||
|
|||
private async Task UpdateSizeAsync(Guid appId, DateTime date, long size, long count) |
|||
{ |
|||
var id = $"{appId}_{date:yyyy-MM-dd}"; |
|||
|
|||
var entity = await Collection.Find(x => x.Id == id).FirstOrDefaultAsync(); |
|||
|
|||
if (entity == null) |
|||
{ |
|||
var last = await Collection.Find(x => x.AppId == appId).SortByDescending(x => x.Date).FirstOrDefaultAsync(); |
|||
|
|||
entity = new MongoAssetStatsEntity |
|||
{ |
|||
Id = id, |
|||
Date = date, |
|||
AppId = appId, |
|||
TotalSize = last?.TotalSize ?? 0, |
|||
TotalCount = last?.TotalCount ?? 0 |
|||
}; |
|||
} |
|||
|
|||
entity.TotalSize += size; |
|||
entity.TotalCount += count; |
|||
|
|||
await Collection.ReplaceOneAsync(x => x.Id == id, entity, Upsert); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,21 @@ |
|||
// ==========================================================================
|
|||
// IAssetDaySizeEntity.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
|
|||
namespace Squidex.Read.Assets |
|||
{ |
|||
public interface IAssetStatsEntity |
|||
{ |
|||
DateTime Date { get; } |
|||
|
|||
long TotalSize { get; } |
|||
|
|||
long TotalCount { get; } |
|||
} |
|||
} |
|||
@ -0,0 +1,21 @@ |
|||
// ==========================================================================
|
|||
// IAssetDaySizeRepository.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Threading.Tasks; |
|||
|
|||
namespace Squidex.Read.Assets.Repositories |
|||
{ |
|||
public interface IAssetStatsRepository |
|||
{ |
|||
Task<IReadOnlyList<IAssetStatsEntity>> QueryAsync(Guid appId, DateTime fromDate, DateTime toDate); |
|||
|
|||
Task<long> GetTotalSizeAsync(Guid appId); |
|||
} |
|||
} |
|||
Loading…
Reference in new issue