From ff96802e61662dd30dcbc6f0d6090c370d1c9879 Mon Sep 17 00:00:00 2001
From: Travis Ralston <travpc@gmail.com>
Date: Sun, 25 Apr 2021 15:04:41 -0600
Subject: [PATCH] Improve datastore selection for single-kind datastores

---
 CHANGELOG.md                   |  4 ++++
 storage/datastore/datastore.go | 19 ++++++++++++++-----
 2 files changed, 18 insertions(+), 5 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index fc53c1b5..78ad37d7 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -16,6 +16,10 @@ caching that is now supported properly by this release, or disable caching if no
 
 * Support the Redis config at the root level of the config, promoting it to a proper feature.
 
+### Fixed
+
+* Improved performance of datastore selection when only one datastore is eligible to contain media.
+
 ## [1.2.7] - April 19th, 2021
 
 ### Security advisories
diff --git a/storage/datastore/datastore.go b/storage/datastore/datastore.go
index 687f74ea..26a9f35e 100644
--- a/storage/datastore/datastore.go
+++ b/storage/datastore/datastore.go
@@ -3,11 +3,11 @@ package datastore
 import (
 	"fmt"
 	"github.com/getsentry/sentry-go"
+	"github.com/turt2live/matrix-media-repo/common"
 	"io"
 
 	"github.com/pkg/errors"
 	"github.com/sirupsen/logrus"
-	"github.com/turt2live/matrix-media-repo/common"
 	"github.com/turt2live/matrix-media-repo/common/config"
 	"github.com/turt2live/matrix-media-repo/common/rcontext"
 	"github.com/turt2live/matrix-media-repo/storage"
@@ -102,9 +102,10 @@ func PickDatastore(forKind string, ctx rcontext.RequestContext) (*DatastoreRef,
 	confDatastores := ctx.Config.DataStores
 	mediaStore := storage.GetDatabase().GetMediaStore(ctx)
 
-	var targetDs *types.Datastore
-	var targetDsConf config.DatastoreConfig
-	var dsSize int64
+	// Figure out which datastores are likely to be useful for us to check against first. This
+	// helps speed up later checks which could require significant DB resources (estimating the
+	// size of the datastore).
+	var possibleDatastores = make([]config.DatastoreConfig, 0)
 	for _, dsConf := range confDatastores {
 		if !dsConf.Enabled {
 			continue
@@ -115,6 +116,14 @@ func PickDatastore(forKind string, ctx rcontext.RequestContext) (*DatastoreRef,
 			continue
 		}
 
+		possibleDatastores = append(possibleDatastores, dsConf)
+	}
+
+	var targetDs *types.Datastore
+	var targetDsConf config.DatastoreConfig
+	var dsSize int64
+	for _, dsConf := range possibleDatastores {
+
 		ds, err := mediaStore.GetDatastoreByUri(GetUriForDatastore(dsConf))
 		if err != nil {
 			ctx.Log.Error("Error getting datastore: ", err.Error())
@@ -124,7 +133,7 @@ func PickDatastore(forKind string, ctx rcontext.RequestContext) (*DatastoreRef,
 
 		var size int64
 
-		if len(confDatastores) > 1 {
+		if len(possibleDatastores) > 1 {
 			size, err = estimatedDatastoreSize(ds, ctx)
 			if err != nil {
 				ctx.Log.Error("Error estimating datastore size for ", ds.DatastoreId, ": ", err.Error())
-- 
GitLab