Skip to content
This repository was archived by the owner on Nov 25, 2024. It is now read-only.

Peeking over federation via MSC2444 #1391

Merged
merged 92 commits into from
Jan 22, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
92 commits
Select commit Hold shift + click to select a range
b9342d9
a very very WIP first cut of peeking via MSC2753.
ara4n Aug 30, 2020
d7bdf71
make PeekingDeviceSet private
ara4n Aug 30, 2020
cfa0be5
merge master
ara4n Aug 31, 2020
9b79f9a
add server_name param
ara4n Aug 31, 2020
d343b8f
blind stab at adding a `peek` section to /sync
ara4n Aug 31, 2020
c4e5f60
make it build
ara4n Aug 31, 2020
d1e4d66
make it launch
ara4n Aug 31, 2020
f006b37
add peeking to getResponseWithPDUsForCompleteSync
ara4n Aug 31, 2020
6c3a896
cancel any peeks when we join a room
ara4n Aug 31, 2020
7b38d48
spell out how to runoutside of docker if you want speed
ara4n Aug 31, 2020
e589984
fix SQL
ara4n Aug 31, 2020
0bb2c2c
remove unnecessary txn for SelectPeeks
ara4n Aug 31, 2020
28219c6
Merge branch 'master' into matthew/peeking
ara4n Sep 1, 2020
86e9736
fix s/join/peek/ cargocult fail
ara4n Sep 1, 2020
d0d5f70
Merge branch 'master' into matthew/peeking
ara4n Sep 1, 2020
bfecc8e
HACK: Track goroutine IDs to determine when we write by the wrong thread
kegsay Sep 1, 2020
7bf2a27
Track partition offsets and only log unsafe for non-selects
kegsay Sep 1, 2020
fcdb90c
Put redactions in the writer goroutine
kegsay Sep 1, 2020
6410b70
Update filters on writer goroutine
kegsay Sep 1, 2020
ed4b3a5
Merge branch 'kegan/redact-txn' into matthew/peeking
ara4n Sep 1, 2020
3cebd8d
Merge branch 'kegan/HACK-goid-sqlite-db-is-locked' into matthew/peeking
ara4n Sep 1, 2020
5d7f688
wrap peek storage in goid hack
ara4n Sep 1, 2020
6424117
use exclusive writer, and MarkPeeksAsOld more efficiently
ara4n Sep 1, 2020
85bce11
don't log ascii in binary at sql trace...
ara4n Sep 1, 2020
75b91ac
strip out empty roomd deltas
ara4n Sep 1, 2020
b6cc441
re-add txn to SelectPeeks
ara4n Sep 2, 2020
f6af656
re-add accidentally deleted field
ara4n Sep 2, 2020
8712ea3
Merge branch 'master' into matthew/peeking
ara4n Sep 3, 2020
eda84cd
reject peeks for non-worldreadable rooms
ara4n Sep 3, 2020
da3742c
move perform_peek
ara4n Sep 3, 2020
3c5e079
fix package
ara4n Sep 3, 2020
994cc18
correctly refactor perform_peek
ara4n Sep 3, 2020
c1f1fcd
WIP of implementing MSC2444
ara4n Sep 4, 2020
4ca2cf4
typo
ara4n Sep 4, 2020
98cf898
Revert "Merge branch 'kegan/HACK-goid-sqlite-db-is-locked' into matth…
ara4n Sep 11, 2020
f236e82
Merge branch 'master' into matthew/peeking-over-fed
ara4n Sep 11, 2020
baee97b
(almost) make it build
ara4n Sep 11, 2020
4ef6a3c
clean up bad merge
ara4n Sep 11, 2020
65e59a1
support SendEventWithState with optional event
ara4n Sep 11, 2020
a5c0521
fix build & lint
ara4n Sep 11, 2020
df29509
fix build & lint
ara4n Sep 11, 2020
410ac72
reinstate federated peeks in the roomserver (doh)
ara4n Sep 11, 2020
f8bb448
fix sql thinko
ara4n Sep 11, 2020
fff1845
todo for authenticating state returned by /peek
ara4n Sep 12, 2020
c6a2604
support returning current state from QueryStateAndAuthChain
ara4n Sep 12, 2020
803647b
handle SS /peek
ara4n Sep 12, 2020
0ae0d11
reimplement SS /peek to prod the RS to tell the FS about the peek
ara4n Sep 12, 2020
4e96e62
rename RemotePeeks as OutboundPeeks
ara4n Sep 12, 2020
59e2be7
rename remote_peeks_table as outbound_peeks_table
ara4n Sep 12, 2020
36e32f1
add perform_handle_remote_peek.go
ara4n Sep 12, 2020
0dc422c
flesh out federation doc
ara4n Sep 12, 2020
71732f2
add inbound peeks table and hook it up
ara4n Sep 12, 2020
8f203fe
rename ambiguous RemotePeek as InboundPeek
ara4n Sep 12, 2020
3caae79
rename FSAPI's PerformPeek as PerformOutboundPeek
ara4n Sep 12, 2020
a160c07
setup inbound peeks db correctly
ara4n Sep 13, 2020
32f898d
fix api.SendEventWithState with no event
ara4n Sep 13, 2020
41b9b66
Merge branch 'master' into matthew/peeking-over-fed
ara4n Sep 19, 2020
20e2cb4
track latestevent on /peek
ara4n Sep 22, 2020
3202c7e
go fmt
ara4n Sep 22, 2020
0ab4bc9
document the peek send stream race better
ara4n Sep 22, 2020
75c3f2d
merge master
ara4n Sep 26, 2020
2b4353e
fix SendEventWithRewrite not to bail if handed a non-state event
ara4n Sep 26, 2020
927a62a
add fixme
ara4n Sep 26, 2020
1e6e23d
switch SS /peek to use SendEventWithRewrite
ara4n Sep 26, 2020
fd90849
fix comment
ara4n Sep 26, 2020
ed9e3fc
use reverse topo ordering to find latest extrem
ara4n Sep 26, 2020
efd8656
support postgres for federated peeking
ara4n Sep 27, 2020
ebeff8d
go fmt
ara4n Sep 27, 2020
4262095
back out bogus go.mod change
ara4n Sep 27, 2020
797085f
Merge branch 'master' into matthew/peeking-over-fed
neilalexander Oct 20, 2020
814c220
Merge branch 'master' into matthew/peeking-over-fed
neilalexander Oct 20, 2020
be5a4e6
Fix performOutboundPeekUsingServer
neilalexander Oct 20, 2020
90017d0
Fix getAuthChain -> GetAuthChain
neilalexander Oct 20, 2020
0fd9e96
Merge branch 'master' into matthew/peeking-over-fed
kegsay Oct 22, 2020
a2a5c7e
Merge branch 'master' into matthew/peeking-over-fed
neilalexander Dec 2, 2020
3ba3530
Merge branch 'master' into matthew/peeking-over-fed
neilalexander Dec 2, 2020
7fc3852
Fix build issues
neilalexander Dec 2, 2020
d25345d
Merge branch 'master' into matthew/peeking-over-fed
neilalexander Dec 3, 2020
c2f7c80
Fix build again
neilalexander Dec 3, 2020
fe1d2f8
Merge branch 'master' into matthew/peeking-over-fed
neilalexander Dec 3, 2020
45f0fdd
Merge branch 'master' into matthew/peeking-over-fed
neilalexander Dec 10, 2020
d47ab1f
Fix getAuthChain -> GetAuthChain
neilalexander Dec 10, 2020
0fe0e23
Don't repeat outbound peeks for the same room ID to the same servers
neilalexander Dec 10, 2020
e0a35c0
Fix lint
neilalexander Dec 10, 2020
8508af3
Merge branch 'master' into matthew/peeking-over-fed
neilalexander Dec 18, 2020
3985d03
Merge branch 'master' into matthew/peeking-over-fed
neilalexander Jan 13, 2021
f2dec90
Merge branch 'master' into matthew/peeking-over-fed
neilalexander Jan 18, 2021
609743b
Merge branch 'master' into matthew/peeking-over-fed
kegsay Jan 19, 2021
c71bf5d
Merge branch 'master' into matthew/peeking-over-fed
kegsay Jan 20, 2021
4491e53
Don't omitempty to appease sytest
kegsay Jan 22, 2021
552f583
Merge branch 'master' into matthew/peeking-over-fed
kegsay Jan 22, 2021
dd3c6ff
Merge branch 'master' into matthew/peeking-over-fed
kegsay Jan 22, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Merge branch 'master' into matthew/peeking-over-fed
  • Loading branch information
neilalexander authored Oct 20, 2020
commit 797085f1b7a66cb542af08fddd11d4b476a6d6be
97 changes: 93 additions & 4 deletions federationapi/routing/send.go
Original file line number Diff line number Diff line change
Expand Up @@ -523,10 +523,99 @@ func (t *txnReq) processEventWithMissingState(ctx context.Context, e gomatrixser
*gomatrixserverlib.RespState
}

// pass the event along with the state to the roomserver using a background context so we don't
// needlessly expire
headeredEvent := e.Headered(roomVersion)
return api.SendEventWithState(context.Background(), t.rsAPI, resolvedState, headeredEvent, t.haveEventIDs())
// at this point we know we're going to have a gap: we need to work out the room state at the new backwards extremity.
// Therefore, we cannot just query /state_ids with this event to get the state before. Instead, we need to query
// the state AFTER all the prev_events for this event, then apply state resolution to that to get the state before the event.
var states []*respState
for _, prevEventID := range backwardsExtremity.PrevEventIDs() {
// Look up what the state is after the backward extremity. This will either
// come from the roomserver, if we know all the required events, or it will
// come from a remote server via /state_ids if not.
prevState, trustworthy, lerr := t.lookupStateAfterEvent(gmectx, roomVersion, backwardsExtremity.RoomID(), prevEventID)
if lerr != nil {
util.GetLogger(ctx).WithError(lerr).Errorf("Failed to lookup state after prev_event: %s", prevEventID)
return lerr
}
// Append the state onto the collected state. We'll run this through the
// state resolution next.
states = append(states, &respState{trustworthy, prevState})
}

// Now that we have collected all of the state from the prev_events, we'll
// run the state through the appropriate state resolution algorithm for the
// room if needed. This does a couple of things:
// 1. Ensures that the state is deduplicated fully for each state-key tuple
// 2. Ensures that we pick the latest events from both sets, in the case that
// one of the prev_events is quite a bit older than the others
resolvedState := &gomatrixserverlib.RespState{}
switch len(states) {
case 0:
extremityIsCreate := backwardsExtremity.Type() == gomatrixserverlib.MRoomCreate && backwardsExtremity.StateKeyEquals("")
if !extremityIsCreate {
// There are no previous states and this isn't the beginning of the
// room - this is an error condition!
util.GetLogger(ctx).Errorf("Failed to lookup any state after prev_events")
return fmt.Errorf("expected %d states but got %d", len(backwardsExtremity.PrevEventIDs()), len(states))
}
case 1:
// There's only one previous state - if it's trustworthy (came from a
// local state snapshot which will already have been through state res),
// use it as-is. There's no point in resolving it again.
if states[0].trustworthy {
resolvedState = states[0].RespState
break
}
// Otherwise, if it isn't trustworthy (came from federation), run it through
// state resolution anyway for safety, in case there are duplicates.
fallthrough
default:
respStates := make([]*gomatrixserverlib.RespState, len(states))
for i := range states {
respStates[i] = states[i].RespState
}
// There's more than one previous state - run them all through state res
resolvedState, err = t.resolveStatesAndCheck(gmectx, roomVersion, respStates, backwardsExtremity)
if err != nil {
util.GetLogger(ctx).WithError(err).Errorf("Failed to resolve state conflicts for event %s", backwardsExtremity.EventID())
return err
}
}

// First of all, send the backward extremity into the roomserver with the
// newly resolved state. This marks the "oldest" point in the backfill and
// sets the baseline state for any new events after this.
err = api.SendEventWithState(
context.Background(),
t.rsAPI,
api.KindOld,
resolvedState,
backwardsExtremity.Headered(roomVersion),
t.haveEventIDs(),
)
if err != nil {
return fmt.Errorf("api.SendEventWithState: %w", err)
}

// Then send all of the newer backfilled events, of which will all be newer
// than the backward extremity, into the roomserver without state. This way
// they will automatically fast-forward based on the room state at the
// extremity in the last step.
headeredNewEvents := make([]gomatrixserverlib.HeaderedEvent, len(newEvents))
for i, newEvent := range newEvents {
headeredNewEvents[i] = newEvent.Headered(roomVersion)
}
if err = api.SendEvents(
context.Background(),
t.rsAPI,
api.KindOld,
append(headeredNewEvents, e.Headered(roomVersion)),
api.DoNotSendToOtherServers,
nil,
); err != nil {
return fmt.Errorf("api.SendEvents: %w", err)
}

return nil
}

// lookupStateAfterEvent returns the room state after `eventID`, which is the state before eventID with the state of `eventID` (if it's a state event)
Expand Down
90 changes: 0 additions & 90 deletions roomserver/api/wrapper.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,96 +82,6 @@ func SendEventWithState(
return SendInputRoomEvents(ctx, rsAPI, ires)
}

// SendEventWithRewrite writes an event with KindNew to the roomserver along
// with a number of rewrite and outlier events for state and auth events
// respectively.
func SendEventWithRewrite(
ctx context.Context, rsAPI RoomserverInternalAPI, state *gomatrixserverlib.RespState,
event gomatrixserverlib.HeaderedEvent, haveEventIDs map[string]bool,
) error {
isCurrentState := map[string]struct{}{}
for _, se := range state.StateEvents {
isCurrentState[se.EventID()] = struct{}{}
}

authAndStateEvents, err := state.Events()
if err != nil {
return err
}

var ires []InputRoomEvent
var stateIDs []string

// This function generates three things:
// A - A set of "rewrite" events, which will form the newly rewritten
// state before the event, which includes every rewrite event that
// came before it in its state
// B - A set of "outlier" events, which are auth events but not part
// of the rewritten state
// C - A "new" event, which include all of the rewrite events in its
// state
for _, authOrStateEvent := range authAndStateEvents {
if authOrStateEvent.StateKey() == nil {
continue
}
if haveEventIDs[authOrStateEvent.EventID()] {
continue
}

// We will handle an event as if it's an outlier if one of the
// following conditions is true:
storeAsOutlier := false
if _, ok := isCurrentState[authOrStateEvent.EventID()]; !ok {
// The event is an auth event and isn't a part of the state set.
// We'll send it as an outlier because we need it to be stored
// in case something is referring to it as an auth event.
storeAsOutlier = true
}

if storeAsOutlier {
ires = append(ires, InputRoomEvent{
Kind: KindOutlier,
Event: authOrStateEvent.Headered(event.RoomVersion),
AuthEventIDs: authOrStateEvent.AuthEventIDs(),
})
continue
}

// If the event isn't an outlier then we'll instead send it as a
// rewrite event, so that it'll form part of the rewritten state.
// These events will go through the membership and latest event
// updaters and we will generate output events, but they will be
// flagged as non-current (i.e. didn't just happen) events.
// Each of these rewrite events includes all of the rewrite events
// that came before in their StateEventIDs.
ires = append(ires, InputRoomEvent{
Kind: KindRewrite,
Event: authOrStateEvent.Headered(event.RoomVersion),
AuthEventIDs: authOrStateEvent.AuthEventIDs(),
HasState: true,
StateEventIDs: stateIDs,
})

// Add the event ID into the StateEventIDs of all subsequent
// rewrite events, and the new event.
stateIDs = append(stateIDs, authOrStateEvent.EventID())
}

// Send the final event as a new event, which will generate
// a timeline output event for it. All of the rewrite events
// that came before will be sent as StateEventIDs, forming a
// new clean state before the event.
ires = append(ires, InputRoomEvent{
Kind: KindNew,
Event: event,
AuthEventIDs: event.AuthEventIDs(),
HasState: true,
StateEventIDs: stateIDs,
})

return SendInputRoomEvents(ctx, rsAPI, ires)
}

// SendInputRoomEvents to the roomserver.
func SendInputRoomEvents(
ctx context.Context, rsAPI RoomserverInternalAPI, ires []InputRoomEvent,
Expand Down
You are viewing a condensed version of this merge commit. You can view the full changes here.