[feature] Add instance-stats-randomize config option (#3718)

* [feature] Add `instance-stats-randomize` config option

* don't use cache (overkill)
This commit is contained in:
tobi 2025-01-31 19:27:18 +01:00 committed by GitHub
commit a55bd6d2bd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 183 additions and 10 deletions

View file

@ -18,10 +18,17 @@
package typeutils
import (
crand "crypto/rand"
"math/big"
"math/rand"
"sync"
"sync/atomic"
"time"
apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model"
"github.com/superseriousbusiness/gotosocial/internal/filter/interaction"
"github.com/superseriousbusiness/gotosocial/internal/filter/visibility"
"github.com/superseriousbusiness/gotosocial/internal/log"
"github.com/superseriousbusiness/gotosocial/internal/state"
)
@ -31,6 +38,7 @@ type Converter struct {
randAvatars sync.Map
visFilter *visibility.Filter
intFilter *interaction.Filter
randStats atomic.Pointer[apimodel.RandomStats]
}
func NewConverter(state *state.State) *Converter {
@ -41,3 +49,53 @@ func NewConverter(state *state.State) *Converter {
intFilter: interaction.NewFilter(state),
}
}
// RandomStats returns or generates
// and returns random instance stats.
func (c *Converter) RandomStats() apimodel.RandomStats {
now := time.Now()
stats := c.randStats.Load()
if stats != nil && time.Since(stats.Generated) < time.Hour {
// Random stats are still
// fresh (less than 1hr old),
// so return them as-is.
return *stats
}
// Generate new random stats.
newStats := genRandStats()
newStats.Generated = now
c.randStats.Store(&newStats)
return newStats
}
func genRandStats() apimodel.RandomStats {
const (
statusesMax = 10000000
usersMax = 1000000
)
statusesB, err := crand.Int(crand.Reader, big.NewInt(statusesMax))
if err != nil {
// Only errs if something is buggered with the OS.
log.Panicf(nil, "error randomly generating statuses count: %v", err)
}
totalUsersB, err := crand.Int(crand.Reader, big.NewInt(usersMax))
if err != nil {
// Only errs if something is buggered with the OS.
log.Panicf(nil, "error randomly generating users count: %v", err)
}
// Monthly users should only ever
// be <= 100% of total users.
totalUsers := totalUsersB.Int64()
activeRatio := rand.Float64() //nolint
mau := int64(float64(totalUsers) * activeRatio)
return apimodel.RandomStats{
Statuses: statusesB.Int64(),
TotalUsers: totalUsers,
MonthlyActiveUsers: mau,
}
}

View file

@ -1745,6 +1745,12 @@ func (c *Converter) InstanceToAPIV1Instance(ctx context.Context, i *gtsmodel.Ins
stats["domain_count"] = util.Ptr(domainCount)
instance.Stats = stats
if config.GetInstanceStatsRandomize() {
// Whack some random stats on the instance
// to be injected by API handlers.
instance.RandomStats = c.RandomStats()
}
// thumbnail
iAccount, err := c.state.DB.GetInstanceAccount(ctx, "")
if err != nil {
@ -1821,6 +1827,12 @@ func (c *Converter) InstanceToAPIV2Instance(ctx context.Context, i *gtsmodel.Ins
instance.Debug = util.Ptr(true)
}
if config.GetInstanceStatsRandomize() {
// Whack some random stats on the instance
// to be injected by API handlers.
instance.RandomStats = c.RandomStats()
}
// thumbnail
thumbnail := apimodel.InstanceV2Thumbnail{}