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 { type OutputRoomEvent struct {
// The JSON bytes of the event. // The JSON bytes of the event.
Event []byte 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. // 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 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. // 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 // If the LastSentEventID doesn't match what they were expecting it to be
// they can use the LatestEventIDs to request the full current state. // they can use the LatestEventIDs to request the full current state.
LastSentEventID string 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 // 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 // We use json.RawMessage so that the event JSON is sent as JSON rather than
// being base64 encoded which is the default for []byte. // being base64 encoded which is the default for []byte.
var content struct { var content struct {
Event *json.RawMessage Event *json.RawMessage
VisibilityEventIDs []string VisibilityEventIDs []string
LatestEventIDs []string LatestEventIDs []string
AddsStateEventIDs []string AddsStateEventIDs []string
RemovesStateEventIDs []string RemovesStateEventIDs []string
LastSentEventID string LastSentEventID string
StateBeforeAddsEventIDs []string
StateBeforeRemovesEventIDs []string
} }
if err := json.Unmarshal(data, &content); err != nil { if err := json.Unmarshal(data, &content); err != nil {
return err return err
@ -65,11 +72,12 @@ func (ore *OutputRoomEvent) UnmarshalJSON(data []byte) error {
if content.Event != nil { if content.Event != nil {
ore.Event = []byte(*content.Event) ore.Event = []byte(*content.Event)
} }
ore.VisibilityEventIDs = content.VisibilityEventIDs
ore.LatestEventIDs = content.LatestEventIDs ore.LatestEventIDs = content.LatestEventIDs
ore.AddsStateEventIDs = content.AddsStateEventIDs ore.AddsStateEventIDs = content.AddsStateEventIDs
ore.RemovesStateEventIDs = content.RemovesStateEventIDs ore.RemovesStateEventIDs = content.RemovesStateEventIDs
ore.LastSentEventID = content.LastSentEventID ore.LastSentEventID = content.LastSentEventID
ore.StateBeforeAddsEventIDs = content.StateBeforeAddsEventIDs
ore.StateBeforeRemovesEventIDs = content.StateBeforeRemovesEventIDs
return nil return nil
} }
@ -81,19 +89,22 @@ func (ore OutputRoomEvent) MarshalJSON() ([]byte, error) {
// being base64 encoded which is the default for []byte. // being base64 encoded which is the default for []byte.
event := json.RawMessage(ore.Event) event := json.RawMessage(ore.Event)
content := struct { content := struct {
Event *json.RawMessage Event *json.RawMessage
VisibilityEventIDs []string VisibilityEventIDs []string
LatestEventIDs []string LatestEventIDs []string
AddsStateEventIDs []string AddsStateEventIDs []string
RemovesStateEventIDs []string RemovesStateEventIDs []string
LastSentEventID string LastSentEventID string
StateBeforeAddsEventIDs []string
StateBeforeRemovesEventIDs []string
}{ }{
Event: &event, Event: &event,
VisibilityEventIDs: ore.VisibilityEventIDs, LatestEventIDs: ore.LatestEventIDs,
LatestEventIDs: ore.LatestEventIDs, AddsStateEventIDs: ore.AddsStateEventIDs,
AddsStateEventIDs: ore.AddsStateEventIDs, RemovesStateEventIDs: ore.RemovesStateEventIDs,
RemovesStateEventIDs: ore.RemovesStateEventIDs, LastSentEventID: ore.LastSentEventID,
LastSentEventID: ore.LastSentEventID, StateBeforeAddsEventIDs: ore.StateBeforeAddsEventIDs,
StateBeforeRemovesEventIDs: ore.StateBeforeRemovesEventIDs,
} }
return json.Marshal(&content) return json.Marshal(&content)
} }

View file

@ -20,6 +20,7 @@ import (
"github.com/matrix-org/dendrite/roomserver/state" "github.com/matrix-org/dendrite/roomserver/state"
"github.com/matrix-org/dendrite/roomserver/types" "github.com/matrix-org/dendrite/roomserver/types"
"github.com/matrix-org/gomatrixserverlib" "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 // updateLatestEvents updates the list of latest events for this room in the database and writes the
@ -110,6 +111,13 @@ func doUpdateLatestEvents(
return err return err
} }
stateBeforeEventRemoves, stateBeforeEventAdds, err := state.DifferenceBetweeenStateSnapshots(
db, newStateNID, stateAtEvent.BeforeStateSnapshotNID,
)
if err != nil {
return err
}
// Send the event to the output logs. // 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. // 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 // (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 // 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 // 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. // 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 return err
} }
@ -170,6 +181,7 @@ func writeEvent(
db RoomEventDatabase, ow OutputRoomEventWriter, lastEventIDSent string, db RoomEventDatabase, ow OutputRoomEventWriter, lastEventIDSent string,
event gomatrixserverlib.Event, latest []types.StateAtEventAndReference, event gomatrixserverlib.Event, latest []types.StateAtEventAndReference,
removed, added []types.StateEntry, removed, added []types.StateEntry,
stateBeforeEventRemoves, stateBeforeEventAdds []types.StateEntry,
) error { ) error {
latestEventIDs := make([]string, len(latest)) latestEventIDs := make([]string, len(latest))
@ -190,6 +202,13 @@ func writeEvent(
for _, entry := range removed { for _, entry := range removed {
stateEventNIDs = append(stateEventNIDs, entry.EventNID) 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) eventIDMap, err := db.EventIDs(stateEventNIDs)
if err != nil { if err != nil {
return err return err
@ -200,7 +219,18 @@ func writeEvent(
for _, entry := range removed { for _, entry := range removed {
ore.RemovesStateEventIDs = append(ore.RemovesStateEventIDs, eventIDMap[entry.EventNID]) 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 // TODO: Fill out VisibilityStateIDs
return ow.WriteOutputRoomEvent(ore) 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] }