def on_local_model_change(self, sender, message):
        """
        React to model changes reported from the web-ui by transmitting
        appropriate messages to peers

        Args:
            sender(object): Sender of the Blinker signal
            message(dict): Changeset containing keys in CHANGESET_REQUIRED_FIELDS

        Raises:
            KeyError: Missing key from Changeset
            ValueError: Changeset contains illegal value
        """
        CHANGESET_REQUIRED_FIELDS = ["author_id", "action", "object_id", "object_type"]

        # Verify changeset
        for k in CHANGESET_REQUIRED_FIELDS:
            if k not in message.keys():
                raise KeyError("Missing key: '{}'".format(k))

        if message["action"] not in CHANGE_TYPES:
            raise ValueError("Unknown action: '{}'".format(message["action"]))

        if message["object_type"] not in OBJECT_TYPES:
            raise ValueError("Object type {} not supported".format(message["object_type"]))

        # Get the object's class from globals
        obj_class = globals()[message["object_type"]]
        obj = obj_class.query.get(message["object_id"])

        if obj is None:
            # TODO: Use different exception type
            raise Exception("Could not find {} {}".format(obj_class, message["object_id"]))

        author = Persona.query.get(message["author_id"])

        # Send Vesicle
        data = dict({
            "action": message["action"],
            "object_type": message["object_type"]
        })

        if message["action"] == "insert":
            data["object"] = obj.export()
        elif message["action"] == "update":
            data["object"] = obj.export(update=True)
        elif message["action"] == "delete":
            data["object"] = {
                "id": obj.id,
                "modified": obj.modified.isoformat()
            }

        if "recipients" in message:
            recipients = message["recipients"]
        else:
            recipients = author.contacts.all()

        vesicle = Vesicle(
            id=uuid4().hex,
            message_type="object",
            data=data,
            author=author,
            handled=True
        )
        obj.vesicles.append(vesicle)

        session = create_session()

        try:
            session.add(vesicle)
            session.commit()
        except:
            session.rollback()
            raise
        else:
            self.logger.info("Local {} changed: Distributing {}\n{}".format(obj, vesicle, vesicle.json(indent=True)))
            vesicle = self._distribute_vesicle(vesicle, recipients=recipients)

        session.add(vesicle)
        session.commit()
dataset/ETHPy150Open ciex/souma/synapse/__init__.py/Synapse.on_local_model_change/original