Ver Fonte

Implemented event system in stores

Kenric Nugteren há 6 meses atrás
pai
commit
5cdb0ef344

+ 8 - 0
prs.stores/BaseStore.cs

@@ -7,6 +7,7 @@ using InABox.Core;
 using InABox.Database;
 using InABox.Database;
 using System;
 using System;
 using com.sun.org.glassfish.external.probe.provider.annotations;
 using com.sun.org.glassfish.external.probe.provider.annotations;
+using PRS.Shared.Events;
 
 
 namespace Comal.Stores
 namespace Comal.Stores
 {
 {
@@ -45,6 +46,13 @@ namespace Comal.Stores
             base.BeforeSave(entity);
             base.BeforeSave(entity);
         }
         }
 
 
+        protected override void AfterSave(T entity)
+        {
+            base.AfterSave(entity);
+
+            EventUtils.AfterSave(this, entity);
+        }
+
         protected override void BeforeDelete(T entity)
         protected override void BeforeDelete(T entity)
         {
         {
             CheckPlatformVersion();
             CheckPlatformVersion();

+ 25 - 0
prs.stores/EventStore.cs

@@ -0,0 +1,25 @@
+using Comal.Classes;
+using Comal.Stores;
+using PRS.Shared.Events;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace PRSStores;
+
+public class EventStore : BaseStore<Event>
+{
+    protected override void AfterSave(Event entity)
+    {
+        base.AfterSave(entity);
+        EventUtils.AddEvent(Provider, entity);
+    }
+
+    protected override void AfterDelete(Event entity)
+    {
+        base.AfterDelete(entity);
+        EventUtils.RemoveEvent(Provider, entity);
+    }
+}

+ 96 - 2
prs.shared/Events/Event.cs → prs.stores/Events/Event.cs

@@ -2,7 +2,6 @@
 using Expressive;
 using Expressive;
 using InABox.Core;
 using InABox.Core;
 using InABox.Database;
 using InABox.Database;
-using Org.BouncyCastle.Asn1.X509.Qualified;
 using System;
 using System;
 using System.Collections;
 using System.Collections;
 using System.Collections.Generic;
 using System.Collections.Generic;
@@ -70,7 +69,7 @@ public class EventData<T, TDataModel> : IEventData
         var nActions = reader.ReadInt32();
         var nActions = reader.ReadInt32();
         for(int i = 0; i < nActions; ++i)
         for(int i = 0; i < nActions; ++i)
         {
         {
-            var action = EventUtils.DeserializeObject<IEventAction<T>>(EventUtils.GetTriggerType, reader);
+            var action = EventUtils.DeserializeObject<IEventAction<T>>(EventUtils.GetActionType, reader);
             Actions.Add(action);
             Actions.Add(action);
         }
         }
     }
     }
@@ -306,6 +305,101 @@ public static class EventUtils
     }
     }
 
 
     #endregion
     #endregion
+
+    #region Event Cache
+
+    private static bool _loadedCache = false;
+    private static Dictionary<EventType, Dictionary<Type, List<(Event Event, IEventData EventData)>>> _entityEvents = new();
+    private static Dictionary<Guid, (EventType, Type)> _entityEventMap = new();
+
+    public static void ReloadCache(IProvider provider)
+    {
+        _entityEvents.Clear();
+        _entityEventMap.Clear();
+        var events = provider.Query(null, Columns.None<Event>().Add(x => x.ID).Add(x => x.Code).Add(x => x.EventType).Add(x => x.Data))
+            .ToObjects<Event>();
+        foreach(var ev in events)
+        {
+            AddEvent(provider, ev);
+        }
+        _loadedCache = true;
+    }
+
+    private static void AddEntityEvent(Event ev)
+    {
+        if(ev.Data.Length != 0)
+        {
+            using var stream = new MemoryStream(ev.Data);
+            var reader = new CoreBinaryReader(stream, BinarySerializationSettings.Latest);
+            var data = Deserialize(reader);
+
+            var entityType = data.Event.GetType().GenericTypeArguments[0];
+            _entityEvents.GetValueOrAdd(ev.EventType).GetValueOrAdd(entityType).Add((ev, data));
+            _entityEventMap[ev.ID] = (ev.EventType, entityType);
+        }
+    }
+    private static void RemoveEntityEvent(Event ev)
+    {
+        if(_entityEventMap.TryGetValue(ev.ID, out var item))
+        {
+            if(_entityEvents.TryGetValue(item.Item1, out var eventTypeEvents))
+            {
+                if(eventTypeEvents.TryGetValue(item.Item2, out var entityEvents))
+                {
+                    entityEvents.RemoveAll(x => x.Event.ID == ev.ID);
+                    if(entityEvents.Count == 0)
+                    {
+                        eventTypeEvents.Remove(item.Item2);
+                    }
+                }
+                if(eventTypeEvents.Count == 0)
+                {
+                    _entityEvents.Remove(item.Item1);
+                }
+            }
+            _entityEventMap.Remove(ev.ID);
+        }
+    }
+
+    public static void RemoveEvent(IProvider provider, Event ev)
+    {
+        if (!_loadedCache) ReloadCache(provider);
+
+        switch (ev.EventType)
+        {
+            case EventType.AfterSave:
+                RemoveEntityEvent(ev);
+                break;
+        }
+    }
+    public static void AddEvent(IProvider provider, Event ev)
+    {
+        if (!_loadedCache) ReloadCache(provider);
+
+        switch (ev.EventType)
+        {
+            case EventType.AfterSave:
+                AddEntityEvent(ev);
+                break;
+        }
+    }
+
+    public static void AfterSave<T>(IStore store, T entity)
+        where T : Entity
+    {
+        if (!_loadedCache) ReloadCache(store.Provider);
+
+        var events = _entityEvents.GetValueOrDefault(EventType.AfterSave)
+            ?.GetValueOrDefault(typeof(T));
+        if (events is null) return;
+
+        foreach(var ev in events)
+        {
+            Run(store, ev.Event, (ev.EventData as EventData<SaveEvent<T>, SaveEventDataModel<T>>)!, new SaveEventDataModel<T>(entity));
+        }
+    }
+
+    #endregion
 }
 }
 
 
 #region DataModel Definition
 #region DataModel Definition

+ 0 - 0
prs.shared/Events/SaveEvent.cs → prs.stores/Events/SaveEvent.cs