State events sent by modules sometimes disappear #10830
Description
I've observed a few times that when a module sends a state event A while processing another state event B in the same room then A might be persisted into the room, then deleted immediately afterwards when B gets persisted. Some time ago I managed to track it down to the state res algorithm (when processing B) returning a state that didn't include A and therefore Synapse deleting A from the room's current state; but that algorithm was a bit of a black box to me back then and I didn't push my investigation further.
Today, seeing I could still reproduce it (at least this morning) I decided to give it another go. However, after some time of digging (and no code change) the bug stopped reproducing. I'm still opening this issue in case I stumble upon it again in the future and want to look into it again (I didn't fix the bug, so it must still be around, though it might be a bit random to reproduce).
The sample module I've been using to test this is:
import time
from synapse.api.constants import EventTypes
from synapse.events import EventBase
from synapse.module_api import ModuleApi
from synapse.types import StateMap
class MySuperModule:
def __init__(self, config: dict, api: ModuleApi):
self.api = api
self.api.register_third_party_rules_callbacks(
check_event_allowed=self.check_event_allowed,
)
async def check_event_allowed(self, event: EventBase, state: StateMap[EventBase]):
if event.is_state() and event.type == EventTypes.PowerLevels:
await self.api.create_and_send_event_into_room(
{
"room_id": event.room_id,
"sender": event.sender,
"type": "bzh.abolivier.test3",
"content": {"now": int(time.time())},
"state_key": "",
}
)
return True, None
(which roughly reproduces the scenario I've seen it happen in initially)
At the time the workaround I found was to use the check_event_allowed
callback, and return the event's get_dict()
(without modifying it) to force Synapse to rebuild B and recalculate its context to use updated prev_events
.