From a565a0e33066a2bae00517ffea92f9cd027e1125 Mon Sep 17 00:00:00 2001 From: ChronosX88 Date: Thu, 25 Mar 2021 14:25:51 +0300 Subject: [PATCH] Implement getting event timeline by chat in EventStorageManager --- .../Storage/EventStorageManager.cs | 112 +++++++++++++----- .../Interfaces/IEventStorageManager.cs | 2 +- .../Storage/Models/SyncRequest.cs | 12 ++ .../Storage/Models/SyncResponse.cs | 12 ++ .../DefaultAuthProvider/Plugin.cs | 1 - 5 files changed, 105 insertions(+), 34 deletions(-) create mode 100644 src/ZirconiumPlugins/ChatSubsystem/Storage/Models/SyncRequest.cs create mode 100644 src/ZirconiumPlugins/ChatSubsystem/Storage/Models/SyncResponse.cs diff --git a/src/ZirconiumPlugins/ChatSubsystem/Storage/EventStorageManager.cs b/src/ZirconiumPlugins/ChatSubsystem/Storage/EventStorageManager.cs index f9edeef..e363bb6 100644 --- a/src/ZirconiumPlugins/ChatSubsystem/Storage/EventStorageManager.cs +++ b/src/ZirconiumPlugins/ChatSubsystem/Storage/EventStorageManager.cs @@ -3,6 +3,8 @@ using System.Linq; using System.Threading.Tasks; using ChatSubsystem.Storage.Interfaces; using ChatSubsystem.Storage.Models; +using MongoDB.Bson; +using MongoDB.Bson.Serialization; using MongoDB.Driver; using Zirconium.Core.Models; @@ -12,9 +14,6 @@ namespace ChatSubsystem.Storage { private const string EventsCollectionName = "events"; - // get event by id - // get events for user after some point in timeline (via sorting by event id) - private ChatStorageManager _chatStorageManager; private IMongoCollection events; @@ -24,56 +23,105 @@ namespace ChatSubsystem.Storage events = database.GetCollection(EventsCollectionName); } - public async Task> GetEventsForUser(EntityID user, EntityID since, int limit) + public async Task<(IList, IList)> GetEventsForUser(EntityID user, EntityID since, int limit) { var chats = await _chatStorageManager.GetChatsForUser(user); - - return new List(); + + var evs = new List(); + + foreach (var c in chats) + { + var res = await GetEventsForChat(c, since, limit); + evs.AddRange(res); + } + + evs = evs.OrderBy(x => x.Timestamp).ToList(); + + return (evs, chats); } - private async Task> GetEventsForChat(EntityID since, int limit) + private async Task> GetEventsForChat(Chat chat, EntityID since, int limit) { - return new List(); + var graphLookupStage = new BsonDocument("$graphLookup", + new BsonDocument + { + { "from", EventsCollectionName }, + { "startWith", "{ EventID: "+since+" }" }, + { "connectFromField", "EventID"}, + { "connectToField", "PrevEvents" }, + { "as", "Children" }, + { "maxDepth", limit }, + { "restrictSearchWithMatch", "{ ChatId: "+chat.Id+" }" } + }); + + var result = await events.Aggregate() + .AppendStage(graphLookupStage).ToListAsync(); + + var deserializedResult = new List(); + result.ForEach(x => + { + deserializedResult.Add(BsonSerializer.Deserialize(x)); + }); + + return deserializedResult; } public async Task SaveEvent(Event e) { - var connectFromField = (FieldDefinition)"_id"; - var connectToField = (FieldDefinition)"PrevID"; - var startWith = (AggregateExpressionDefinition)"$_id"; - var @as = (FieldDefinition>)"Children"; - - // link to previous global events - var res = await events.Aggregate() - .GraphLookup(events, connectFromField, connectToField, startWith, @as) - .Match("{ Children: { $size: 0 } }").ToListAsync(); - if (res.Count == 0) + var graphLookupStage = new BsonDocument("$graphLookup", + new BsonDocument + { + { "from", EventsCollectionName }, + { "startWith", "$_id" }, + { "connectFromField", "_id"}, + { "connectToField", "PrevID" }, + { "as", "Children" }, + { "maxDepth", 0 } + }); + + var result = await events.Aggregate() + .AppendStage(graphLookupStage) + .Match("{ Children: { $size: 0 } }") + .ToListAsync(); + + if (result.Count == 0) { await events.InsertOneAsync(e); return; } - res.ForEach(x => + result.ForEach(x => { - e.PrevID.Append(x.Id); + var y = BsonSerializer.Deserialize(x); + e.PrevID.Append(y.Id); }); - // link to previous events in chat - connectToField = (FieldDefinition)"PrevEvents"; - var opts = new AggregateGraphLookupOptions() - { - RestrictSearchWithMatch = "{ ChatId: "+e.ChatId+" }" - }; - res = await events.Aggregate() - .GraphLookup(events, connectFromField, connectToField, startWith, @as, opts) - .Match("{ Children: { $size: 0 } }").ToListAsync(); - if (res.Count == 0) + graphLookupStage = new BsonDocument("$graphLookup", + new BsonDocument + { + { "from", EventsCollectionName }, + { "startWith", "$EventID" }, + { "connectFromField", "EventID"}, + { "connectToField", "PrevEvents" }, + { "as", "Children" }, + { "maxDepth", 0 }, + { "restrictSearchWithMatch", "{ ChatId: "+e.ChatId+" }" } + }); + + + result = await events.Aggregate() + .AppendStage(graphLookupStage) + .Match("{ Children: { $size: 0 } }") + .ToListAsync(); + + if (result.Count == 0) { await events.InsertOneAsync(e); return; } - res.ForEach(x => + result.ForEach(x => { - e.PrevEvents.Append(x.EventID); + var y = BsonSerializer.Deserialize(x); + e.PrevEvents.Append(y.EventID); }); await events.InsertOneAsync(e); diff --git a/src/ZirconiumPlugins/ChatSubsystem/Storage/Interfaces/IEventStorageManager.cs b/src/ZirconiumPlugins/ChatSubsystem/Storage/Interfaces/IEventStorageManager.cs index 93ecf38..ac9370e 100644 --- a/src/ZirconiumPlugins/ChatSubsystem/Storage/Interfaces/IEventStorageManager.cs +++ b/src/ZirconiumPlugins/ChatSubsystem/Storage/Interfaces/IEventStorageManager.cs @@ -7,7 +7,7 @@ namespace ChatSubsystem.Storage.Interfaces { public interface IEventStorageManager { - Task> GetEventsForUser(EntityID user, EntityID since, int limit); + Task<(IList, IList)> GetEventsForUser(EntityID user, EntityID since, int limit); Task GetEventById(EntityID id); Task SaveEvent(Event e); } diff --git a/src/ZirconiumPlugins/ChatSubsystem/Storage/Models/SyncRequest.cs b/src/ZirconiumPlugins/ChatSubsystem/Storage/Models/SyncRequest.cs new file mode 100644 index 0000000..3ce009b --- /dev/null +++ b/src/ZirconiumPlugins/ChatSubsystem/Storage/Models/SyncRequest.cs @@ -0,0 +1,12 @@ +using Zirconium.Core.Models; + +namespace ChatSubsystem.Storage.Models +{ + public class SyncRequest + { + public EntityID Since { get; set; } + public int Limit { get; set; } + public EntityID ChatID { get; set; } + public string SyncDirection { get; set; } + } +} \ No newline at end of file diff --git a/src/ZirconiumPlugins/ChatSubsystem/Storage/Models/SyncResponse.cs b/src/ZirconiumPlugins/ChatSubsystem/Storage/Models/SyncResponse.cs new file mode 100644 index 0000000..4c2eeec --- /dev/null +++ b/src/ZirconiumPlugins/ChatSubsystem/Storage/Models/SyncResponse.cs @@ -0,0 +1,12 @@ +using System.Collections.Generic; +using Zirconium.Core.Models; + +namespace ChatSubsystem.Storage.Models +{ + public class SyncResponse + { + public EntityID NextBatch { get; set; } + public IList MentionedChats { get; set; } + public IList Events { get; set; } + } +} \ No newline at end of file diff --git a/src/ZirconiumPlugins/DefaultAuthProvider/Plugin.cs b/src/ZirconiumPlugins/DefaultAuthProvider/Plugin.cs index aff25c8..dcc83d6 100644 --- a/src/ZirconiumPlugins/DefaultAuthProvider/Plugin.cs +++ b/src/ZirconiumPlugins/DefaultAuthProvider/Plugin.cs @@ -3,7 +3,6 @@ using MongoDB.Bson.Serialization.Attributes; using MongoDB.Driver; using Zirconium.Core; using Zirconium.Core.Plugins.Interfaces; -using System.Linq; using Newtonsoft.Json; using JWT.Algorithms; using JWT.Builder;