2022-07-18 10:55:06 +00:00
/ *
GoToSocial
Copyright ( C ) 2021 - 2022 GoToSocial Authors admin @ gotosocial . org
This program is free software : you can redistribute it and / or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation , either version 3 of the License , or
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU Affero General Public License for more details .
You should have received a copy of the GNU Affero General Public License
along with this program . If not , see < http : //www.gnu.org/licenses/>.
* /
2021-09-01 09:08:21 +00:00
package cache
import (
2022-07-10 15:18:21 +00:00
"time"
2021-09-01 09:08:21 +00:00
2022-07-10 15:18:21 +00:00
"codeberg.org/gruf/go-cache/v2"
2021-09-01 09:08:21 +00:00
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
)
2022-07-10 15:18:21 +00:00
// AccountCache is a cache wrapper to provide URL and URI lookups for gtsmodel.Account
2021-09-01 09:08:21 +00:00
type AccountCache struct {
2022-07-10 15:18:21 +00:00
cache cache . LookupCache [ string , string , * gtsmodel . Account ]
2021-09-01 09:08:21 +00:00
}
// NewAccountCache returns a new instantiated AccountCache object
func NewAccountCache ( ) * AccountCache {
2022-07-10 15:18:21 +00:00
c := & AccountCache { }
c . cache = cache . NewLookup ( cache . LookupCfg [ string , string , * gtsmodel . Account ] {
RegisterLookups : func ( lm * cache . LookupMap [ string , string ] ) {
lm . RegisterLookup ( "uri" )
lm . RegisterLookup ( "url" )
2022-09-02 09:58:42 +00:00
lm . RegisterLookup ( "pubkeyid" )
2022-08-20 20:47:19 +00:00
lm . RegisterLookup ( "usernamedomain" )
2022-07-10 15:18:21 +00:00
} ,
AddLookups : func ( lm * cache . LookupMap [ string , string ] , acc * gtsmodel . Account ) {
if uri := acc . URI ; uri != "" {
lm . Set ( "uri" , uri , acc . ID )
}
if url := acc . URL ; url != "" {
lm . Set ( "url" , url , acc . ID )
}
2022-09-02 09:58:42 +00:00
lm . Set ( "pubkeyid" , acc . PublicKeyURI , acc . ID )
2022-08-20 20:47:19 +00:00
lm . Set ( "usernamedomain" , usernameDomainKey ( acc . Username , acc . Domain ) , acc . ID )
2022-07-10 15:18:21 +00:00
} ,
DeleteLookups : func ( lm * cache . LookupMap [ string , string ] , acc * gtsmodel . Account ) {
if uri := acc . URI ; uri != "" {
lm . Delete ( "uri" , uri )
}
if url := acc . URL ; url != "" {
lm . Delete ( "url" , url )
}
2022-09-02 09:58:42 +00:00
lm . Delete ( "pubkeyid" , acc . PublicKeyURI )
2022-08-20 20:47:19 +00:00
lm . Delete ( "usernamedomain" , usernameDomainKey ( acc . Username , acc . Domain ) )
2022-07-10 15:18:21 +00:00
} ,
2021-09-01 09:08:21 +00:00
} )
2022-07-10 15:18:21 +00:00
c . cache . SetTTL ( time . Minute * 5 , false )
c . cache . Start ( time . Second * 10 )
return c
2021-09-01 09:08:21 +00:00
}
// GetByID attempts to fetch a account from the cache by its ID, you will receive a copy for thread-safety
func ( c * AccountCache ) GetByID ( id string ) ( * gtsmodel . Account , bool ) {
2022-07-10 15:18:21 +00:00
return c . cache . Get ( id )
2021-09-01 09:08:21 +00:00
}
// GetByURL attempts to fetch a account from the cache by its URL, you will receive a copy for thread-safety
func ( c * AccountCache ) GetByURL ( url string ) ( * gtsmodel . Account , bool ) {
2022-07-10 15:18:21 +00:00
return c . cache . GetBy ( "url" , url )
2021-09-01 09:08:21 +00:00
}
// GetByURI attempts to fetch a account from the cache by its URI, you will receive a copy for thread-safety
func ( c * AccountCache ) GetByURI ( uri string ) ( * gtsmodel . Account , bool ) {
2022-07-10 15:18:21 +00:00
return c . cache . GetBy ( "uri" , uri )
2021-09-01 09:08:21 +00:00
}
2022-09-02 09:58:42 +00:00
// GettByUsernameDomain attempts to fetch an account from the cache by its username@domain combo (or just username), you will receive a copy for thread-safety.
2022-08-20 20:47:19 +00:00
func ( c * AccountCache ) GetByUsernameDomain ( username string , domain string ) ( * gtsmodel . Account , bool ) {
return c . cache . GetBy ( "usernamedomain" , usernameDomainKey ( username , domain ) )
}
2022-09-02 09:58:42 +00:00
// GetByPubkeyID attempts to fetch an account from the cache by its public key URI (ID), you will receive a copy for thread-safety.
func ( c * AccountCache ) GetByPubkeyID ( id string ) ( * gtsmodel . Account , bool ) {
return c . cache . GetBy ( "pubkeyid" , id )
}
2021-09-01 09:08:21 +00:00
// Put places a account in the cache, ensuring that the object place is a copy for thread-safety
func ( c * AccountCache ) Put ( account * gtsmodel . Account ) {
if account == nil || account . ID == "" {
panic ( "invalid account" )
}
c . cache . Set ( account . ID , copyAccount ( account ) )
}
// copyAccount performs a surface-level copy of account, only keeping attached IDs intact, not the objects.
// due to all the data being copied being 99% primitive types or strings (which are immutable and passed by ptr)
// this should be a relatively cheap process
func copyAccount ( account * gtsmodel . Account ) * gtsmodel . Account {
return & gtsmodel . Account {
ID : account . ID ,
Username : account . Username ,
Domain : account . Domain ,
AvatarMediaAttachmentID : account . AvatarMediaAttachmentID ,
AvatarMediaAttachment : nil ,
AvatarRemoteURL : account . AvatarRemoteURL ,
HeaderMediaAttachmentID : account . HeaderMediaAttachmentID ,
HeaderMediaAttachment : nil ,
HeaderRemoteURL : account . HeaderRemoteURL ,
DisplayName : account . DisplayName ,
Fields : account . Fields ,
Note : account . Note ,
2022-05-07 15:55:27 +00:00
NoteRaw : account . NoteRaw ,
2022-08-15 10:35:05 +00:00
Memorial : copyBoolPtr ( account . Memorial ) ,
2021-09-01 09:08:21 +00:00
MovedToAccountID : account . MovedToAccountID ,
2022-08-15 10:35:05 +00:00
Bot : copyBoolPtr ( account . Bot ) ,
2021-09-01 09:08:21 +00:00
CreatedAt : account . CreatedAt ,
UpdatedAt : account . UpdatedAt ,
Reason : account . Reason ,
2022-08-15 10:35:05 +00:00
Locked : copyBoolPtr ( account . Locked ) ,
Discoverable : copyBoolPtr ( account . Discoverable ) ,
2021-09-01 09:08:21 +00:00
Privacy : account . Privacy ,
2022-08-15 10:35:05 +00:00
Sensitive : copyBoolPtr ( account . Sensitive ) ,
2021-09-01 09:08:21 +00:00
Language : account . Language ,
2022-08-06 10:09:21 +00:00
StatusFormat : account . StatusFormat ,
2022-09-12 11:14:29 +00:00
CustomCSS : account . CustomCSS ,
2021-09-01 09:08:21 +00:00
URI : account . URI ,
URL : account . URL ,
LastWebfingeredAt : account . LastWebfingeredAt ,
InboxURI : account . InboxURI ,
OutboxURI : account . OutboxURI ,
FollowingURI : account . FollowingURI ,
FollowersURI : account . FollowersURI ,
FeaturedCollectionURI : account . FeaturedCollectionURI ,
ActorType : account . ActorType ,
AlsoKnownAs : account . AlsoKnownAs ,
PrivateKey : account . PrivateKey ,
PublicKey : account . PublicKey ,
PublicKeyURI : account . PublicKeyURI ,
SensitizedAt : account . SensitizedAt ,
SilencedAt : account . SilencedAt ,
SuspendedAt : account . SuspendedAt ,
2022-08-15 10:35:05 +00:00
HideCollections : copyBoolPtr ( account . HideCollections ) ,
2021-09-01 09:08:21 +00:00
SuspensionOrigin : account . SuspensionOrigin ,
}
}
2022-08-20 20:47:19 +00:00
func usernameDomainKey ( username string , domain string ) string {
u := "@" + username
if domain != "" {
return u + "@" + domain
}
return u
}