mirror of
https://github.com/matrix-org/dendrite.git
synced 2025-12-21 05:43:09 -06:00
Change API and rename to ExtraPublicRoomsProvider
This commit is contained in:
parent
38caf8e5b7
commit
cd3da772de
|
|
@ -14,9 +14,10 @@
|
||||||
|
|
||||||
package api
|
package api
|
||||||
|
|
||||||
type ExternalPublicRoomsProvider interface {
|
import "github.com/matrix-org/gomatrixserverlib"
|
||||||
// The list of homeserver domains to query. These servers will receive a request
|
|
||||||
// via this API: https://matrix.org/docs/spec/server_server/latest#public-room-directory
|
// ExtraPublicRoomsProvider provides a way to inject extra published rooms into /publicRooms requests.
|
||||||
// This will be called -on demand- by clients, so cache appropriately!
|
type ExtraPublicRoomsProvider interface {
|
||||||
Homeservers() []string
|
// Rooms returns the extra rooms. This is called on-demand by clients, so cache appropriately.
|
||||||
|
Rooms() []gomatrixserverlib.PublicRoom
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@ func AddPublicRoutes(
|
||||||
transactionsCache *transactions.Cache,
|
transactionsCache *transactions.Cache,
|
||||||
fsAPI federationSenderAPI.FederationSenderInternalAPI,
|
fsAPI federationSenderAPI.FederationSenderInternalAPI,
|
||||||
userAPI userapi.UserInternalAPI,
|
userAPI userapi.UserInternalAPI,
|
||||||
extRoomsProvider api.ExternalPublicRoomsProvider,
|
extRoomsProvider api.ExtraPublicRoomsProvider,
|
||||||
) {
|
) {
|
||||||
syncProducer := &producers.SyncAPIProducer{
|
syncProducer := &producers.SyncAPIProducer{
|
||||||
Producer: producer,
|
Producer: producer,
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,6 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/matrix-org/dendrite/clientapi/api"
|
"github.com/matrix-org/dendrite/clientapi/api"
|
||||||
"github.com/matrix-org/dendrite/clientapi/httputil"
|
"github.com/matrix-org/dendrite/clientapi/httputil"
|
||||||
|
|
@ -33,6 +32,11 @@ import (
|
||||||
"github.com/matrix-org/util"
|
"github.com/matrix-org/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
cacheMu sync.Mutex
|
||||||
|
publicRoomsCache []gomatrixserverlib.PublicRoom
|
||||||
|
)
|
||||||
|
|
||||||
type PublicRoomReq struct {
|
type PublicRoomReq struct {
|
||||||
Since string `json:"since,omitempty"`
|
Since string `json:"since,omitempty"`
|
||||||
Limit int16 `json:"limit,omitempty"`
|
Limit int16 `json:"limit,omitempty"`
|
||||||
|
|
@ -46,13 +50,15 @@ type filter struct {
|
||||||
// GetPostPublicRooms implements GET and POST /publicRooms
|
// GetPostPublicRooms implements GET and POST /publicRooms
|
||||||
func GetPostPublicRooms(
|
func GetPostPublicRooms(
|
||||||
req *http.Request, rsAPI roomserverAPI.RoomserverInternalAPI, stateAPI currentstateAPI.CurrentStateInternalAPI,
|
req *http.Request, rsAPI roomserverAPI.RoomserverInternalAPI, stateAPI currentstateAPI.CurrentStateInternalAPI,
|
||||||
|
extRoomsProvider api.ExtraPublicRoomsProvider,
|
||||||
) util.JSONResponse {
|
) util.JSONResponse {
|
||||||
var request PublicRoomReq
|
var request PublicRoomReq
|
||||||
if fillErr := fillPublicRoomsReq(req, &request); fillErr != nil {
|
if fillErr := fillPublicRoomsReq(req, &request); fillErr != nil {
|
||||||
return *fillErr
|
return *fillErr
|
||||||
}
|
}
|
||||||
response, err := publicRooms(req.Context(), request, rsAPI, stateAPI)
|
response, err := publicRooms(req.Context(), request, rsAPI, stateAPI, extRoomsProvider)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
util.GetLogger(req.Context()).WithError(err).Errorf("failed to work out public rooms")
|
||||||
return jsonerror.InternalServerError()
|
return jsonerror.InternalServerError()
|
||||||
}
|
}
|
||||||
return util.JSONResponse{
|
return util.JSONResponse{
|
||||||
|
|
@ -64,13 +70,13 @@ func GetPostPublicRooms(
|
||||||
// GetPostPublicRoomsWithExternal is the same as GetPostPublicRooms but also mixes in public rooms from the provider supplied.
|
// GetPostPublicRoomsWithExternal is the same as GetPostPublicRooms but also mixes in public rooms from the provider supplied.
|
||||||
func GetPostPublicRoomsWithExternal(
|
func GetPostPublicRoomsWithExternal(
|
||||||
req *http.Request, rsAPI roomserverAPI.RoomserverInternalAPI, stateAPI currentstateAPI.CurrentStateInternalAPI,
|
req *http.Request, rsAPI roomserverAPI.RoomserverInternalAPI, stateAPI currentstateAPI.CurrentStateInternalAPI,
|
||||||
fedClient *gomatrixserverlib.FederationClient, extRoomsProvider api.ExternalPublicRoomsProvider,
|
fedClient *gomatrixserverlib.FederationClient, extRoomsProvider api.ExtraPublicRoomsProvider,
|
||||||
) util.JSONResponse {
|
) util.JSONResponse {
|
||||||
var request PublicRoomReq
|
var request PublicRoomReq
|
||||||
if fillErr := fillPublicRoomsReq(req, &request); fillErr != nil {
|
if fillErr := fillPublicRoomsReq(req, &request); fillErr != nil {
|
||||||
return *fillErr
|
return *fillErr
|
||||||
}
|
}
|
||||||
response, err := publicRooms(req.Context(), request, rsAPI, stateAPI)
|
response, err := publicRooms(req.Context(), request, rsAPI, stateAPI, extRoomsProvider)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return jsonerror.InternalServerError()
|
return jsonerror.InternalServerError()
|
||||||
}
|
}
|
||||||
|
|
@ -98,8 +104,8 @@ func GetPostPublicRoomsWithExternal(
|
||||||
}
|
}
|
||||||
|
|
||||||
// downcasting `limit` is safe as we know it isn't bigger than request.Limit which is int16
|
// downcasting `limit` is safe as we know it isn't bigger than request.Limit which is int16
|
||||||
fedRooms := bulkFetchPublicRoomsFromServers(req.Context(), fedClient, extRoomsProvider.Homeservers(), int16(limit))
|
//fedRooms := bulkFetchPublicRoomsFromServers(req.Context(), fedClient, extRoomsProvider.Homeservers(), int16(limit))
|
||||||
response.Chunk = append(response.Chunk, fedRooms...)
|
//response.Chunk = append(response.Chunk, fedRooms...)
|
||||||
|
|
||||||
// de-duplicate rooms with the same room ID. We can join the room via any of these aliases as we know these servers
|
// de-duplicate rooms with the same room ID. We can join the room via any of these aliases as we know these servers
|
||||||
// are alive and well, so we arbitrarily pick one (purposefully shuffling them to spread the load a bit)
|
// are alive and well, so we arbitrarily pick one (purposefully shuffling them to spread the load a bit)
|
||||||
|
|
@ -128,6 +134,7 @@ func GetPostPublicRoomsWithExternal(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
// bulkFetchPublicRoomsFromServers fetches public rooms from the list of homeservers.
|
// bulkFetchPublicRoomsFromServers fetches public rooms from the list of homeservers.
|
||||||
// Returns a list of public rooms up to the limit specified.
|
// Returns a list of public rooms up to the limit specified.
|
||||||
func bulkFetchPublicRoomsFromServers(
|
func bulkFetchPublicRoomsFromServers(
|
||||||
|
|
@ -198,9 +205,11 @@ FanIn:
|
||||||
|
|
||||||
return publicRooms
|
return publicRooms
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
func publicRooms(ctx context.Context, request PublicRoomReq, rsAPI roomserverAPI.RoomserverInternalAPI,
|
func publicRooms(ctx context.Context, request PublicRoomReq, rsAPI roomserverAPI.RoomserverInternalAPI,
|
||||||
stateAPI currentstateAPI.CurrentStateInternalAPI) (*gomatrixserverlib.RespPublicRooms, error) {
|
stateAPI currentstateAPI.CurrentStateInternalAPI, extRoomsProvider api.ExtraPublicRoomsProvider,
|
||||||
|
) (*gomatrixserverlib.RespPublicRooms, error) {
|
||||||
|
|
||||||
var response gomatrixserverlib.RespPublicRooms
|
var response gomatrixserverlib.RespPublicRooms
|
||||||
var limit int16
|
var limit int16
|
||||||
|
|
@ -216,23 +225,25 @@ func publicRooms(ctx context.Context, request PublicRoomReq, rsAPI roomserverAPI
|
||||||
util.GetLogger(ctx).WithError(err).Error("strconv.ParseInt failed")
|
util.GetLogger(ctx).WithError(err).Error("strconv.ParseInt failed")
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
err = nil
|
||||||
|
|
||||||
var queryRes roomserverAPI.QueryPublishedRoomsResponse
|
var rooms []gomatrixserverlib.PublicRoom
|
||||||
err = rsAPI.QueryPublishedRooms(ctx, &roomserverAPI.QueryPublishedRoomsRequest{}, &queryRes)
|
if request.Since == "" {
|
||||||
if err != nil {
|
rooms = refreshPublicRoomCache(ctx, rsAPI, extRoomsProvider, stateAPI)
|
||||||
util.GetLogger(ctx).WithError(err).Error("QueryPublishedRooms failed")
|
} else {
|
||||||
return nil, err
|
rooms = getPublicRoomsFromCache()
|
||||||
}
|
}
|
||||||
response.TotalRoomCountEstimate = len(queryRes.RoomIDs)
|
|
||||||
|
|
||||||
roomIDs, prev, next := sliceInto(queryRes.RoomIDs, offset, limit)
|
response.TotalRoomCountEstimate = len(rooms)
|
||||||
|
|
||||||
|
chunk, prev, next := sliceInto(rooms, offset, limit)
|
||||||
if prev >= 0 {
|
if prev >= 0 {
|
||||||
response.PrevBatch = "T" + strconv.Itoa(prev)
|
response.PrevBatch = "T" + strconv.Itoa(prev)
|
||||||
}
|
}
|
||||||
if next >= 0 {
|
if next >= 0 {
|
||||||
response.NextBatch = "T" + strconv.Itoa(next)
|
response.NextBatch = "T" + strconv.Itoa(next)
|
||||||
}
|
}
|
||||||
response.Chunk, err = fillInRooms(ctx, roomIDs, stateAPI)
|
response.Chunk = chunk
|
||||||
return &response, err
|
return &response, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -348,7 +359,7 @@ func fillInRooms(ctx context.Context, roomIDs []string, stateAPI currentstateAPI
|
||||||
// limit=3&since=6 => G (prev='3', next='')
|
// limit=3&since=6 => G (prev='3', next='')
|
||||||
//
|
//
|
||||||
// A value of '-1' for prev/next indicates no position.
|
// A value of '-1' for prev/next indicates no position.
|
||||||
func sliceInto(slice []string, since int64, limit int16) (subset []string, prev, next int) {
|
func sliceInto(slice []gomatrixserverlib.PublicRoom, since int64, limit int16) (subset []gomatrixserverlib.PublicRoom, prev, next int) {
|
||||||
prev = -1
|
prev = -1
|
||||||
next = -1
|
next = -1
|
||||||
|
|
||||||
|
|
@ -371,3 +382,41 @@ func sliceInto(slice []string, since int64, limit int16) (subset []string, prev,
|
||||||
subset = slice[since:nextIndex]
|
subset = slice[since:nextIndex]
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func refreshPublicRoomCache(
|
||||||
|
ctx context.Context, rsAPI roomserverAPI.RoomserverInternalAPI, extRoomsProvider api.ExtraPublicRoomsProvider,
|
||||||
|
stateAPI currentstateAPI.CurrentStateInternalAPI,
|
||||||
|
) []gomatrixserverlib.PublicRoom {
|
||||||
|
cacheMu.Lock()
|
||||||
|
defer cacheMu.Unlock()
|
||||||
|
var extraRooms []gomatrixserverlib.PublicRoom
|
||||||
|
if extRoomsProvider != nil {
|
||||||
|
extraRooms = extRoomsProvider.Rooms()
|
||||||
|
}
|
||||||
|
|
||||||
|
var queryRes roomserverAPI.QueryPublishedRoomsResponse
|
||||||
|
err := rsAPI.QueryPublishedRooms(ctx, &roomserverAPI.QueryPublishedRoomsRequest{}, &queryRes)
|
||||||
|
if err != nil {
|
||||||
|
util.GetLogger(ctx).WithError(err).Error("QueryPublishedRooms failed")
|
||||||
|
return publicRoomsCache
|
||||||
|
}
|
||||||
|
pubRooms, err := fillInRooms(ctx, queryRes.RoomIDs, stateAPI)
|
||||||
|
if err != nil {
|
||||||
|
util.GetLogger(ctx).WithError(err).Error("fillInRooms failed")
|
||||||
|
return publicRoomsCache
|
||||||
|
}
|
||||||
|
publicRoomsCache = []gomatrixserverlib.PublicRoom{}
|
||||||
|
publicRoomsCache = append(publicRoomsCache, pubRooms...)
|
||||||
|
publicRoomsCache = append(publicRoomsCache, extraRooms...)
|
||||||
|
// sort by total joined member count (big to small)
|
||||||
|
sort.SliceStable(publicRoomsCache, func(i, j int) bool {
|
||||||
|
return publicRoomsCache[i].JoinedMembersCount > publicRoomsCache[j].JoinedMembersCount
|
||||||
|
})
|
||||||
|
return publicRoomsCache
|
||||||
|
}
|
||||||
|
|
||||||
|
func getPublicRoomsFromCache() []gomatrixserverlib.PublicRoom {
|
||||||
|
cacheMu.Lock()
|
||||||
|
defer cacheMu.Unlock()
|
||||||
|
return publicRoomsCache
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,16 +3,26 @@ package routing
|
||||||
import (
|
import (
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/matrix-org/gomatrixserverlib"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func pubRoom(name string) gomatrixserverlib.PublicRoom {
|
||||||
|
return gomatrixserverlib.PublicRoom{
|
||||||
|
Name: name,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestSliceInto(t *testing.T) {
|
func TestSliceInto(t *testing.T) {
|
||||||
slice := []string{"a", "b", "c", "d", "e", "f", "g"}
|
slice := []gomatrixserverlib.PublicRoom{
|
||||||
|
pubRoom("a"), pubRoom("b"), pubRoom("c"), pubRoom("d"), pubRoom("e"), pubRoom("f"), pubRoom("g"),
|
||||||
|
}
|
||||||
limit := int16(3)
|
limit := int16(3)
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
since int64
|
since int64
|
||||||
wantPrev int
|
wantPrev int
|
||||||
wantNext int
|
wantNext int
|
||||||
wantSubset []string
|
wantSubset []gomatrixserverlib.PublicRoom
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
since: 0,
|
since: 0,
|
||||||
|
|
|
||||||
|
|
@ -61,7 +61,7 @@ func Setup(
|
||||||
transactionsCache *transactions.Cache,
|
transactionsCache *transactions.Cache,
|
||||||
federationSender federationSenderAPI.FederationSenderInternalAPI,
|
federationSender federationSenderAPI.FederationSenderInternalAPI,
|
||||||
stateAPI currentstateAPI.CurrentStateInternalAPI,
|
stateAPI currentstateAPI.CurrentStateInternalAPI,
|
||||||
extRoomsProvider api.ExternalPublicRoomsProvider,
|
extRoomsProvider api.ExtraPublicRoomsProvider,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
publicAPIMux.Handle("/client/versions",
|
publicAPIMux.Handle("/client/versions",
|
||||||
|
|
@ -313,11 +313,7 @@ func Setup(
|
||||||
).Methods(http.MethodPut, http.MethodOptions)
|
).Methods(http.MethodPut, http.MethodOptions)
|
||||||
r0mux.Handle("/publicRooms",
|
r0mux.Handle("/publicRooms",
|
||||||
httputil.MakeExternalAPI("public_rooms", func(req *http.Request) util.JSONResponse {
|
httputil.MakeExternalAPI("public_rooms", func(req *http.Request) util.JSONResponse {
|
||||||
/* TODO:
|
return GetPostPublicRooms(req, rsAPI, stateAPI, extRoomsProvider)
|
||||||
if extRoomsProvider != nil {
|
|
||||||
return GetPostPublicRoomsWithExternal(req, stateAPI, fedClient, extRoomsProvider)
|
|
||||||
} */
|
|
||||||
return GetPostPublicRooms(req, rsAPI, stateAPI)
|
|
||||||
}),
|
}),
|
||||||
).Methods(http.MethodGet, http.MethodPost, http.MethodOptions)
|
).Methods(http.MethodGet, http.MethodPost, http.MethodOptions)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -62,6 +62,10 @@ func (p *libp2pPublicRoomsProvider) foundProviders(peerInfos []go_http_js_libp2p
|
||||||
p.providers = peerInfos
|
p.providers = peerInfos
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *libp2pPublicRoomsProvider) Rooms() []gomatrixserverlib.PublicRoom {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (p *libp2pPublicRoomsProvider) Homeservers() []string {
|
func (p *libp2pPublicRoomsProvider) Homeservers() []string {
|
||||||
result := make([]string, len(p.providers))
|
result := make([]string, len(p.providers))
|
||||||
for i := range p.providers {
|
for i := range p.providers {
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,7 @@ type Monolith struct {
|
||||||
StateAPI currentstateAPI.CurrentStateInternalAPI
|
StateAPI currentstateAPI.CurrentStateInternalAPI
|
||||||
|
|
||||||
// Optional
|
// Optional
|
||||||
ExtPublicRoomsProvider api.ExternalPublicRoomsProvider
|
ExtPublicRoomsProvider api.ExtraPublicRoomsProvider
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddAllPublicRoutes attaches all public paths to the given router
|
// AddAllPublicRoutes attaches all public paths to the given router
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue