diff --git a/example/config.yaml b/example/config.yaml index 7e02a702d..37ee84c09 100644 --- a/example/config.yaml +++ b/example/config.yaml @@ -164,6 +164,61 @@ db-tls-mode: "disable" # Default: "" db-tls-ca-cert: "" +cache: + gts: + ########################### + #### DATABASE CACHES ###### + ########################### + # + # Database cache configuration: + # + # Allows configuration of caches used + # when loading GTS models from the database. + # + # max-size = maximum cached objects count + # ttl = cached object lifetime + # sweep-freq = frequency to look for stale cache objects + + account-max-size: 100 + account-ttl: "5m" + account-sweep-freq: "10s" + + block-max-size: 100 + block-ttl: "5m" + block-sweep-freq: "10s" + + domain-block-max-size: 1000 + domain-block-ttl: "24h" + domain-block-sweep-freq: "1m" + + emoji-max-size: 500 + emoji-ttl: "5m" + emoji-sweep-freq: "10s" + + emoji-category-max-size: 100 + emoji-category-ttl: "5m" + emoji-category-sweep-freq: "10s" + + mention-max-size: 500 + mention-ttl: "5m" + mention-sweep-freq: "10s" + + notification-max-size: 500 + notification-ttl: "5m" + notification-sweep-freq: "10s" + + status-max-size: 500 + status-ttl: "5m" + status-sweep-freq: "10s" + + tombstone-max-size: 100 + tombstone-ttl: "5m" + tombstone-sweep-freq: "10s" + + user-max-size: 100 + user-ttl: "5m" + user-sweep-freq: "10s" + ###################### ##### WEB CONFIG ##### ###################### diff --git a/internal/cache/gts.go b/internal/cache/gts.go index 9d77f5386..6083b8693 100644 --- a/internal/cache/gts.go +++ b/internal/cache/gts.go @@ -19,9 +19,8 @@ package cache import ( - "time" - "codeberg.org/gruf/go-cache/v3/result" + "github.com/superseriousbusiness/gotosocial/internal/config" "github.com/superseriousbusiness/gotosocial/internal/gtsmodel" ) @@ -100,34 +99,34 @@ func (c *gtsCaches) Init() { func (c *gtsCaches) Start() { tryUntil("starting gtsmodel.Account cache", 5, func() bool { - return c.account.Start(time.Second * 10) + return c.account.Start(config.GetCacheGTSAccountSweepFreq()) }) tryUntil("starting gtsmodel.Block cache", 5, func() bool { - return c.block.Start(time.Second * 10) + return c.block.Start(config.GetCacheGTSBlockSweepFreq()) }) tryUntil("starting gtsmodel.DomainBlock cache", 5, func() bool { - return c.domainBlock.Start(time.Second * 10) + return c.domainBlock.Start(config.GetCacheGTSDomainBlockSweepFreq()) }) tryUntil("starting gtsmodel.Emoji cache", 5, func() bool { - return c.emoji.Start(time.Second * 10) + return c.emoji.Start(config.GetCacheGTSEmojiSweepFreq()) }) tryUntil("starting gtsmodel.EmojiCategory cache", 5, func() bool { - return c.emojiCategory.Start(time.Second * 10) + return c.emojiCategory.Start(config.GetCacheGTSEmojiCategorySweepFreq()) }) tryUntil("starting gtsmodel.Mention cache", 5, func() bool { - return c.mention.Start(time.Second * 10) + return c.mention.Start(config.GetCacheGTSMentionSweepFreq()) }) tryUntil("starting gtsmodel.Notification cache", 5, func() bool { - return c.notification.Start(time.Second * 10) + return c.notification.Start(config.GetCacheGTSNotificationSweepFreq()) }) tryUntil("starting gtsmodel.Status cache", 5, func() bool { - return c.status.Start(time.Second * 10) + return c.status.Start(config.GetCacheGTSStatusSweepFreq()) }) tryUntil("starting gtsmodel.Tombstone cache", 5, func() bool { - return c.tombstone.Start(time.Second * 10) + return c.tombstone.Start(config.GetCacheGTSTombstoneSweepFreq()) }) tryUntil("starting gtsmodel.User cache", 5, func() bool { - return c.user.Start(time.Second * 10) + return c.user.Start(config.GetCacheGTSUserSweepFreq()) }) } @@ -195,8 +194,8 @@ func (c *gtsCaches) initAccount() { a2 := new(gtsmodel.Account) *a2 = *a1 return a2 - }, 1000) - c.account.SetTTL(time.Minute*5, false) + }, config.GetCacheGTSAccountMaxSize()) + c.account.SetTTL(config.GetCacheGTSAccountTTL(), true) } func (c *gtsCaches) initBlock() { @@ -208,8 +207,8 @@ func (c *gtsCaches) initBlock() { b2 := new(gtsmodel.Block) *b2 = *b1 return b2 - }, 1000) - c.block.SetTTL(time.Minute*5, false) + }, config.GetCacheGTSBlockMaxSize()) + c.block.SetTTL(config.GetCacheGTSBlockTTL(), true) } func (c *gtsCaches) initDomainBlock() { @@ -219,8 +218,8 @@ func (c *gtsCaches) initDomainBlock() { d2 := new(gtsmodel.DomainBlock) *d2 = *d1 return d2 - }, 1000) - c.domainBlock.SetTTL(time.Minute*5, false) + }, config.GetCacheGTSDomainBlockMaxSize()) + c.domainBlock.SetTTL(config.GetCacheGTSDomainBlockTTL(), true) } func (c *gtsCaches) initEmoji() { @@ -233,8 +232,8 @@ func (c *gtsCaches) initEmoji() { e2 := new(gtsmodel.Emoji) *e2 = *e1 return e2 - }, 1000) - c.emoji.SetTTL(time.Minute*5, false) + }, config.GetCacheGTSEmojiMaxSize()) + c.emoji.SetTTL(config.GetCacheGTSEmojiTTL(), true) } func (c *gtsCaches) initEmojiCategory() { @@ -245,8 +244,8 @@ func (c *gtsCaches) initEmojiCategory() { c2 := new(gtsmodel.EmojiCategory) *c2 = *c1 return c2 - }, 1000) - c.emojiCategory.SetTTL(time.Minute*5, false) + }, config.GetCacheGTSEmojiCategoryMaxSize()) + c.emojiCategory.SetTTL(config.GetCacheGTSEmojiCategoryTTL(), true) } func (c *gtsCaches) initMention() { @@ -256,8 +255,8 @@ func (c *gtsCaches) initMention() { m2 := new(gtsmodel.Mention) *m2 = *m1 return m2 - }, 1000) - c.mention.SetTTL(time.Minute*5, false) + }, config.GetCacheGTSMentionMaxSize()) + c.mention.SetTTL(config.GetCacheGTSMentionTTL(), true) } func (c *gtsCaches) initNotification() { @@ -267,8 +266,8 @@ func (c *gtsCaches) initNotification() { n2 := new(gtsmodel.Notification) *n2 = *n1 return n2 - }, 1000) - c.notification.SetTTL(time.Minute*5, false) + }, config.GetCacheGTSNotificationMaxSize()) + c.notification.SetTTL(config.GetCacheGTSNotificationTTL(), true) } func (c *gtsCaches) initStatus() { @@ -280,8 +279,8 @@ func (c *gtsCaches) initStatus() { s2 := new(gtsmodel.Status) *s2 = *s1 return s2 - }, 1000) - c.status.SetTTL(time.Minute*5, false) + }, config.GetCacheGTSStatusMaxSize()) + c.status.SetTTL(config.GetCacheGTSStatusTTL(), true) } // initTombstone will initialize the gtsmodel.Tombstone cache. @@ -293,8 +292,8 @@ func (c *gtsCaches) initTombstone() { t2 := new(gtsmodel.Tombstone) *t2 = *t1 return t2 - }, 100) - c.tombstone.SetTTL(time.Minute*5, false) + }, config.GetCacheGTSTombstoneMaxSize()) + c.tombstone.SetTTL(config.GetCacheGTSTombstoneTTL(), true) } func (c *gtsCaches) initUser() { @@ -308,6 +307,6 @@ func (c *gtsCaches) initUser() { u2 := new(gtsmodel.User) *u2 = *u1 return u2 - }, 1000) - c.user.SetTTL(time.Minute*5, false) + }, config.GetCacheGTSUserMaxSize()) + c.user.SetTTL(config.GetCacheGTSUserTTL(), true) } diff --git a/internal/config/config.go b/internal/config/config.go index 047765a75..8a2c041e1 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -20,6 +20,7 @@ package config import ( "reflect" + "time" "codeberg.org/gruf/go-bytesize" "github.com/mitchellh/mapstructure" @@ -129,6 +130,9 @@ type Configuration struct { AdvancedCookiesSamesite string `name:"advanced-cookies-samesite" usage:"'strict' or 'lax', see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite"` AdvancedRateLimitRequests int `name:"advanced-rate-limit-requests" usage:"Amount of HTTP requests to permit within a 5 minute window. 0 or less turns rate limiting off."` + // Cache configuration vars. + Cache CacheConfiguration `name:"cache"` + // TODO: move these elsewhere, these are more ephemeral vs long-running flags like above AdminAccountUsername string `name:"username" usage:"the username to create/delete/etc"` AdminAccountEmail string `name:"email" usage:"the email address of this account"` @@ -137,7 +141,53 @@ type Configuration struct { AdminMediaPruneDryRun bool `name:"dry-run" usage:"perform a dry run and only log number of items eligible for pruning"` } -// MarshalMap will marshal current Configuration into a map structure (useful for JSON). +type CacheConfiguration struct { + GTS GTSCacheConfiguration `name:"gts"` +} + +type GTSCacheConfiguration struct { + AccountMaxSize int `name:"account-max-size"` + AccountTTL time.Duration `name:"account-ttl"` + AccountSweepFreq time.Duration `name:"account-sweep-freq"` + + BlockMaxSize int `name:"block-max-size"` + BlockTTL time.Duration `name:"block-ttl"` + BlockSweepFreq time.Duration `name:"block-sweep-freq"` + + DomainBlockMaxSize int `name:"domain-block-max-size"` + DomainBlockTTL time.Duration `name:"domain-block-ttl"` + DomainBlockSweepFreq time.Duration `name:"domain-block-sweep-freq"` + + EmojiMaxSize int `name:"emoji-max-size"` + EmojiTTL time.Duration `name:"emoji-ttl"` + EmojiSweepFreq time.Duration `name:"emoji-sweep-freq"` + + EmojiCategoryMaxSize int `name:"emoji-category-max-size"` + EmojiCategoryTTL time.Duration `name:"emoji-category-ttl"` + EmojiCategorySweepFreq time.Duration `name:"emoji-category-sweep-freq"` + + MentionMaxSize int `name:"mention-max-size"` + MentionTTL time.Duration `name:"mention-ttl"` + MentionSweepFreq time.Duration `name:"mention-sweep-freq"` + + NotificationMaxSize int `name:"notification-max-size"` + NotificationTTL time.Duration `name:"notification-ttl"` + NotificationSweepFreq time.Duration `name:"notification-sweep-freq"` + + StatusMaxSize int `name:"status-max-size"` + StatusTTL time.Duration `name:"status-ttl"` + StatusSweepFreq time.Duration `name:"status-sweep-freq"` + + TombstoneMaxSize int `name:"tombstone-max-size"` + TombstoneTTL time.Duration `name:"tombstone-ttl"` + TombstoneSweepFreq time.Duration `name:"tombstone-sweep-freq"` + + UserMaxSize int `name:"user-max-size"` + UserTTL time.Duration `name:"user-ttl"` + UserSweepFreq time.Duration `name:"user-sweep-freq"` +} + +// MarshalMap will marshal current Configuration into a map structure (useful for JSON/TOML/YAML). func (cfg *Configuration) MarshalMap() (map[string]interface{}, error) { var dst map[string]interface{} dec, _ := mapstructure.NewDecoder(&mapstructure.DecoderConfig{ diff --git a/internal/config/cliparsing_test.go b/internal/config/config_test.go similarity index 100% rename from internal/config/cliparsing_test.go rename to internal/config/config_test.go diff --git a/internal/config/defaults.go b/internal/config/defaults.go index be537a0df..4fd783611 100644 --- a/internal/config/defaults.go +++ b/internal/config/defaults.go @@ -18,7 +18,12 @@ package config -import "github.com/coreos/go-oidc/v3/oidc" +import ( + "time" + + "codeberg.org/gruf/go-bytesize" + "github.com/coreos/go-oidc/v3/oidc" +) // Defaults contains a populated Configuration with reasonable defaults. Note that // if you use this, you will still need to set Host, and, if desired, ConfigPath. @@ -56,13 +61,13 @@ var Defaults = Configuration{ AccountsReasonRequired: true, AccountsAllowCustomCSS: false, - MediaImageMaxSize: 10485760, // 10mb - MediaVideoMaxSize: 41943040, // 40mb + MediaImageMaxSize: 10 * bytesize.MiB, + MediaVideoMaxSize: 40 * bytesize.MiB, MediaDescriptionMinChars: 0, MediaDescriptionMaxChars: 500, MediaRemoteCacheDays: 30, - MediaEmojiLocalMaxSize: 51200, // 50kb - MediaEmojiRemoteMaxSize: 102400, // 100kb + MediaEmojiLocalMaxSize: 50 * bytesize.KiB, + MediaEmojiRemoteMaxSize: 100 * bytesize.KiB, StorageBackend: "local", StorageLocalBasePath: "/gotosocial/storage", @@ -101,4 +106,48 @@ var Defaults = Configuration{ AdvancedCookiesSamesite: "lax", AdvancedRateLimitRequests: 1000, // per 5 minutes + + Cache: CacheConfiguration{ + GTS: GTSCacheConfiguration{ + AccountMaxSize: 100, + AccountTTL: time.Minute * 5, + AccountSweepFreq: time.Second * 10, + + BlockMaxSize: 100, + BlockTTL: time.Minute * 5, + BlockSweepFreq: time.Second * 10, + + DomainBlockMaxSize: 1000, + DomainBlockTTL: time.Hour * 24, + DomainBlockSweepFreq: time.Minute, + + EmojiMaxSize: 500, + EmojiTTL: time.Minute * 5, + EmojiSweepFreq: time.Second * 10, + + EmojiCategoryMaxSize: 100, + EmojiCategoryTTL: time.Minute * 5, + EmojiCategorySweepFreq: time.Second * 10, + + MentionMaxSize: 500, + MentionTTL: time.Minute * 5, + MentionSweepFreq: time.Second * 10, + + NotificationMaxSize: 500, + NotificationTTL: time.Minute * 5, + NotificationSweepFreq: time.Second * 10, + + StatusMaxSize: 500, + StatusTTL: time.Minute * 5, + StatusSweepFreq: time.Second * 10, + + TombstoneMaxSize: 100, + TombstoneTTL: time.Minute * 5, + TombstoneSweepFreq: time.Second * 10, + + UserMaxSize: 100, + UserTTL: time.Minute * 5, + UserSweepFreq: time.Second * 10, + }, + }, } diff --git a/internal/config/gen/gen.go b/internal/config/gen/gen.go index a0db7e0e0..9065528e6 100644 --- a/internal/config/gen/gen.go +++ b/internal/config/gen/gen.go @@ -21,11 +21,14 @@ package main import ( "flag" "fmt" + "io" "os" "os/exec" "reflect" + "strings" + "time" - "github.com/superseriousbusiness/gotosocial/internal/config" + "codeberg.org/gruf/go-bytesize" ) const license = `/* @@ -47,15 +50,154 @@ const license = `/* */ ` +type Configuration struct { + LogLevel string `name:"log-level" usage:"Log level to run at: [trace, debug, info, warn, fatal]"` + LogDbQueries bool `name:"log-db-queries" usage:"Log database queries verbosely when log-level is trace or debug"` + ApplicationName string `name:"application-name" usage:"Name of the application, used in various places internally"` + LandingPageUser string `name:"landing-page-user" usage:"the user that should be shown on the instance's landing page"` + ConfigPath string `name:"config-path" usage:"Path to a file containing gotosocial configuration. Values set in this file will be overwritten by values set as env vars or arguments"` + Host string `name:"host" usage:"Hostname to use for the server (eg., example.org, gotosocial.whatever.com). DO NOT change this on a server that's already run!"` + AccountDomain string `name:"account-domain" usage:"Domain to use in account names (eg., example.org, whatever.com). If not set, will default to the setting for host. DO NOT change this on a server that's already run!"` + Protocol string `name:"protocol" usage:"Protocol to use for the REST api of the server (only use http if you are debugging or behind a reverse proxy!)"` + BindAddress string `name:"bind-address" usage:"Bind address to use for the GoToSocial server (eg., 0.0.0.0, 172.138.0.9, [::], localhost). For ipv6, enclose the address in square brackets, eg [2001:db8::fed1]. Default binds to all interfaces."` + Port int `name:"port" usage:"Port to use for GoToSocial. Change this to 443 if you're running the binary directly on the host machine."` + TrustedProxies []string `name:"trusted-proxies" usage:"Proxies to trust when parsing x-forwarded headers into real IPs."` + SoftwareVersion string `name:"software-version" usage:""` + + DbType string `name:"db-type" usage:"Database type: eg., postgres"` + DbAddress string `name:"db-address" usage:"Database ipv4 address, hostname, or filename"` + DbPort int `name:"db-port" usage:"Database port"` + DbUser string `name:"db-user" usage:"Database username"` + DbPassword string `name:"db-password" usage:"Database password"` + DbDatabase string `name:"db-database" usage:"Database name"` + DbTLSMode string `name:"db-tls-mode" usage:"Database tls mode"` + DbTLSCACert string `name:"db-tls-ca-cert" usage:"Path to CA cert for db tls connection"` + + WebTemplateBaseDir string `name:"web-template-base-dir" usage:"Basedir for html templating files for rendering pages and composing emails."` + WebAssetBaseDir string `name:"web-asset-base-dir" usage:"Directory to serve static assets from, accessible at example.org/assets/"` + + InstanceExposePeers bool `name:"instance-expose-peers" usage:"Allow unauthenticated users to query /api/v1/instance/peers?filter=open"` + InstanceExposeSuspended bool `name:"instance-expose-suspended" usage:"Expose suspended instances via web UI, and allow unauthenticated users to query /api/v1/instance/peers?filter=suspended"` + InstanceExposePublicTimeline bool `name:"instance-expose-public-timeline" usage:"Allow unauthenticated users to query /api/v1/timelines/public"` + InstanceDeliverToSharedInboxes bool `name:"instance-deliver-to-shared-inboxes" usage:"Deliver federated messages to shared inboxes, if they're available."` + + AccountsRegistrationOpen bool `name:"accounts-registration-open" usage:"Allow anyone to submit an account signup request. If false, server will be invite-only."` + AccountsApprovalRequired bool `name:"accounts-approval-required" usage:"Do account signups require approval by an admin or moderator before user can log in? If false, new registrations will be automatically approved."` + AccountsReasonRequired bool `name:"accounts-reason-required" usage:"Do new account signups require a reason to be submitted on registration?"` + AccountsAllowCustomCSS bool `name:"accounts-allow-custom-css" usage:"Allow accounts to enable custom CSS for their profile pages and statuses."` + + MediaImageMaxSize bytesize.Size `name:"media-image-max-size" usage:"Max size of accepted images in bytes"` + MediaVideoMaxSize bytesize.Size `name:"media-video-max-size" usage:"Max size of accepted videos in bytes"` + MediaDescriptionMinChars int `name:"media-description-min-chars" usage:"Min required chars for an image description"` + MediaDescriptionMaxChars int `name:"media-description-max-chars" usage:"Max permitted chars for an image description"` + MediaRemoteCacheDays int `name:"media-remote-cache-days" usage:"Number of days to locally cache media from remote instances. If set to 0, remote media will be kept indefinitely."` + MediaEmojiLocalMaxSize bytesize.Size `name:"media-emoji-local-max-size" usage:"Max size in bytes of emojis uploaded to this instance via the admin API."` + MediaEmojiRemoteMaxSize bytesize.Size `name:"media-emoji-remote-max-size" usage:"Max size in bytes of emojis to download from other instances."` + + StorageBackend string `name:"storage-backend" usage:"Storage backend to use for media attachments"` + StorageLocalBasePath string `name:"storage-local-base-path" usage:"Full path to an already-created directory where gts should store/retrieve media files. Subfolders will be created within this dir."` + StorageS3Endpoint string `name:"storage-s3-endpoint" usage:"S3 Endpoint URL (e.g 'minio.example.org:9000')"` + StorageS3AccessKey string `name:"storage-s3-access-key" usage:"S3 Access Key"` + StorageS3SecretKey string `name:"storage-s3-secret-key" usage:"S3 Secret Key"` + StorageS3UseSSL bool `name:"storage-s3-use-ssl" usage:"Use SSL for S3 connections. Only set this to 'false' when testing locally"` + StorageS3BucketName string `name:"storage-s3-bucket" usage:"Place blobs in this bucket"` + StorageS3Proxy bool `name:"storage-s3-proxy" usage:"Proxy S3 contents through GoToSocial instead of redirecting to a presigned URL"` + + StatusesMaxChars int `name:"statuses-max-chars" usage:"Max permitted characters for posted statuses"` + StatusesCWMaxChars int `name:"statuses-cw-max-chars" usage:"Max permitted characters for content/spoiler warnings on statuses"` + StatusesPollMaxOptions int `name:"statuses-poll-max-options" usage:"Max amount of options permitted on a poll"` + StatusesPollOptionMaxChars int `name:"statuses-poll-option-max-chars" usage:"Max amount of characters for a poll option"` + StatusesMediaMaxFiles int `name:"statuses-media-max-files" usage:"Maximum number of media files/attachments per status"` + + LetsEncryptEnabled bool `name:"letsencrypt-enabled" usage:"Enable letsencrypt TLS certs for this server. If set to true, then cert dir also needs to be set (or take the default)."` + LetsEncryptPort int `name:"letsencrypt-port" usage:"Port to listen on for letsencrypt certificate challenges. Must not be the same as the GtS webserver/API port."` + LetsEncryptCertDir string `name:"letsencrypt-cert-dir" usage:"Directory to store acquired letsencrypt certificates."` + LetsEncryptEmailAddress string `name:"letsencrypt-email-address" usage:"Email address to use when requesting letsencrypt certs. Will receive updates on cert expiry etc."` + + OIDCEnabled bool `name:"oidc-enabled" usage:"Enabled OIDC authorization for this instance. If set to true, then the other OIDC flags must also be set."` + OIDCIdpName string `name:"oidc-idp-name" usage:"Name of the OIDC identity provider. Will be shown to the user when logging in."` + OIDCSkipVerification bool `name:"oidc-skip-verification" usage:"Skip verification of tokens returned by the OIDC provider. Should only be set to 'true' for testing purposes, never in a production environment!"` + OIDCIssuer string `name:"oidc-issuer" usage:"Address of the OIDC issuer. Should be the web address, including protocol, at which the issuer can be reached. Eg., 'https://example.org/auth'"` + OIDCClientID string `name:"oidc-client-id" usage:"ClientID of GoToSocial, as registered with the OIDC provider."` + OIDCClientSecret string `name:"oidc-client-secret" usage:"ClientSecret of GoToSocial, as registered with the OIDC provider."` + OIDCScopes []string `name:"oidc-scopes" usage:"OIDC scopes."` + OIDCLinkExisting bool `name:"oidc-link-existing" usage:"link existing user accounts to OIDC logins based on the stored email value"` + + SMTPHost string `name:"smtp-host" usage:"Host of the smtp server. Eg., 'smtp.eu.mailgun.org'"` + SMTPPort int `name:"smtp-port" usage:"Port of the smtp server. Eg., 587"` + SMTPUsername string `name:"smtp-username" usage:"Username to authenticate with the smtp server as. Eg., 'postmaster@mail.example.org'"` + SMTPPassword string `name:"smtp-password" usage:"Password to pass to the smtp server."` + SMTPFrom string `name:"smtp-from" usage:"Address to use as the 'from' field of the email. Eg., 'gotosocial@example.org'"` + + SyslogEnabled bool `name:"syslog-enabled" usage:"Enable the syslog logging hook. Logs will be mirrored to the configured destination."` + SyslogProtocol string `name:"syslog-protocol" usage:"Protocol to use when directing logs to syslog. Leave empty to connect to local syslog."` + SyslogAddress string `name:"syslog-address" usage:"Address:port to send syslog logs to. Leave empty to connect to local syslog."` + + AdvancedCookiesSamesite string `name:"advanced-cookies-samesite" usage:"'strict' or 'lax', see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite"` + AdvancedRateLimitRequests int `name:"advanced-rate-limit-requests" usage:"Amount of HTTP requests to permit within a 5 minute window. 0 or less turns rate limiting off."` + + // Cache configuration vars. + Cache CacheConfiguration `name:"cache"` + + // TODO: move these elsewhere, these are more ephemeral vs long-running flags like above + AdminAccountUsername string `name:"username" usage:"the username to create/delete/etc"` + AdminAccountEmail string `name:"email" usage:"the email address of this account"` + AdminAccountPassword string `name:"password" usage:"the password to set for this account"` + AdminTransPath string `name:"path" usage:"the path of the file to import from/export to"` + AdminMediaPruneDryRun bool `name:"dry-run" usage:"perform a dry run and only log number of items eligible for pruning"` +} + +type CacheConfiguration struct { + GTS GTSCacheConfiguration `name:"gts"` +} + +type GTSCacheConfiguration struct { + AccountMaxSize int `name:"account-max-size"` + AccountTTL time.Duration `name:"account-ttl"` + AccountSweepFreq time.Duration `name:"account-sweep-freq"` + + BlockMaxSize int `name:"block-max-size"` + BlockTTL time.Duration `name:"block-ttl"` + BlockSweepFreq time.Duration `name:"block-sweep-freq"` + + DomainBlockMaxSize int `name:"domain-block-max-size"` + DomainBlockTTL time.Duration `name:"domain-block-ttl"` + DomainBlockSweepFreq time.Duration `name:"domain-block-sweep-freq"` + + EmojiMaxSize int `name:"emoji-max-size"` + EmojiTTL time.Duration `name:"emoji-ttl"` + EmojiSweepFreq time.Duration `name:"emoji-sweep-freq"` + + EmojiCategoryMaxSize int `name:"emoji-category-max-size"` + EmojiCategoryTTL time.Duration `name:"emoji-category-ttl"` + EmojiCategorySweepFreq time.Duration `name:"emoji-category-sweep-freq"` + + MentionMaxSize int `name:"mention-max-size"` + MentionTTL time.Duration `name:"mention-ttl"` + MentionSweepFreq time.Duration `name:"mention-sweep-freq"` + + NotificationMaxSize int `name:"notification-max-size"` + NotificationTTL time.Duration `name:"notification-ttl"` + NotificationSweepFreq time.Duration `name:"notification-sweep-freq"` + + StatusMaxSize int `name:"status-max-size"` + StatusTTL time.Duration `name:"status-ttl"` + StatusSweepFreq time.Duration `name:"status-sweep-freq"` + + TombstoneMaxSize int `name:"tombstone-max-size"` + TombstoneTTL time.Duration `name:"tombstone-ttl"` + TombstoneSweepFreq time.Duration `name:"tombstone-sweep-freq"` + + UserMaxSize int `name:"user-max-size"` + UserTTL time.Duration `name:"user-ttl"` + UserSweepFreq time.Duration `name:"user-sweep-freq"` +} + func main() { - var ( - out string - gen string - ) + var out string // Load runtime config flags flag.StringVar(&out, "out", "", "Generated file output path") - flag.StringVar(&gen, "gen", "helpers", "Type of file to generate (helpers)") flag.Parse() // Open output file path @@ -64,50 +206,61 @@ func main() { panic(err) } - switch gen { - // Generate config field helper methods - case "helpers": - fmt.Fprint(output, "// THIS IS A GENERATED FILE, DO NOT EDIT BY HAND\n") - fmt.Fprint(output, license) - fmt.Fprint(output, "package config\n\n") - fmt.Fprint(output, "import \"codeberg.org/gruf/go-bytesize\"\n\n") - t := reflect.TypeOf(config.Configuration{}) - for i := 0; i < t.NumField(); i++ { - field := t.Field(i) + fmt.Fprint(output, "// THIS IS A GENERATED FILE, DO NOT EDIT BY HAND\n") + fmt.Fprint(output, license) + fmt.Fprint(output, "package config\n\n") + fmt.Fprint(output, "import \"codeberg.org/gruf/go-bytesize\"\n\n") + generateFields(output, nil, reflect.TypeOf(Configuration{})) + _ = output.Close() + _ = exec.Command("gofumports", "-w", out).Run() - // ConfigState structure helper methods - fmt.Fprintf(output, "// Get%s safely fetches the Configuration value for state's '%s' field\n", field.Name, field.Name) - fmt.Fprintf(output, "func (st *ConfigState) Get%s() (v %s) {\n", field.Name, field.Type.String()) - fmt.Fprintf(output, "\tst.mutex.Lock()\n") - fmt.Fprintf(output, "\tv = st.config.%s\n", field.Name) - fmt.Fprintf(output, "\tst.mutex.Unlock()\n") - fmt.Fprintf(output, "\treturn\n") - fmt.Fprintf(output, "}\n\n") - fmt.Fprintf(output, "// Set%s safely sets the Configuration value for state's '%s' field\n", field.Name, field.Name) - fmt.Fprintf(output, "func (st *ConfigState) Set%s(v %s) {\n", field.Name, field.Type.String()) - fmt.Fprintf(output, "\tst.mutex.Lock()\n") - fmt.Fprintf(output, "\tdefer st.mutex.Unlock()\n") - fmt.Fprintf(output, "\tst.config.%s = v\n", field.Name) - fmt.Fprintf(output, "\tst.reloadToViper()\n") - fmt.Fprintf(output, "}\n\n") - - // Global ConfigState helper methods - // TODO: remove when we pass around a ConfigState{} - fmt.Fprintf(output, "// %sFlag returns the flag name for the '%s' field\n", field.Name, field.Name) - fmt.Fprintf(output, "func %sFlag() string { return \"%s\" }\n\n", field.Name, field.Tag.Get("name")) - fmt.Fprintf(output, "// Get%s safely fetches the value for global configuration '%s' field\n", field.Name, field.Name) - fmt.Fprintf(output, "func Get%[1]s() %[2]s { return global.Get%[1]s() }\n\n", field.Name, field.Type.String()) - fmt.Fprintf(output, "// Set%s safely sets the value for global configuration '%s' field\n", field.Name, field.Name) - fmt.Fprintf(output, "func Set%[1]s(v %[2]s) { global.Set%[1]s(v) }\n\n", field.Name, field.Type.String()) - } - _ = output.Close() - _ = exec.Command("gofumports", "-w", out).Run() - - // The plain here is that eventually we might be able + // The plan here is that eventually we might be able // to generate an example configuration from struct tags +} - // Unknown type - default: - panic("unknown generation type: " + gen) +func generateFields(output io.Writer, prefixes []string, t reflect.Type) { + for i := 0; i < t.NumField(); i++ { + field := t.Field(i) + + if ft := field.Type; ft.Kind() == reflect.Struct { + // This is a struct field containing further nested config vars. + generateFields(output, append(prefixes, field.Name), ft) + continue + } + + // Get prefixed config variable name + name := strings.Join(prefixes, "") + field.Name + + // Get period-separated (if nested) config variable "path" + fieldPath := strings.Join(append(prefixes, field.Name), ".") + + // Get dash-separated config variable CLI flag "path" + flagPath := strings.Join(append(prefixes, field.Tag.Get("name")), "-") + flagPath = strings.ToLower(flagPath) + + // ConfigState structure helper methods + fmt.Fprintf(output, "// Get%s safely fetches the Configuration value for state's '%s' field\n", name, fieldPath) + fmt.Fprintf(output, "func (st *ConfigState) Get%s() (v %s) {\n", name, field.Type.String()) + fmt.Fprintf(output, "\tst.mutex.Lock()\n") + fmt.Fprintf(output, "\tv = st.config.%s\n", fieldPath) + fmt.Fprintf(output, "\tst.mutex.Unlock()\n") + fmt.Fprintf(output, "\treturn\n") + fmt.Fprintf(output, "}\n\n") + fmt.Fprintf(output, "// Set%s safely sets the Configuration value for state's '%s' field\n", name, fieldPath) + fmt.Fprintf(output, "func (st *ConfigState) Set%s(v %s) {\n", name, field.Type.String()) + fmt.Fprintf(output, "\tst.mutex.Lock()\n") + fmt.Fprintf(output, "\tdefer st.mutex.Unlock()\n") + fmt.Fprintf(output, "\tst.config.%s = v\n", fieldPath) + fmt.Fprintf(output, "\tst.reloadToViper()\n") + fmt.Fprintf(output, "}\n\n") + + // Global ConfigState helper methods + // TODO: remove when we pass around a ConfigState{} + fmt.Fprintf(output, "// %sFlag returns the flag name for the '%s' field\n", name, fieldPath) + fmt.Fprintf(output, "func %sFlag() string { return \"%s\" }\n\n", name, flagPath) + fmt.Fprintf(output, "// Get%s safely fetches the value for global configuration '%s' field\n", name, fieldPath) + fmt.Fprintf(output, "func Get%[1]s() %[2]s { return global.Get%[1]s() }\n\n", name, field.Type.String()) + fmt.Fprintf(output, "// Set%s safely sets the value for global configuration '%s' field\n", name, fieldPath) + fmt.Fprintf(output, "func Set%[1]s(v %[2]s) { global.Set%[1]s(v) }\n\n", name, field.Type.String()) } } diff --git a/internal/config/helpers.gen.go b/internal/config/helpers.gen.go index 4b834998a..62894b4d5 100644 --- a/internal/config/helpers.gen.go +++ b/internal/config/helpers.gen.go @@ -18,7 +18,11 @@ */ package config -import "codeberg.org/gruf/go-bytesize" +import ( + "time" + + "codeberg.org/gruf/go-bytesize" +) // GetLogLevel safely fetches the Configuration value for state's 'LogLevel' field func (st *ConfigState) GetLogLevel() (v string) { @@ -1820,6 +1824,760 @@ func GetAdvancedRateLimitRequests() int { return global.GetAdvancedRateLimitRequ // SetAdvancedRateLimitRequests safely sets the value for global configuration 'AdvancedRateLimitRequests' field func SetAdvancedRateLimitRequests(v int) { global.SetAdvancedRateLimitRequests(v) } +// GetCacheGTSAccountMaxSize safely fetches the Configuration value for state's 'Cache.GTS.AccountMaxSize' field +func (st *ConfigState) GetCacheGTSAccountMaxSize() (v int) { + st.mutex.Lock() + v = st.config.Cache.GTS.AccountMaxSize + st.mutex.Unlock() + return +} + +// SetCacheGTSAccountMaxSize safely sets the Configuration value for state's 'Cache.GTS.AccountMaxSize' field +func (st *ConfigState) SetCacheGTSAccountMaxSize(v int) { + st.mutex.Lock() + defer st.mutex.Unlock() + st.config.Cache.GTS.AccountMaxSize = v + st.reloadToViper() +} + +// CacheGTSAccountMaxSizeFlag returns the flag name for the 'Cache.GTS.AccountMaxSize' field +func CacheGTSAccountMaxSizeFlag() string { return "cache-gts-account-max-size" } + +// GetCacheGTSAccountMaxSize safely fetches the value for global configuration 'Cache.GTS.AccountMaxSize' field +func GetCacheGTSAccountMaxSize() int { return global.GetCacheGTSAccountMaxSize() } + +// SetCacheGTSAccountMaxSize safely sets the value for global configuration 'Cache.GTS.AccountMaxSize' field +func SetCacheGTSAccountMaxSize(v int) { global.SetCacheGTSAccountMaxSize(v) } + +// GetCacheGTSAccountTTL safely fetches the Configuration value for state's 'Cache.GTS.AccountTTL' field +func (st *ConfigState) GetCacheGTSAccountTTL() (v time.Duration) { + st.mutex.Lock() + v = st.config.Cache.GTS.AccountTTL + st.mutex.Unlock() + return +} + +// SetCacheGTSAccountTTL safely sets the Configuration value for state's 'Cache.GTS.AccountTTL' field +func (st *ConfigState) SetCacheGTSAccountTTL(v time.Duration) { + st.mutex.Lock() + defer st.mutex.Unlock() + st.config.Cache.GTS.AccountTTL = v + st.reloadToViper() +} + +// CacheGTSAccountTTLFlag returns the flag name for the 'Cache.GTS.AccountTTL' field +func CacheGTSAccountTTLFlag() string { return "cache-gts-account-ttl" } + +// GetCacheGTSAccountTTL safely fetches the value for global configuration 'Cache.GTS.AccountTTL' field +func GetCacheGTSAccountTTL() time.Duration { return global.GetCacheGTSAccountTTL() } + +// SetCacheGTSAccountTTL safely sets the value for global configuration 'Cache.GTS.AccountTTL' field +func SetCacheGTSAccountTTL(v time.Duration) { global.SetCacheGTSAccountTTL(v) } + +// GetCacheGTSAccountSweepFreq safely fetches the Configuration value for state's 'Cache.GTS.AccountSweepFreq' field +func (st *ConfigState) GetCacheGTSAccountSweepFreq() (v time.Duration) { + st.mutex.Lock() + v = st.config.Cache.GTS.AccountSweepFreq + st.mutex.Unlock() + return +} + +// SetCacheGTSAccountSweepFreq safely sets the Configuration value for state's 'Cache.GTS.AccountSweepFreq' field +func (st *ConfigState) SetCacheGTSAccountSweepFreq(v time.Duration) { + st.mutex.Lock() + defer st.mutex.Unlock() + st.config.Cache.GTS.AccountSweepFreq = v + st.reloadToViper() +} + +// CacheGTSAccountSweepFreqFlag returns the flag name for the 'Cache.GTS.AccountSweepFreq' field +func CacheGTSAccountSweepFreqFlag() string { return "cache-gts-account-sweep-freq" } + +// GetCacheGTSAccountSweepFreq safely fetches the value for global configuration 'Cache.GTS.AccountSweepFreq' field +func GetCacheGTSAccountSweepFreq() time.Duration { return global.GetCacheGTSAccountSweepFreq() } + +// SetCacheGTSAccountSweepFreq safely sets the value for global configuration 'Cache.GTS.AccountSweepFreq' field +func SetCacheGTSAccountSweepFreq(v time.Duration) { global.SetCacheGTSAccountSweepFreq(v) } + +// GetCacheGTSBlockMaxSize safely fetches the Configuration value for state's 'Cache.GTS.BlockMaxSize' field +func (st *ConfigState) GetCacheGTSBlockMaxSize() (v int) { + st.mutex.Lock() + v = st.config.Cache.GTS.BlockMaxSize + st.mutex.Unlock() + return +} + +// SetCacheGTSBlockMaxSize safely sets the Configuration value for state's 'Cache.GTS.BlockMaxSize' field +func (st *ConfigState) SetCacheGTSBlockMaxSize(v int) { + st.mutex.Lock() + defer st.mutex.Unlock() + st.config.Cache.GTS.BlockMaxSize = v + st.reloadToViper() +} + +// CacheGTSBlockMaxSizeFlag returns the flag name for the 'Cache.GTS.BlockMaxSize' field +func CacheGTSBlockMaxSizeFlag() string { return "cache-gts-block-max-size" } + +// GetCacheGTSBlockMaxSize safely fetches the value for global configuration 'Cache.GTS.BlockMaxSize' field +func GetCacheGTSBlockMaxSize() int { return global.GetCacheGTSBlockMaxSize() } + +// SetCacheGTSBlockMaxSize safely sets the value for global configuration 'Cache.GTS.BlockMaxSize' field +func SetCacheGTSBlockMaxSize(v int) { global.SetCacheGTSBlockMaxSize(v) } + +// GetCacheGTSBlockTTL safely fetches the Configuration value for state's 'Cache.GTS.BlockTTL' field +func (st *ConfigState) GetCacheGTSBlockTTL() (v time.Duration) { + st.mutex.Lock() + v = st.config.Cache.GTS.BlockTTL + st.mutex.Unlock() + return +} + +// SetCacheGTSBlockTTL safely sets the Configuration value for state's 'Cache.GTS.BlockTTL' field +func (st *ConfigState) SetCacheGTSBlockTTL(v time.Duration) { + st.mutex.Lock() + defer st.mutex.Unlock() + st.config.Cache.GTS.BlockTTL = v + st.reloadToViper() +} + +// CacheGTSBlockTTLFlag returns the flag name for the 'Cache.GTS.BlockTTL' field +func CacheGTSBlockTTLFlag() string { return "cache-gts-block-ttl" } + +// GetCacheGTSBlockTTL safely fetches the value for global configuration 'Cache.GTS.BlockTTL' field +func GetCacheGTSBlockTTL() time.Duration { return global.GetCacheGTSBlockTTL() } + +// SetCacheGTSBlockTTL safely sets the value for global configuration 'Cache.GTS.BlockTTL' field +func SetCacheGTSBlockTTL(v time.Duration) { global.SetCacheGTSBlockTTL(v) } + +// GetCacheGTSBlockSweepFreq safely fetches the Configuration value for state's 'Cache.GTS.BlockSweepFreq' field +func (st *ConfigState) GetCacheGTSBlockSweepFreq() (v time.Duration) { + st.mutex.Lock() + v = st.config.Cache.GTS.BlockSweepFreq + st.mutex.Unlock() + return +} + +// SetCacheGTSBlockSweepFreq safely sets the Configuration value for state's 'Cache.GTS.BlockSweepFreq' field +func (st *ConfigState) SetCacheGTSBlockSweepFreq(v time.Duration) { + st.mutex.Lock() + defer st.mutex.Unlock() + st.config.Cache.GTS.BlockSweepFreq = v + st.reloadToViper() +} + +// CacheGTSBlockSweepFreqFlag returns the flag name for the 'Cache.GTS.BlockSweepFreq' field +func CacheGTSBlockSweepFreqFlag() string { return "cache-gts-block-sweep-freq" } + +// GetCacheGTSBlockSweepFreq safely fetches the value for global configuration 'Cache.GTS.BlockSweepFreq' field +func GetCacheGTSBlockSweepFreq() time.Duration { return global.GetCacheGTSBlockSweepFreq() } + +// SetCacheGTSBlockSweepFreq safely sets the value for global configuration 'Cache.GTS.BlockSweepFreq' field +func SetCacheGTSBlockSweepFreq(v time.Duration) { global.SetCacheGTSBlockSweepFreq(v) } + +// GetCacheGTSDomainBlockMaxSize safely fetches the Configuration value for state's 'Cache.GTS.DomainBlockMaxSize' field +func (st *ConfigState) GetCacheGTSDomainBlockMaxSize() (v int) { + st.mutex.Lock() + v = st.config.Cache.GTS.DomainBlockMaxSize + st.mutex.Unlock() + return +} + +// SetCacheGTSDomainBlockMaxSize safely sets the Configuration value for state's 'Cache.GTS.DomainBlockMaxSize' field +func (st *ConfigState) SetCacheGTSDomainBlockMaxSize(v int) { + st.mutex.Lock() + defer st.mutex.Unlock() + st.config.Cache.GTS.DomainBlockMaxSize = v + st.reloadToViper() +} + +// CacheGTSDomainBlockMaxSizeFlag returns the flag name for the 'Cache.GTS.DomainBlockMaxSize' field +func CacheGTSDomainBlockMaxSizeFlag() string { return "cache-gts-domain-block-max-size" } + +// GetCacheGTSDomainBlockMaxSize safely fetches the value for global configuration 'Cache.GTS.DomainBlockMaxSize' field +func GetCacheGTSDomainBlockMaxSize() int { return global.GetCacheGTSDomainBlockMaxSize() } + +// SetCacheGTSDomainBlockMaxSize safely sets the value for global configuration 'Cache.GTS.DomainBlockMaxSize' field +func SetCacheGTSDomainBlockMaxSize(v int) { global.SetCacheGTSDomainBlockMaxSize(v) } + +// GetCacheGTSDomainBlockTTL safely fetches the Configuration value for state's 'Cache.GTS.DomainBlockTTL' field +func (st *ConfigState) GetCacheGTSDomainBlockTTL() (v time.Duration) { + st.mutex.Lock() + v = st.config.Cache.GTS.DomainBlockTTL + st.mutex.Unlock() + return +} + +// SetCacheGTSDomainBlockTTL safely sets the Configuration value for state's 'Cache.GTS.DomainBlockTTL' field +func (st *ConfigState) SetCacheGTSDomainBlockTTL(v time.Duration) { + st.mutex.Lock() + defer st.mutex.Unlock() + st.config.Cache.GTS.DomainBlockTTL = v + st.reloadToViper() +} + +// CacheGTSDomainBlockTTLFlag returns the flag name for the 'Cache.GTS.DomainBlockTTL' field +func CacheGTSDomainBlockTTLFlag() string { return "cache-gts-domain-block-ttl" } + +// GetCacheGTSDomainBlockTTL safely fetches the value for global configuration 'Cache.GTS.DomainBlockTTL' field +func GetCacheGTSDomainBlockTTL() time.Duration { return global.GetCacheGTSDomainBlockTTL() } + +// SetCacheGTSDomainBlockTTL safely sets the value for global configuration 'Cache.GTS.DomainBlockTTL' field +func SetCacheGTSDomainBlockTTL(v time.Duration) { global.SetCacheGTSDomainBlockTTL(v) } + +// GetCacheGTSDomainBlockSweepFreq safely fetches the Configuration value for state's 'Cache.GTS.DomainBlockSweepFreq' field +func (st *ConfigState) GetCacheGTSDomainBlockSweepFreq() (v time.Duration) { + st.mutex.Lock() + v = st.config.Cache.GTS.DomainBlockSweepFreq + st.mutex.Unlock() + return +} + +// SetCacheGTSDomainBlockSweepFreq safely sets the Configuration value for state's 'Cache.GTS.DomainBlockSweepFreq' field +func (st *ConfigState) SetCacheGTSDomainBlockSweepFreq(v time.Duration) { + st.mutex.Lock() + defer st.mutex.Unlock() + st.config.Cache.GTS.DomainBlockSweepFreq = v + st.reloadToViper() +} + +// CacheGTSDomainBlockSweepFreqFlag returns the flag name for the 'Cache.GTS.DomainBlockSweepFreq' field +func CacheGTSDomainBlockSweepFreqFlag() string { return "cache-gts-domain-block-sweep-freq" } + +// GetCacheGTSDomainBlockSweepFreq safely fetches the value for global configuration 'Cache.GTS.DomainBlockSweepFreq' field +func GetCacheGTSDomainBlockSweepFreq() time.Duration { return global.GetCacheGTSDomainBlockSweepFreq() } + +// SetCacheGTSDomainBlockSweepFreq safely sets the value for global configuration 'Cache.GTS.DomainBlockSweepFreq' field +func SetCacheGTSDomainBlockSweepFreq(v time.Duration) { global.SetCacheGTSDomainBlockSweepFreq(v) } + +// GetCacheGTSEmojiMaxSize safely fetches the Configuration value for state's 'Cache.GTS.EmojiMaxSize' field +func (st *ConfigState) GetCacheGTSEmojiMaxSize() (v int) { + st.mutex.Lock() + v = st.config.Cache.GTS.EmojiMaxSize + st.mutex.Unlock() + return +} + +// SetCacheGTSEmojiMaxSize safely sets the Configuration value for state's 'Cache.GTS.EmojiMaxSize' field +func (st *ConfigState) SetCacheGTSEmojiMaxSize(v int) { + st.mutex.Lock() + defer st.mutex.Unlock() + st.config.Cache.GTS.EmojiMaxSize = v + st.reloadToViper() +} + +// CacheGTSEmojiMaxSizeFlag returns the flag name for the 'Cache.GTS.EmojiMaxSize' field +func CacheGTSEmojiMaxSizeFlag() string { return "cache-gts-emoji-max-size" } + +// GetCacheGTSEmojiMaxSize safely fetches the value for global configuration 'Cache.GTS.EmojiMaxSize' field +func GetCacheGTSEmojiMaxSize() int { return global.GetCacheGTSEmojiMaxSize() } + +// SetCacheGTSEmojiMaxSize safely sets the value for global configuration 'Cache.GTS.EmojiMaxSize' field +func SetCacheGTSEmojiMaxSize(v int) { global.SetCacheGTSEmojiMaxSize(v) } + +// GetCacheGTSEmojiTTL safely fetches the Configuration value for state's 'Cache.GTS.EmojiTTL' field +func (st *ConfigState) GetCacheGTSEmojiTTL() (v time.Duration) { + st.mutex.Lock() + v = st.config.Cache.GTS.EmojiTTL + st.mutex.Unlock() + return +} + +// SetCacheGTSEmojiTTL safely sets the Configuration value for state's 'Cache.GTS.EmojiTTL' field +func (st *ConfigState) SetCacheGTSEmojiTTL(v time.Duration) { + st.mutex.Lock() + defer st.mutex.Unlock() + st.config.Cache.GTS.EmojiTTL = v + st.reloadToViper() +} + +// CacheGTSEmojiTTLFlag returns the flag name for the 'Cache.GTS.EmojiTTL' field +func CacheGTSEmojiTTLFlag() string { return "cache-gts-emoji-ttl" } + +// GetCacheGTSEmojiTTL safely fetches the value for global configuration 'Cache.GTS.EmojiTTL' field +func GetCacheGTSEmojiTTL() time.Duration { return global.GetCacheGTSEmojiTTL() } + +// SetCacheGTSEmojiTTL safely sets the value for global configuration 'Cache.GTS.EmojiTTL' field +func SetCacheGTSEmojiTTL(v time.Duration) { global.SetCacheGTSEmojiTTL(v) } + +// GetCacheGTSEmojiSweepFreq safely fetches the Configuration value for state's 'Cache.GTS.EmojiSweepFreq' field +func (st *ConfigState) GetCacheGTSEmojiSweepFreq() (v time.Duration) { + st.mutex.Lock() + v = st.config.Cache.GTS.EmojiSweepFreq + st.mutex.Unlock() + return +} + +// SetCacheGTSEmojiSweepFreq safely sets the Configuration value for state's 'Cache.GTS.EmojiSweepFreq' field +func (st *ConfigState) SetCacheGTSEmojiSweepFreq(v time.Duration) { + st.mutex.Lock() + defer st.mutex.Unlock() + st.config.Cache.GTS.EmojiSweepFreq = v + st.reloadToViper() +} + +// CacheGTSEmojiSweepFreqFlag returns the flag name for the 'Cache.GTS.EmojiSweepFreq' field +func CacheGTSEmojiSweepFreqFlag() string { return "cache-gts-emoji-sweep-freq" } + +// GetCacheGTSEmojiSweepFreq safely fetches the value for global configuration 'Cache.GTS.EmojiSweepFreq' field +func GetCacheGTSEmojiSweepFreq() time.Duration { return global.GetCacheGTSEmojiSweepFreq() } + +// SetCacheGTSEmojiSweepFreq safely sets the value for global configuration 'Cache.GTS.EmojiSweepFreq' field +func SetCacheGTSEmojiSweepFreq(v time.Duration) { global.SetCacheGTSEmojiSweepFreq(v) } + +// GetCacheGTSEmojiCategoryMaxSize safely fetches the Configuration value for state's 'Cache.GTS.EmojiCategoryMaxSize' field +func (st *ConfigState) GetCacheGTSEmojiCategoryMaxSize() (v int) { + st.mutex.Lock() + v = st.config.Cache.GTS.EmojiCategoryMaxSize + st.mutex.Unlock() + return +} + +// SetCacheGTSEmojiCategoryMaxSize safely sets the Configuration value for state's 'Cache.GTS.EmojiCategoryMaxSize' field +func (st *ConfigState) SetCacheGTSEmojiCategoryMaxSize(v int) { + st.mutex.Lock() + defer st.mutex.Unlock() + st.config.Cache.GTS.EmojiCategoryMaxSize = v + st.reloadToViper() +} + +// CacheGTSEmojiCategoryMaxSizeFlag returns the flag name for the 'Cache.GTS.EmojiCategoryMaxSize' field +func CacheGTSEmojiCategoryMaxSizeFlag() string { return "cache-gts-emoji-category-max-size" } + +// GetCacheGTSEmojiCategoryMaxSize safely fetches the value for global configuration 'Cache.GTS.EmojiCategoryMaxSize' field +func GetCacheGTSEmojiCategoryMaxSize() int { return global.GetCacheGTSEmojiCategoryMaxSize() } + +// SetCacheGTSEmojiCategoryMaxSize safely sets the value for global configuration 'Cache.GTS.EmojiCategoryMaxSize' field +func SetCacheGTSEmojiCategoryMaxSize(v int) { global.SetCacheGTSEmojiCategoryMaxSize(v) } + +// GetCacheGTSEmojiCategoryTTL safely fetches the Configuration value for state's 'Cache.GTS.EmojiCategoryTTL' field +func (st *ConfigState) GetCacheGTSEmojiCategoryTTL() (v time.Duration) { + st.mutex.Lock() + v = st.config.Cache.GTS.EmojiCategoryTTL + st.mutex.Unlock() + return +} + +// SetCacheGTSEmojiCategoryTTL safely sets the Configuration value for state's 'Cache.GTS.EmojiCategoryTTL' field +func (st *ConfigState) SetCacheGTSEmojiCategoryTTL(v time.Duration) { + st.mutex.Lock() + defer st.mutex.Unlock() + st.config.Cache.GTS.EmojiCategoryTTL = v + st.reloadToViper() +} + +// CacheGTSEmojiCategoryTTLFlag returns the flag name for the 'Cache.GTS.EmojiCategoryTTL' field +func CacheGTSEmojiCategoryTTLFlag() string { return "cache-gts-emoji-category-ttl" } + +// GetCacheGTSEmojiCategoryTTL safely fetches the value for global configuration 'Cache.GTS.EmojiCategoryTTL' field +func GetCacheGTSEmojiCategoryTTL() time.Duration { return global.GetCacheGTSEmojiCategoryTTL() } + +// SetCacheGTSEmojiCategoryTTL safely sets the value for global configuration 'Cache.GTS.EmojiCategoryTTL' field +func SetCacheGTSEmojiCategoryTTL(v time.Duration) { global.SetCacheGTSEmojiCategoryTTL(v) } + +// GetCacheGTSEmojiCategorySweepFreq safely fetches the Configuration value for state's 'Cache.GTS.EmojiCategorySweepFreq' field +func (st *ConfigState) GetCacheGTSEmojiCategorySweepFreq() (v time.Duration) { + st.mutex.Lock() + v = st.config.Cache.GTS.EmojiCategorySweepFreq + st.mutex.Unlock() + return +} + +// SetCacheGTSEmojiCategorySweepFreq safely sets the Configuration value for state's 'Cache.GTS.EmojiCategorySweepFreq' field +func (st *ConfigState) SetCacheGTSEmojiCategorySweepFreq(v time.Duration) { + st.mutex.Lock() + defer st.mutex.Unlock() + st.config.Cache.GTS.EmojiCategorySweepFreq = v + st.reloadToViper() +} + +// CacheGTSEmojiCategorySweepFreqFlag returns the flag name for the 'Cache.GTS.EmojiCategorySweepFreq' field +func CacheGTSEmojiCategorySweepFreqFlag() string { return "cache-gts-emoji-category-sweep-freq" } + +// GetCacheGTSEmojiCategorySweepFreq safely fetches the value for global configuration 'Cache.GTS.EmojiCategorySweepFreq' field +func GetCacheGTSEmojiCategorySweepFreq() time.Duration { + return global.GetCacheGTSEmojiCategorySweepFreq() +} + +// SetCacheGTSEmojiCategorySweepFreq safely sets the value for global configuration 'Cache.GTS.EmojiCategorySweepFreq' field +func SetCacheGTSEmojiCategorySweepFreq(v time.Duration) { global.SetCacheGTSEmojiCategorySweepFreq(v) } + +// GetCacheGTSMentionMaxSize safely fetches the Configuration value for state's 'Cache.GTS.MentionMaxSize' field +func (st *ConfigState) GetCacheGTSMentionMaxSize() (v int) { + st.mutex.Lock() + v = st.config.Cache.GTS.MentionMaxSize + st.mutex.Unlock() + return +} + +// SetCacheGTSMentionMaxSize safely sets the Configuration value for state's 'Cache.GTS.MentionMaxSize' field +func (st *ConfigState) SetCacheGTSMentionMaxSize(v int) { + st.mutex.Lock() + defer st.mutex.Unlock() + st.config.Cache.GTS.MentionMaxSize = v + st.reloadToViper() +} + +// CacheGTSMentionMaxSizeFlag returns the flag name for the 'Cache.GTS.MentionMaxSize' field +func CacheGTSMentionMaxSizeFlag() string { return "cache-gts-mention-max-size" } + +// GetCacheGTSMentionMaxSize safely fetches the value for global configuration 'Cache.GTS.MentionMaxSize' field +func GetCacheGTSMentionMaxSize() int { return global.GetCacheGTSMentionMaxSize() } + +// SetCacheGTSMentionMaxSize safely sets the value for global configuration 'Cache.GTS.MentionMaxSize' field +func SetCacheGTSMentionMaxSize(v int) { global.SetCacheGTSMentionMaxSize(v) } + +// GetCacheGTSMentionTTL safely fetches the Configuration value for state's 'Cache.GTS.MentionTTL' field +func (st *ConfigState) GetCacheGTSMentionTTL() (v time.Duration) { + st.mutex.Lock() + v = st.config.Cache.GTS.MentionTTL + st.mutex.Unlock() + return +} + +// SetCacheGTSMentionTTL safely sets the Configuration value for state's 'Cache.GTS.MentionTTL' field +func (st *ConfigState) SetCacheGTSMentionTTL(v time.Duration) { + st.mutex.Lock() + defer st.mutex.Unlock() + st.config.Cache.GTS.MentionTTL = v + st.reloadToViper() +} + +// CacheGTSMentionTTLFlag returns the flag name for the 'Cache.GTS.MentionTTL' field +func CacheGTSMentionTTLFlag() string { return "cache-gts-mention-ttl" } + +// GetCacheGTSMentionTTL safely fetches the value for global configuration 'Cache.GTS.MentionTTL' field +func GetCacheGTSMentionTTL() time.Duration { return global.GetCacheGTSMentionTTL() } + +// SetCacheGTSMentionTTL safely sets the value for global configuration 'Cache.GTS.MentionTTL' field +func SetCacheGTSMentionTTL(v time.Duration) { global.SetCacheGTSMentionTTL(v) } + +// GetCacheGTSMentionSweepFreq safely fetches the Configuration value for state's 'Cache.GTS.MentionSweepFreq' field +func (st *ConfigState) GetCacheGTSMentionSweepFreq() (v time.Duration) { + st.mutex.Lock() + v = st.config.Cache.GTS.MentionSweepFreq + st.mutex.Unlock() + return +} + +// SetCacheGTSMentionSweepFreq safely sets the Configuration value for state's 'Cache.GTS.MentionSweepFreq' field +func (st *ConfigState) SetCacheGTSMentionSweepFreq(v time.Duration) { + st.mutex.Lock() + defer st.mutex.Unlock() + st.config.Cache.GTS.MentionSweepFreq = v + st.reloadToViper() +} + +// CacheGTSMentionSweepFreqFlag returns the flag name for the 'Cache.GTS.MentionSweepFreq' field +func CacheGTSMentionSweepFreqFlag() string { return "cache-gts-mention-sweep-freq" } + +// GetCacheGTSMentionSweepFreq safely fetches the value for global configuration 'Cache.GTS.MentionSweepFreq' field +func GetCacheGTSMentionSweepFreq() time.Duration { return global.GetCacheGTSMentionSweepFreq() } + +// SetCacheGTSMentionSweepFreq safely sets the value for global configuration 'Cache.GTS.MentionSweepFreq' field +func SetCacheGTSMentionSweepFreq(v time.Duration) { global.SetCacheGTSMentionSweepFreq(v) } + +// GetCacheGTSNotificationMaxSize safely fetches the Configuration value for state's 'Cache.GTS.NotificationMaxSize' field +func (st *ConfigState) GetCacheGTSNotificationMaxSize() (v int) { + st.mutex.Lock() + v = st.config.Cache.GTS.NotificationMaxSize + st.mutex.Unlock() + return +} + +// SetCacheGTSNotificationMaxSize safely sets the Configuration value for state's 'Cache.GTS.NotificationMaxSize' field +func (st *ConfigState) SetCacheGTSNotificationMaxSize(v int) { + st.mutex.Lock() + defer st.mutex.Unlock() + st.config.Cache.GTS.NotificationMaxSize = v + st.reloadToViper() +} + +// CacheGTSNotificationMaxSizeFlag returns the flag name for the 'Cache.GTS.NotificationMaxSize' field +func CacheGTSNotificationMaxSizeFlag() string { return "cache-gts-notification-max-size" } + +// GetCacheGTSNotificationMaxSize safely fetches the value for global configuration 'Cache.GTS.NotificationMaxSize' field +func GetCacheGTSNotificationMaxSize() int { return global.GetCacheGTSNotificationMaxSize() } + +// SetCacheGTSNotificationMaxSize safely sets the value for global configuration 'Cache.GTS.NotificationMaxSize' field +func SetCacheGTSNotificationMaxSize(v int) { global.SetCacheGTSNotificationMaxSize(v) } + +// GetCacheGTSNotificationTTL safely fetches the Configuration value for state's 'Cache.GTS.NotificationTTL' field +func (st *ConfigState) GetCacheGTSNotificationTTL() (v time.Duration) { + st.mutex.Lock() + v = st.config.Cache.GTS.NotificationTTL + st.mutex.Unlock() + return +} + +// SetCacheGTSNotificationTTL safely sets the Configuration value for state's 'Cache.GTS.NotificationTTL' field +func (st *ConfigState) SetCacheGTSNotificationTTL(v time.Duration) { + st.mutex.Lock() + defer st.mutex.Unlock() + st.config.Cache.GTS.NotificationTTL = v + st.reloadToViper() +} + +// CacheGTSNotificationTTLFlag returns the flag name for the 'Cache.GTS.NotificationTTL' field +func CacheGTSNotificationTTLFlag() string { return "cache-gts-notification-ttl" } + +// GetCacheGTSNotificationTTL safely fetches the value for global configuration 'Cache.GTS.NotificationTTL' field +func GetCacheGTSNotificationTTL() time.Duration { return global.GetCacheGTSNotificationTTL() } + +// SetCacheGTSNotificationTTL safely sets the value for global configuration 'Cache.GTS.NotificationTTL' field +func SetCacheGTSNotificationTTL(v time.Duration) { global.SetCacheGTSNotificationTTL(v) } + +// GetCacheGTSNotificationSweepFreq safely fetches the Configuration value for state's 'Cache.GTS.NotificationSweepFreq' field +func (st *ConfigState) GetCacheGTSNotificationSweepFreq() (v time.Duration) { + st.mutex.Lock() + v = st.config.Cache.GTS.NotificationSweepFreq + st.mutex.Unlock() + return +} + +// SetCacheGTSNotificationSweepFreq safely sets the Configuration value for state's 'Cache.GTS.NotificationSweepFreq' field +func (st *ConfigState) SetCacheGTSNotificationSweepFreq(v time.Duration) { + st.mutex.Lock() + defer st.mutex.Unlock() + st.config.Cache.GTS.NotificationSweepFreq = v + st.reloadToViper() +} + +// CacheGTSNotificationSweepFreqFlag returns the flag name for the 'Cache.GTS.NotificationSweepFreq' field +func CacheGTSNotificationSweepFreqFlag() string { return "cache-gts-notification-sweep-freq" } + +// GetCacheGTSNotificationSweepFreq safely fetches the value for global configuration 'Cache.GTS.NotificationSweepFreq' field +func GetCacheGTSNotificationSweepFreq() time.Duration { + return global.GetCacheGTSNotificationSweepFreq() +} + +// SetCacheGTSNotificationSweepFreq safely sets the value for global configuration 'Cache.GTS.NotificationSweepFreq' field +func SetCacheGTSNotificationSweepFreq(v time.Duration) { global.SetCacheGTSNotificationSweepFreq(v) } + +// GetCacheGTSStatusMaxSize safely fetches the Configuration value for state's 'Cache.GTS.StatusMaxSize' field +func (st *ConfigState) GetCacheGTSStatusMaxSize() (v int) { + st.mutex.Lock() + v = st.config.Cache.GTS.StatusMaxSize + st.mutex.Unlock() + return +} + +// SetCacheGTSStatusMaxSize safely sets the Configuration value for state's 'Cache.GTS.StatusMaxSize' field +func (st *ConfigState) SetCacheGTSStatusMaxSize(v int) { + st.mutex.Lock() + defer st.mutex.Unlock() + st.config.Cache.GTS.StatusMaxSize = v + st.reloadToViper() +} + +// CacheGTSStatusMaxSizeFlag returns the flag name for the 'Cache.GTS.StatusMaxSize' field +func CacheGTSStatusMaxSizeFlag() string { return "cache-gts-status-max-size" } + +// GetCacheGTSStatusMaxSize safely fetches the value for global configuration 'Cache.GTS.StatusMaxSize' field +func GetCacheGTSStatusMaxSize() int { return global.GetCacheGTSStatusMaxSize() } + +// SetCacheGTSStatusMaxSize safely sets the value for global configuration 'Cache.GTS.StatusMaxSize' field +func SetCacheGTSStatusMaxSize(v int) { global.SetCacheGTSStatusMaxSize(v) } + +// GetCacheGTSStatusTTL safely fetches the Configuration value for state's 'Cache.GTS.StatusTTL' field +func (st *ConfigState) GetCacheGTSStatusTTL() (v time.Duration) { + st.mutex.Lock() + v = st.config.Cache.GTS.StatusTTL + st.mutex.Unlock() + return +} + +// SetCacheGTSStatusTTL safely sets the Configuration value for state's 'Cache.GTS.StatusTTL' field +func (st *ConfigState) SetCacheGTSStatusTTL(v time.Duration) { + st.mutex.Lock() + defer st.mutex.Unlock() + st.config.Cache.GTS.StatusTTL = v + st.reloadToViper() +} + +// CacheGTSStatusTTLFlag returns the flag name for the 'Cache.GTS.StatusTTL' field +func CacheGTSStatusTTLFlag() string { return "cache-gts-status-ttl" } + +// GetCacheGTSStatusTTL safely fetches the value for global configuration 'Cache.GTS.StatusTTL' field +func GetCacheGTSStatusTTL() time.Duration { return global.GetCacheGTSStatusTTL() } + +// SetCacheGTSStatusTTL safely sets the value for global configuration 'Cache.GTS.StatusTTL' field +func SetCacheGTSStatusTTL(v time.Duration) { global.SetCacheGTSStatusTTL(v) } + +// GetCacheGTSStatusSweepFreq safely fetches the Configuration value for state's 'Cache.GTS.StatusSweepFreq' field +func (st *ConfigState) GetCacheGTSStatusSweepFreq() (v time.Duration) { + st.mutex.Lock() + v = st.config.Cache.GTS.StatusSweepFreq + st.mutex.Unlock() + return +} + +// SetCacheGTSStatusSweepFreq safely sets the Configuration value for state's 'Cache.GTS.StatusSweepFreq' field +func (st *ConfigState) SetCacheGTSStatusSweepFreq(v time.Duration) { + st.mutex.Lock() + defer st.mutex.Unlock() + st.config.Cache.GTS.StatusSweepFreq = v + st.reloadToViper() +} + +// CacheGTSStatusSweepFreqFlag returns the flag name for the 'Cache.GTS.StatusSweepFreq' field +func CacheGTSStatusSweepFreqFlag() string { return "cache-gts-status-sweep-freq" } + +// GetCacheGTSStatusSweepFreq safely fetches the value for global configuration 'Cache.GTS.StatusSweepFreq' field +func GetCacheGTSStatusSweepFreq() time.Duration { return global.GetCacheGTSStatusSweepFreq() } + +// SetCacheGTSStatusSweepFreq safely sets the value for global configuration 'Cache.GTS.StatusSweepFreq' field +func SetCacheGTSStatusSweepFreq(v time.Duration) { global.SetCacheGTSStatusSweepFreq(v) } + +// GetCacheGTSTombstoneMaxSize safely fetches the Configuration value for state's 'Cache.GTS.TombstoneMaxSize' field +func (st *ConfigState) GetCacheGTSTombstoneMaxSize() (v int) { + st.mutex.Lock() + v = st.config.Cache.GTS.TombstoneMaxSize + st.mutex.Unlock() + return +} + +// SetCacheGTSTombstoneMaxSize safely sets the Configuration value for state's 'Cache.GTS.TombstoneMaxSize' field +func (st *ConfigState) SetCacheGTSTombstoneMaxSize(v int) { + st.mutex.Lock() + defer st.mutex.Unlock() + st.config.Cache.GTS.TombstoneMaxSize = v + st.reloadToViper() +} + +// CacheGTSTombstoneMaxSizeFlag returns the flag name for the 'Cache.GTS.TombstoneMaxSize' field +func CacheGTSTombstoneMaxSizeFlag() string { return "cache-gts-tombstone-max-size" } + +// GetCacheGTSTombstoneMaxSize safely fetches the value for global configuration 'Cache.GTS.TombstoneMaxSize' field +func GetCacheGTSTombstoneMaxSize() int { return global.GetCacheGTSTombstoneMaxSize() } + +// SetCacheGTSTombstoneMaxSize safely sets the value for global configuration 'Cache.GTS.TombstoneMaxSize' field +func SetCacheGTSTombstoneMaxSize(v int) { global.SetCacheGTSTombstoneMaxSize(v) } + +// GetCacheGTSTombstoneTTL safely fetches the Configuration value for state's 'Cache.GTS.TombstoneTTL' field +func (st *ConfigState) GetCacheGTSTombstoneTTL() (v time.Duration) { + st.mutex.Lock() + v = st.config.Cache.GTS.TombstoneTTL + st.mutex.Unlock() + return +} + +// SetCacheGTSTombstoneTTL safely sets the Configuration value for state's 'Cache.GTS.TombstoneTTL' field +func (st *ConfigState) SetCacheGTSTombstoneTTL(v time.Duration) { + st.mutex.Lock() + defer st.mutex.Unlock() + st.config.Cache.GTS.TombstoneTTL = v + st.reloadToViper() +} + +// CacheGTSTombstoneTTLFlag returns the flag name for the 'Cache.GTS.TombstoneTTL' field +func CacheGTSTombstoneTTLFlag() string { return "cache-gts-tombstone-ttl" } + +// GetCacheGTSTombstoneTTL safely fetches the value for global configuration 'Cache.GTS.TombstoneTTL' field +func GetCacheGTSTombstoneTTL() time.Duration { return global.GetCacheGTSTombstoneTTL() } + +// SetCacheGTSTombstoneTTL safely sets the value for global configuration 'Cache.GTS.TombstoneTTL' field +func SetCacheGTSTombstoneTTL(v time.Duration) { global.SetCacheGTSTombstoneTTL(v) } + +// GetCacheGTSTombstoneSweepFreq safely fetches the Configuration value for state's 'Cache.GTS.TombstoneSweepFreq' field +func (st *ConfigState) GetCacheGTSTombstoneSweepFreq() (v time.Duration) { + st.mutex.Lock() + v = st.config.Cache.GTS.TombstoneSweepFreq + st.mutex.Unlock() + return +} + +// SetCacheGTSTombstoneSweepFreq safely sets the Configuration value for state's 'Cache.GTS.TombstoneSweepFreq' field +func (st *ConfigState) SetCacheGTSTombstoneSweepFreq(v time.Duration) { + st.mutex.Lock() + defer st.mutex.Unlock() + st.config.Cache.GTS.TombstoneSweepFreq = v + st.reloadToViper() +} + +// CacheGTSTombstoneSweepFreqFlag returns the flag name for the 'Cache.GTS.TombstoneSweepFreq' field +func CacheGTSTombstoneSweepFreqFlag() string { return "cache-gts-tombstone-sweep-freq" } + +// GetCacheGTSTombstoneSweepFreq safely fetches the value for global configuration 'Cache.GTS.TombstoneSweepFreq' field +func GetCacheGTSTombstoneSweepFreq() time.Duration { return global.GetCacheGTSTombstoneSweepFreq() } + +// SetCacheGTSTombstoneSweepFreq safely sets the value for global configuration 'Cache.GTS.TombstoneSweepFreq' field +func SetCacheGTSTombstoneSweepFreq(v time.Duration) { global.SetCacheGTSTombstoneSweepFreq(v) } + +// GetCacheGTSUserMaxSize safely fetches the Configuration value for state's 'Cache.GTS.UserMaxSize' field +func (st *ConfigState) GetCacheGTSUserMaxSize() (v int) { + st.mutex.Lock() + v = st.config.Cache.GTS.UserMaxSize + st.mutex.Unlock() + return +} + +// SetCacheGTSUserMaxSize safely sets the Configuration value for state's 'Cache.GTS.UserMaxSize' field +func (st *ConfigState) SetCacheGTSUserMaxSize(v int) { + st.mutex.Lock() + defer st.mutex.Unlock() + st.config.Cache.GTS.UserMaxSize = v + st.reloadToViper() +} + +// CacheGTSUserMaxSizeFlag returns the flag name for the 'Cache.GTS.UserMaxSize' field +func CacheGTSUserMaxSizeFlag() string { return "cache-gts-user-max-size" } + +// GetCacheGTSUserMaxSize safely fetches the value for global configuration 'Cache.GTS.UserMaxSize' field +func GetCacheGTSUserMaxSize() int { return global.GetCacheGTSUserMaxSize() } + +// SetCacheGTSUserMaxSize safely sets the value for global configuration 'Cache.GTS.UserMaxSize' field +func SetCacheGTSUserMaxSize(v int) { global.SetCacheGTSUserMaxSize(v) } + +// GetCacheGTSUserTTL safely fetches the Configuration value for state's 'Cache.GTS.UserTTL' field +func (st *ConfigState) GetCacheGTSUserTTL() (v time.Duration) { + st.mutex.Lock() + v = st.config.Cache.GTS.UserTTL + st.mutex.Unlock() + return +} + +// SetCacheGTSUserTTL safely sets the Configuration value for state's 'Cache.GTS.UserTTL' field +func (st *ConfigState) SetCacheGTSUserTTL(v time.Duration) { + st.mutex.Lock() + defer st.mutex.Unlock() + st.config.Cache.GTS.UserTTL = v + st.reloadToViper() +} + +// CacheGTSUserTTLFlag returns the flag name for the 'Cache.GTS.UserTTL' field +func CacheGTSUserTTLFlag() string { return "cache-gts-user-ttl" } + +// GetCacheGTSUserTTL safely fetches the value for global configuration 'Cache.GTS.UserTTL' field +func GetCacheGTSUserTTL() time.Duration { return global.GetCacheGTSUserTTL() } + +// SetCacheGTSUserTTL safely sets the value for global configuration 'Cache.GTS.UserTTL' field +func SetCacheGTSUserTTL(v time.Duration) { global.SetCacheGTSUserTTL(v) } + +// GetCacheGTSUserSweepFreq safely fetches the Configuration value for state's 'Cache.GTS.UserSweepFreq' field +func (st *ConfigState) GetCacheGTSUserSweepFreq() (v time.Duration) { + st.mutex.Lock() + v = st.config.Cache.GTS.UserSweepFreq + st.mutex.Unlock() + return +} + +// SetCacheGTSUserSweepFreq safely sets the Configuration value for state's 'Cache.GTS.UserSweepFreq' field +func (st *ConfigState) SetCacheGTSUserSweepFreq(v time.Duration) { + st.mutex.Lock() + defer st.mutex.Unlock() + st.config.Cache.GTS.UserSweepFreq = v + st.reloadToViper() +} + +// CacheGTSUserSweepFreqFlag returns the flag name for the 'Cache.GTS.UserSweepFreq' field +func CacheGTSUserSweepFreqFlag() string { return "cache-gts-user-sweep-freq" } + +// GetCacheGTSUserSweepFreq safely fetches the value for global configuration 'Cache.GTS.UserSweepFreq' field +func GetCacheGTSUserSweepFreq() time.Duration { return global.GetCacheGTSUserSweepFreq() } + +// SetCacheGTSUserSweepFreq safely sets the value for global configuration 'Cache.GTS.UserSweepFreq' field +func SetCacheGTSUserSweepFreq(v time.Duration) { global.SetCacheGTSUserSweepFreq(v) } + // GetAdminAccountUsername safely fetches the Configuration value for state's 'AdminAccountUsername' field func (st *ConfigState) GetAdminAccountUsername() (v string) { st.mutex.Lock() @@ -1944,4 +2702,3 @@ func GetAdminMediaPruneDryRun() bool { return global.GetAdminMediaPruneDryRun() // SetAdminMediaPruneDryRun safely sets the value for global configuration 'AdminMediaPruneDryRun' field func SetAdminMediaPruneDryRun(v bool) { global.SetAdminMediaPruneDryRun(v) } - diff --git a/internal/config/state.go b/internal/config/state.go index 17fd31e2a..64d87d771 100644 --- a/internal/config/state.go +++ b/internal/config/state.go @@ -41,8 +41,8 @@ func NewState() *ConfigState { viper := viper.New() // Flag 'some-flag-name' becomes env var 'GTS_SOME_FLAG_NAME' - viper.SetEnvPrefix("gts") viper.SetEnvKeyReplacer(strings.NewReplacer("-", "_")) + viper.SetEnvPrefix("gts") // Load appropriate named vals from env viper.AutomaticEnv() @@ -132,9 +132,13 @@ func (st *ConfigState) reloadToViper() { func (st *ConfigState) reloadFromViper() { if err := st.viper.Unmarshal(&st.config, func(c *mapstructure.DecoderConfig) { c.TagName = "name" - c.ZeroFields = true // empty the config struct before we marshal values into it + + // empty config before marshaling + c.ZeroFields = true oldhook := c.DecodeHook + + // Use the TextUnmarshaler interface when decoding. c.DecodeHook = mapstructure.ComposeDecodeHookFunc( mapstructure.TextUnmarshallerHookFunc(), oldhook, diff --git a/internal/config/testdata/test.yaml b/internal/config/testdata/test.yaml index 9a57b589d..3b2b63fe2 100644 --- a/internal/config/testdata/test.yaml +++ b/internal/config/testdata/test.yaml @@ -409,3 +409,10 @@ syslog-protocol: "udp" # String. Address:port to send syslog logs to. Leave empty to connect to local syslog. # Default: "localhost:514" syslog-address: "localhost:514" + +# Cache configuration +cache: + gts: + account-max-size: 99 + account-ttl: "3h" + account-sweep-freq: "1s" \ No newline at end of file diff --git a/test/envparsing.sh b/test/envparsing.sh index 15b910922..2fc9c055a 100755 --- a/test/envparsing.sh +++ b/test/envparsing.sh @@ -2,7 +2,7 @@ set -eu -EXPECT='{"account-domain":"peepee","accounts-allow-custom-css":true,"accounts-approval-required":false,"accounts-reason-required":false,"accounts-registration-open":true,"advanced-cookies-samesite":"strict","advanced-rate-limit-requests":6969,"application-name":"gts","bind-address":"127.0.0.1","config-path":"internal/config/testdata/test.yaml","db-address":":memory:","db-database":"gotosocial_prod","db-password":"hunter2","db-port":6969,"db-tls-ca-cert":"","db-tls-mode":"disable","db-type":"sqlite","db-user":"sex-haver","dry-run":false,"email":"","host":"example.com","instance-deliver-to-shared-inboxes":false,"instance-expose-peers":true,"instance-expose-public-timeline":true,"instance-expose-suspended":true,"landing-page-user":"admin","letsencrypt-cert-dir":"/gotosocial/storage/certs","letsencrypt-email-address":"","letsencrypt-enabled":true,"letsencrypt-port":80,"log-db-queries":true,"log-level":"info","media-description-max-chars":5000,"media-description-min-chars":69,"media-emoji-local-max-size":420,"media-emoji-remote-max-size":420,"media-image-max-size":420,"media-remote-cache-days":30,"media-video-max-size":420,"oidc-client-id":"1234","oidc-client-secret":"shhhh its a secret","oidc-enabled":true,"oidc-idp-name":"sex-haver","oidc-issuer":"whoknows","oidc-link-existing":true,"oidc-scopes":["read","write"],"oidc-skip-verification":true,"password":"","path":"","port":6969,"protocol":"http","smtp-from":"queen.rip.in.piss@terfisland.org","smtp-host":"example.com","smtp-password":"hunter2","smtp-port":4269,"smtp-username":"sex-haver","software-version":"","statuses-cw-max-chars":420,"statuses-max-chars":69,"statuses-media-max-files":1,"statuses-poll-max-options":1,"statuses-poll-option-max-chars":50,"storage-backend":"local","storage-local-base-path":"/root/store","storage-s3-access-key":"minio","storage-s3-bucket":"gts","storage-s3-endpoint":"localhost:9000","storage-s3-proxy":true,"storage-s3-secret-key":"miniostorage","storage-s3-use-ssl":false,"syslog-address":"127.0.0.1:6969","syslog-enabled":true,"syslog-protocol":"udp","trusted-proxies":["127.0.0.1/32","docker.host.local"],"username":"","web-asset-base-dir":"/root","web-template-base-dir":"/root"}' +EXPECT='{"account-domain":"peepee","accounts-allow-custom-css":true,"accounts-approval-required":false,"accounts-reason-required":false,"accounts-registration-open":true,"advanced-cookies-samesite":"strict","advanced-rate-limit-requests":6969,"application-name":"gts","bind-address":"127.0.0.1","cache":{"gts":{"account-max-size":99,"account-sweep-freq":1000000000,"account-ttl":10800000000000,"block-max-size":100,"block-sweep-freq":10000000000,"block-ttl":300000000000,"domain-block-max-size":1000,"domain-block-sweep-freq":60000000000,"domain-block-ttl":86400000000000,"emoji-category-max-size":100,"emoji-category-sweep-freq":10000000000,"emoji-category-ttl":300000000000,"emoji-max-size":500,"emoji-sweep-freq":10000000000,"emoji-ttl":300000000000,"mention-max-size":500,"mention-sweep-freq":10000000000,"mention-ttl":300000000000,"notification-max-size":500,"notification-sweep-freq":10000000000,"notification-ttl":300000000000,"status-max-size":500,"status-sweep-freq":10000000000,"status-ttl":300000000000,"tombstone-max-size":100,"tombstone-sweep-freq":10000000000,"tombstone-ttl":300000000000,"user-max-size":100,"user-sweep-freq":10000000000,"user-ttl":300000000000}},"config-path":"internal/config/testdata/test.yaml","db-address":":memory:","db-database":"gotosocial_prod","db-password":"hunter2","db-port":6969,"db-tls-ca-cert":"","db-tls-mode":"disable","db-type":"sqlite","db-user":"sex-haver","dry-run":false,"email":"","host":"example.com","instance-deliver-to-shared-inboxes":false,"instance-expose-peers":true,"instance-expose-public-timeline":true,"instance-expose-suspended":true,"landing-page-user":"admin","letsencrypt-cert-dir":"/gotosocial/storage/certs","letsencrypt-email-address":"","letsencrypt-enabled":true,"letsencrypt-port":80,"log-db-queries":true,"log-level":"info","media-description-max-chars":5000,"media-description-min-chars":69,"media-emoji-local-max-size":420,"media-emoji-remote-max-size":420,"media-image-max-size":420,"media-remote-cache-days":30,"media-video-max-size":420,"oidc-client-id":"1234","oidc-client-secret":"shhhh its a secret","oidc-enabled":true,"oidc-idp-name":"sex-haver","oidc-issuer":"whoknows","oidc-link-existing":true,"oidc-scopes":["read","write"],"oidc-skip-verification":true,"password":"","path":"","port":6969,"protocol":"http","smtp-from":"queen.rip.in.piss@terfisland.org","smtp-host":"example.com","smtp-password":"hunter2","smtp-port":4269,"smtp-username":"sex-haver","software-version":"","statuses-cw-max-chars":420,"statuses-max-chars":69,"statuses-media-max-files":1,"statuses-poll-max-options":1,"statuses-poll-option-max-chars":50,"storage-backend":"local","storage-local-base-path":"/root/store","storage-s3-access-key":"minio","storage-s3-bucket":"gts","storage-s3-endpoint":"localhost:9000","storage-s3-proxy":true,"storage-s3-secret-key":"miniostorage","storage-s3-use-ssl":false,"syslog-address":"127.0.0.1:6969","syslog-enabled":true,"syslog-protocol":"udp","trusted-proxies":["127.0.0.1/32","docker.host.local"],"username":"","web-asset-base-dir":"/root","web-template-base-dir":"/root"}' # Set all the environment variables to # ensure that these are parsed without panic diff --git a/testrig/config.go b/testrig/config.go index a8526097d..a1d7e5d54 100644 --- a/testrig/config.go +++ b/testrig/config.go @@ -110,4 +110,7 @@ var testDefaults = config.Configuration{ AdvancedRateLimitRequests: 0, // disabled SoftwareVersion: "0.0.0-testrig", + + // simply use cache defaults. + Cache: config.Defaults.Cache, }