From f1ffe9b4cd7eb76a2df033dbd592aff2200c0d19 Mon Sep 17 00:00:00 2001 From: June Date: Fri, 15 Aug 2025 21:36:23 +0200 Subject: [PATCH] parallelize retrieval of server version information Parallelizing the retrieval of the server version information decreases the program runtime, especially since the impact of slow responses and timeouts is lowered greatly. --- main.go | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 52 insertions(+), 4 deletions(-) diff --git a/main.go b/main.go index 23baa9a..ceda106 100644 --- a/main.go +++ b/main.go @@ -7,6 +7,7 @@ import ( "os" "sort" "strings" + "sync" "github.com/hashicorp/go-version" "github.com/matrix-org/gomatrixserverlib/fclient" @@ -15,6 +16,11 @@ import ( "maunium.net/go/mautrix/id" ) +type HomeserverServerVersionInfo struct { + Homeserver string + ServerVersionInfo fclient.Version +} + type ServerPath struct { MaxRoomVersion string Server string @@ -36,6 +42,44 @@ var unknownServerVersionInfo = fclient.Version{ }, } +func getServerVersionInfoByHomeserver(homeservers []string, federationClient *fclient.Client) map[string](fclient.Version) { + homeserverChannel := make(chan string) + go func() { + for _, hs := range homeservers { + homeserverChannel <- hs + } + close(homeserverChannel) + }() + + homeserverSVInfoChannel := make(chan HomeserverServerVersionInfo) + var wg sync.WaitGroup + const numHomeserverSVInfoReceivers = 100 + wg.Add(numHomeserverSVInfoReceivers) + for i := 0; i < numHomeserverSVInfoReceivers; i++ { + go func() { + for hs := range homeserverChannel { + serverVersionInfo, err := federationClient.GetVersion(context.Background(), spec.ServerName(hs)) + if err != nil { + serverVersionInfo = unknownServerVersionInfo + } + homeserverSVInfoChannel <- HomeserverServerVersionInfo{hs, serverVersionInfo} + } + wg.Done() + }() + } + + go func() { + wg.Wait() + close(homeserverSVInfoChannel) + }() + + serverVersionInfoByHomeserver := make(map[string](fclient.Version)) + for homeserverSVInfo := range homeserverSVInfoChannel { + serverVersionInfoByHomeserver[homeserverSVInfo.Homeserver] = homeserverSVInfo.ServerVersionInfo + } + return serverVersionInfoByHomeserver +} + // Gets the maximum supported room version for the given server-version-pair. func getMaxRoomVersion(serverVersionInfo fclient.Version) string { // Use only the first part of the version string as sometimes there are suffixes after a space, like " ()", which then can't be parsed. @@ -235,6 +279,13 @@ func main() { membersByHomeservers[key.Homeserver()]++ } + homeservers := make([]string, 0, len(membersByHomeservers)) + for hs := range membersByHomeservers { + homeservers = append(homeservers, hs) + } + + serverVersionInfoByHomeserver := getServerVersionInfoByHomeserver(homeservers, federationClient) + // Info map tree. maxRoomVersionInfo := make(map[string](map[string](map[string](map[string]uint)))) // Member counters. @@ -243,10 +294,7 @@ func main() { membersByVersionPath := make(map[VersionPath]uint) for key, value := range membersByHomeservers { - serverVersionInfo, err := federationClient.GetVersion(context.Background(), spec.ServerName(key)) - if err != nil { - serverVersionInfo = unknownServerVersionInfo - } + serverVersionInfo := serverVersionInfoByHomeserver[key] maxRoomVersion := getMaxRoomVersion(serverVersionInfo)