Include the state before the event in roomserver output

This commit is contained in:
Mark Haines 2017-06-19 11:27:02 +01:00
parent c6e59ca967
commit a7e20d1658
2 changed files with 65 additions and 24 deletions

View file

@ -22,9 +22,6 @@ import (
type OutputRoomEvent struct {
// The JSON bytes of the event.
Event []byte
// The state event IDs needed to determine who can see this event.
// This can be used to tell which users to send the event to.
VisibilityEventIDs []string
// The latest events in the room after this event.
// This can be used to set the prev events for new events in the room.
// This also can be used to get the full current state after this event.
@ -43,6 +40,14 @@ type OutputRoomEvent struct {
// If the LastSentEventID doesn't match what they were expecting it to be
// they can use the LatestEventIDs to request the full current state.
LastSentEventID string
// The state event IDs that are part of the state at the event, but not
// part of the current state. Together with the StateBeforeRemovesEventIDs
// this can be used to construct the state before the event from the
// current state.
StateBeforeAddsEventIDs []string
// The state event IDs that are part of the current state, but not part
// of the state at the event.
StateBeforeRemovesEventIDs []string
}
// UnmarshalJSON implements json.Unmarshaller
@ -52,12 +57,14 @@ func (ore *OutputRoomEvent) UnmarshalJSON(data []byte) error {
// We use json.RawMessage so that the event JSON is sent as JSON rather than
// being base64 encoded which is the default for []byte.
var content struct {
Event *json.RawMessage
VisibilityEventIDs []string
LatestEventIDs []string
AddsStateEventIDs []string
RemovesStateEventIDs []string
LastSentEventID string
Event *json.RawMessage
VisibilityEventIDs []string
LatestEventIDs []string
AddsStateEventIDs []string
RemovesStateEventIDs []string
LastSentEventID string
StateBeforeAddsEventIDs []string
StateBeforeRemovesEventIDs []string
}
if err := json.Unmarshal(data, &content); err != nil {
return err
@ -65,11 +72,12 @@ func (ore *OutputRoomEvent) UnmarshalJSON(data []byte) error {
if content.Event != nil {
ore.Event = []byte(*content.Event)
}
ore.VisibilityEventIDs = content.VisibilityEventIDs
ore.LatestEventIDs = content.LatestEventIDs
ore.AddsStateEventIDs = content.AddsStateEventIDs
ore.RemovesStateEventIDs = content.RemovesStateEventIDs
ore.LastSentEventID = content.LastSentEventID
ore.StateBeforeAddsEventIDs = content.StateBeforeAddsEventIDs
ore.StateBeforeRemovesEventIDs = content.StateBeforeRemovesEventIDs
return nil
}
@ -81,19 +89,22 @@ func (ore OutputRoomEvent) MarshalJSON() ([]byte, error) {
// being base64 encoded which is the default for []byte.
event := json.RawMessage(ore.Event)
content := struct {
Event *json.RawMessage
VisibilityEventIDs []string
LatestEventIDs []string
AddsStateEventIDs []string
RemovesStateEventIDs []string
LastSentEventID string
Event *json.RawMessage
VisibilityEventIDs []string
LatestEventIDs []string
AddsStateEventIDs []string
RemovesStateEventIDs []string
LastSentEventID string
StateBeforeAddsEventIDs []string
StateBeforeRemovesEventIDs []string
}{
Event: &event,
VisibilityEventIDs: ore.VisibilityEventIDs,
LatestEventIDs: ore.LatestEventIDs,
AddsStateEventIDs: ore.AddsStateEventIDs,
RemovesStateEventIDs: ore.RemovesStateEventIDs,
LastSentEventID: ore.LastSentEventID,
Event: &event,
LatestEventIDs: ore.LatestEventIDs,
AddsStateEventIDs: ore.AddsStateEventIDs,
RemovesStateEventIDs: ore.RemovesStateEventIDs,
LastSentEventID: ore.LastSentEventID,
StateBeforeAddsEventIDs: ore.StateBeforeAddsEventIDs,
StateBeforeRemovesEventIDs: ore.StateBeforeRemovesEventIDs,
}
return json.Marshal(&content)
}

View file

@ -20,6 +20,7 @@ import (
"github.com/matrix-org/dendrite/roomserver/state"
"github.com/matrix-org/dendrite/roomserver/types"
"github.com/matrix-org/gomatrixserverlib"
"github.com/matrix-org/util"
)
// updateLatestEvents updates the list of latest events for this room in the database and writes the
@ -110,6 +111,13 @@ func doUpdateLatestEvents(
return err
}
stateBeforeEventRemoves, stateBeforeEventAdds, err := state.DifferenceBetweeenStateSnapshots(
db, newStateNID, stateAtEvent.BeforeStateSnapshotNID,
)
if err != nil {
return err
}
// Send the event to the output logs.
// We do this inside the database transaction to ensure that we only mark an event as sent if we sent it.
// (n.b. this means that it's possible that the same event will be sent twice if the transaction fails but
@ -118,7 +126,10 @@ func doUpdateLatestEvents(
// send the event asynchronously but we would need to ensure that 1) the events are written to the log in
// the correct order, 2) that pending writes are resent across restarts. In order to avoid writing all the
// necessary bookkeeping we'll keep the event sending synchronous for now.
if err = writeEvent(db, ow, lastEventIDSent, event, newLatest, removed, added); err != nil {
if err = writeEvent(
db, ow, lastEventIDSent, event, newLatest, removed, added,
stateBeforeEventRemoves, stateBeforeEventAdds,
); err != nil {
return err
}
@ -170,6 +181,7 @@ func writeEvent(
db RoomEventDatabase, ow OutputRoomEventWriter, lastEventIDSent string,
event gomatrixserverlib.Event, latest []types.StateAtEventAndReference,
removed, added []types.StateEntry,
stateBeforeEventRemoves, stateBeforeEventAdds []types.StateEntry,
) error {
latestEventIDs := make([]string, len(latest))
@ -190,6 +202,13 @@ func writeEvent(
for _, entry := range removed {
stateEventNIDs = append(stateEventNIDs, entry.EventNID)
}
for _, entry := range stateBeforeEventRemoves {
stateEventNIDs = append(stateEventNIDs, entry.EventNID)
}
for _, entry := range stateBeforeEventAdds {
stateEventNIDs = append(stateEventNIDs, entry.EventNID)
}
stateEventNIDs = stateEventNIDs[:util.SortAndUnique(eventNIDSorter(stateEventNIDs))]
eventIDMap, err := db.EventIDs(stateEventNIDs)
if err != nil {
return err
@ -200,7 +219,18 @@ func writeEvent(
for _, entry := range removed {
ore.RemovesStateEventIDs = append(ore.RemovesStateEventIDs, eventIDMap[entry.EventNID])
}
for _, entry := range stateBeforeEventRemoves {
ore.StateBeforeRemovesEventIDs = append(ore.StateBeforeRemovesEventIDs, eventIDMap[entry.EventNID])
}
for _, entry := range stateBeforeEventAdds {
ore.StateBeforeAddsEventIDs = append(ore.StateBeforeAddsEventIDs, eventIDMap[entry.EventNID])
}
// TODO: Fill out VisibilityStateIDs
return ow.WriteOutputRoomEvent(ore)
}
type eventNIDSorter []types.EventNID
func (s eventNIDSorter) Len() int { return len(s) }
func (s eventNIDSorter) Less(i, j int) bool { return s[i] < s[j] }
func (s eventNIDSorter) Swap(i, j int) { s[i], s[j] = s[j], s[i] }