From 9981cc47462cee20bb1c39c01b0ec85990acd2a8 Mon Sep 17 00:00:00 2001
From: Fabio Manganiello <info@fabiomanganiello.com>
Date: Sun, 24 Apr 2022 21:38:45 +0200
Subject: [PATCH] Backend support for entities deletion

---
 platypush/message/event/entities.py    | 21 +++++++++++++------
 platypush/plugins/entities/__init__.py | 28 +++++++++++++++++++++++++-
 2 files changed, 42 insertions(+), 7 deletions(-)

diff --git a/platypush/message/event/entities.py b/platypush/message/event/entities.py
index 6b56100a7..4c475c588 100644
--- a/platypush/message/event/entities.py
+++ b/platypush/message/event/entities.py
@@ -1,19 +1,28 @@
+from abc import ABC
 from typing import Union
 
 from platypush.entities import Entity
 from platypush.message.event import Event
 
 
-class EntityUpdateEvent(Event):
-    """
-    This even is triggered whenever an entity of any type (a switch, a light,
-    a sensor, a media player etc.) updates its state.
-    """
-
+class EntityEvent(Event, ABC):
     def __init__(self, entity: Union[Entity, dict], *args, **kwargs):
         if isinstance(entity, Entity):
             entity = entity.to_json()
         super().__init__(entity=entity, *args, **kwargs)
 
 
+class EntityUpdateEvent(EntityEvent):
+    """
+    This event is triggered whenever an entity of any type (a switch, a light,
+    a sensor, a media player etc.) updates its state.
+    """
+
+
+class EntityDeleteEvent(EntityEvent):
+    """
+    This event is triggered whenever an entity is deleted.
+    """
+
+
 # vim:sw=4:ts=4:et:
diff --git a/platypush/plugins/entities/__init__.py b/platypush/plugins/entities/__init__.py
index d2e2652ae..acf7a1205 100644
--- a/platypush/plugins/entities/__init__.py
+++ b/platypush/plugins/entities/__init__.py
@@ -7,7 +7,7 @@ from sqlalchemy.orm import make_transient
 
 from platypush.context import get_plugin, get_bus
 from platypush.entities import Entity, get_plugin_entity_registry, get_entities_registry
-from platypush.message.event.entities import EntityUpdateEvent
+from platypush.message.event.entities import EntityUpdateEvent, EntityDeleteEvent
 from platypush.plugins import Plugin, action
 
 
@@ -168,6 +168,32 @@ class EntitiesPlugin(Plugin):
         assert entity, f'No such entity ID: {id}'
         return entity.run(action, *args, **kwargs)
 
+    @action
+    def delete(self, *entities: int):  # type: ignore
+        """
+        Delete a set of entity IDs.
+
+        Note: this should only be done if the entity is no longer available or
+        the associated plugin has been disabled, otherwise the entities will be
+        re-created by the plugins on the next scan.
+
+        :param entities: IDs of the entities to be removed.
+        :return: The payload of the deleted entities.
+        """
+        with self._get_db().get_session() as session:
+            entities: Collection[Entity] = (
+                session.query(Entity).filter(Entity.id.in_(entities)).all()
+            )
+            for entity in entities:
+                session.delete(entity)
+            session.commit()
+
+        for entity in entities:
+            make_transient(entity)
+            get_bus().post(EntityDeleteEvent(entity))
+
+        return entities
+
     @action
     def rename(self, **entities: Mapping[str, str]):
         """