Add a very basic /initialSync implementation

This is done by coercing a full sync response into the right shape.

Some notable TODOs:

- Support specifying a limt
- Support invites
- Correctly format events
- Add presence, account data, etc
This commit is contained in:
Erik Johnston 2017-10-03 13:36:36 +01:00
parent bcf58fad84
commit 214d856674
7 changed files with 127 additions and 25 deletions

View file

@ -352,23 +352,4 @@ func Setup(
return util.JSONResponse{Code: 200, JSON: struct{}{}}
}),
).Methods("PUT", "OPTIONS")
// Stub implementations for sytest
r0mux.Handle("/events",
common.MakeExternalAPI("events", func(req *http.Request) util.JSONResponse {
return util.JSONResponse{Code: 200, JSON: map[string]interface{}{
"chunk": []interface{}{},
"start": "",
"end": "",
}}
}),
).Methods("GET")
r0mux.Handle("/initialSync",
common.MakeExternalAPI("initial_sync", func(req *http.Request) util.JSONResponse {
return util.JSONResponse{Code: 200, JSON: map[string]interface{}{
"end": "",
}}
}),
).Methods("GET")
}

View file

@ -336,7 +336,7 @@ func (m *monolith) setupAPIs() {
syncapi_routing.Setup(m.api, syncapi_sync.NewRequestPool(
m.syncAPIDB, m.syncAPINotifier, m.accountDB,
), m.deviceDB)
), m.deviceDB, m.syncAPIDB)
federationapi_routing.Setup(
m.api, *m.cfg, m.queryAPI, m.roomServerProducer, m.keyRing, m.federation,

View file

@ -104,7 +104,7 @@ func main() {
log.Info("Starting sync server on ", cfg.Listen.SyncAPI)
api := mux.NewRouter()
routing.Setup(api, sync.NewRequestPool(db, n, adb), deviceDB)
routing.Setup(api, sync.NewRequestPool(db, n, adb), deviceDB, db)
common.SetupHTTPAPI(http.DefaultServeMux, api)
log.Fatal(http.ListenAndServe(string(cfg.Listen.SyncAPI), nil))

View file

@ -21,6 +21,7 @@ import (
"github.com/matrix-org/dendrite/clientapi/auth/authtypes"
"github.com/matrix-org/dendrite/clientapi/auth/storage/devices"
"github.com/matrix-org/dendrite/common"
"github.com/matrix-org/dendrite/syncapi/storage"
"github.com/matrix-org/dendrite/syncapi/sync"
"github.com/matrix-org/util"
)
@ -28,7 +29,12 @@ import (
const pathPrefixR0 = "/_matrix/client/r0"
// Setup configures the given mux with sync-server listeners
func Setup(apiMux *mux.Router, srp *sync.RequestPool, deviceDB *devices.Database) {
func Setup(
apiMux *mux.Router,
srp *sync.RequestPool,
deviceDB *devices.Database,
syncDB *storage.SyncServerDatabase,
) {
r0mux := apiMux.PathPrefix(pathPrefixR0).Subrouter()
r0mux.Handle("/sync", common.MakeAuthAPI("sync", deviceDB, func(req *http.Request, device *authtypes.Device) util.JSONResponse {
@ -39,4 +45,23 @@ func Setup(apiMux *mux.Router, srp *sync.RequestPool, deviceDB *devices.Database
vars := mux.Vars(req)
return srp.OnIncomingStateRequest(req, vars["roomID"])
})).Methods("GET")
// Stub implementations for sytest
r0mux.Handle("/events",
common.MakeExternalAPI("events", func(req *http.Request) util.JSONResponse {
return util.JSONResponse{Code: 200, JSON: map[string]interface{}{
"chunk": []interface{}{},
"start": "",
"end": "",
}}
}),
).Methods("GET")
r0mux.Handle("/initialSync",
common.MakeAuthAPI("initial_sync", deviceDB, func(req *http.Request, device *authtypes.Device) util.JSONResponse {
return sync.GetInitialSync(
req, device, syncDB,
)
}),
).Methods("GET")
}

View file

@ -0,0 +1,93 @@
// Copyright 2017 Vector Creations Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package sync
import (
"net/http"
"github.com/matrix-org/dendrite/clientapi/auth/authtypes"
"github.com/matrix-org/dendrite/clientapi/httputil"
"github.com/matrix-org/dendrite/syncapi/storage"
"github.com/matrix-org/dendrite/syncapi/types"
"github.com/matrix-org/gomatrixserverlib"
"github.com/matrix-org/util"
)
// GetInitialSync gets called on an /initialSync request.
func GetInitialSync(
req *http.Request, device *authtypes.Device,
db *storage.SyncServerDatabase,
) util.JSONResponse {
// TODO: Support limit
syncResponse, err := db.CompleteSync(
req.Context(), device.UserID, DefaultTimelineLimit,
)
if err != nil {
return httputil.LogThenError(req, err)
}
intialSyncResponse := syncResponseToIntialSync(syncResponse)
return util.JSONResponse{
Code: 200,
JSON: intialSyncResponse,
}
}
func syncResponseToIntialSync(syncResponse *types.Response) initialSyncResponse {
var rooms []initialSyncRoomResponse
for roomID, room := range syncResponse.Rooms.Join {
rooms = append(rooms, initialSyncRoomResponse{
RoomID: roomID,
Membership: "join",
Messages: initialSyncChunk{
Chunk: room.Timeline.Events, // TODO: Correctly format events
End: room.Timeline.PrevBatch, // TODO: Start?
},
State: initialSyncChunk{
Chunk: room.State.Events, // TODO: Add state from timeline
},
})
}
// TODO: Invites, leaves, account data, presence, etc.
return initialSyncResponse{
Rooms: rooms,
End: syncResponse.NextBatch,
}
}
type initialSyncResponse struct {
End string `json:"end"`
Rooms []initialSyncRoomResponse `json:"rooms"`
}
type initialSyncRoomResponse struct {
Membership string `json:"membership"`
RoomID string `json:"room_id"`
Messages initialSyncChunk `json:"messages,omitempty"`
State initialSyncChunk `json:"state,omitempty"`
}
type initialSyncChunk struct {
Start string `json:"start"`
End string `json:"end"`
Chunk []gomatrixserverlib.ClientEvent `json:"chunk"`
}

View file

@ -286,7 +286,7 @@ func newTestSyncRequest(userID string, since types.StreamPosition) syncRequest {
timeout: 1 * time.Minute,
since: since,
wantFullState: false,
limit: defaultTimelineLimit,
limit: DefaultTimelineLimit,
log: util.GetLogger(context.TODO()),
}
}

View file

@ -26,7 +26,10 @@ import (
)
const defaultSyncTimeout = time.Duration(30) * time.Second
const defaultTimelineLimit = 20
// DefaultTimelineLimit is the default number limit of timeline entries if no
// limit was given.
const DefaultTimelineLimit = 20
// syncRequest represents a /sync request, with sensible defaults/sanity checks applied.
type syncRequest struct {
@ -54,7 +57,7 @@ func newSyncRequest(req *http.Request, userID string) (*syncRequest, error) {
timeout: timeout,
since: since,
wantFullState: wantFullState,
limit: defaultTimelineLimit, // TODO: read from filter
limit: DefaultTimelineLimit, // TODO: read from filter
log: util.GetLogger(req.Context()),
}, nil
}