diff --git a/api-users.go b/api-users.go index cf77781..adaad24 100644 --- a/api-users.go +++ b/api-users.go @@ -902,9 +902,23 @@ func (app *appContext) AdminPasswordReset(gc *gin.Context) { respondBool(204, true, gc) } +// getActiveReferrals returns a map of jellyfin user IDs to their active referral "invite" code, if they have one. +// It does not check if the user still exists, simply finding invites with the ReferrerJellyfinID field set. +func (app *appContext) getActiveReferrals() map[string]string { + out := map[string]string{} + for _, inv := range app.storage.GetInvites() { + if inv.ReferrerJellyfinID == "" { + continue + } + out[inv.ReferrerJellyfinID] = inv.Code + } + return out +} + // userSummary generates a respUser for to be displayed to the user, or sorted/filtered. // also, consider it a source of which data fields/struct modifications need to trigger a cache invalidation. -func (app *appContext) userSummary(jfUser mediabrowser.User) respUser { +// referralCache can be passed to avoid querying the db each time this is called. It can be generated with app.getActiveReferrals(). +func (app *appContext) userSummary(jfUser mediabrowser.User, referralCache *map[string]string) respUser { adminOnly := app.config.Section("ui").Key("admin_only").MustBool(true) allowAll := app.config.Section("ui").Key("allow_all").MustBool(false) referralsEnabled := app.config.Section("user_page").Key("referrals").MustBool(false) @@ -944,10 +958,17 @@ func (app *appContext) userSummary(jfUser mediabrowser.User) respUser { } // FIXME: Send referral data referrerInv := Invite{} + // FIXME: This is veeery slow when running an arm64 binary through qemu if referralsEnabled { // 1. Directly attached invite. - err := app.storage.db.FindOne(&referrerInv, badgerhold.Where("ReferrerJellyfinID").Eq(jfUser.ID)) - if err == nil { + found := false + if referralCache != nil { + _, found = (*referralCache)[jfUser.ID] + } else { + err := app.storage.db.FindOne(&referrerInv, badgerhold.Where("IsReferral").Eq(true).And("ReferrerJellyfinID").Eq(jfUser.ID)) + found = err == nil + } + if found { user.ReferralsEnabled = true // 2. Referrals via profile template. Shallow check, doesn't look for the thing in the database. } else if email, ok := app.storage.GetEmailsKey(jfUser.ID); ok && email.ReferralTemplateKey != "" { diff --git a/logmessages/logmessages.go b/logmessages/logmessages.go index 333ab5b..4d537e2 100644 --- a/logmessages/logmessages.go +++ b/logmessages/logmessages.go @@ -328,6 +328,9 @@ const ( // webhooks.go WebhookRequest = "Webhook request send to \"%s\" (%d): %v" + + // usercache.go + CacheRefreshCompleted = "Usercache refreshed, %d in %.2fs (%f.2u/sec)" ) const ( diff --git a/usercache.go b/usercache.go index 35b13e2..8b9cd33 100644 --- a/usercache.go +++ b/usercache.go @@ -8,6 +8,8 @@ import ( "strings" "sync" "time" + + lm "github.com/hrfee/jfa-go/logmessages" ) const ( @@ -85,10 +87,12 @@ func (c *UserCache) MaybeSync(app *appContext) error { status <- err return } + startTime := time.Now() cache := make([]respUser, len(users)) labels := map[string]bool{} + referralCache := app.getActiveReferrals() for i, jfUser := range users { - cache[i] = app.userSummary(jfUser) + cache[i] = app.userSummary(jfUser, &referralCache) if cache[i].Label != "" { labels[cache[i].Label] = true } @@ -101,6 +105,9 @@ func (c *UserCache) MaybeSync(app *appContext) error { for label, _ := range labels { labelSlice = append(labelSlice, label) } + elapsed := time.Since(startTime).Seconds() + usersPerSec := float64(len(users)) / elapsed + app.debug.Printf(lm.CacheRefreshCompleted, len(users), elapsed, usersPerSec) c.Cache = cache c.Ref = ref c.Sorted = false diff --git a/users.go b/users.go index e641ba4..f7b8f13 100644 --- a/users.go +++ b/users.go @@ -141,7 +141,7 @@ func (app *appContext) NewUserPostVerification(p NewUserParams) (out NewUserData webhookURIs := app.config.Section("webhooks").Key("created").StringsWithShadows("|") if len(webhookURIs) != 0 { - summary := app.userSummary(out.User) + summary := app.userSummary(out.User, nil) for _, uri := range webhookURIs { pendingTasks.Add(1) go func() {