| 
									
										
										
										
											2022-07-18 12:55:06 +02: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-08-29 15:41:41 +01:00
										 |  |  | package cache | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							| 
									
										
										
										
											2022-07-10 16:18:21 +01:00
										 |  |  | 	"time" | 
					
						
							| 
									
										
										
										
											2021-08-29 15:41:41 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-10 16:18:21 +01:00
										 |  |  | 	"codeberg.org/gruf/go-cache/v2" | 
					
						
							| 
									
										
										
										
											2021-08-29 15:41:41 +01:00
										 |  |  | 	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-10 16:18:21 +01:00
										 |  |  | // StatusCache is a cache wrapper to provide URL and URI lookups for gtsmodel.Status | 
					
						
							| 
									
										
										
										
											2021-08-29 15:41:41 +01:00
										 |  |  | type StatusCache struct { | 
					
						
							| 
									
										
										
										
											2022-07-10 16:18:21 +01:00
										 |  |  | 	cache cache.LookupCache[string, string, *gtsmodel.Status] | 
					
						
							| 
									
										
										
										
											2021-08-29 15:41:41 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-30 11:16:23 +02:00
										 |  |  | // NewStatusCache returns a new instantiated statusCache object | 
					
						
							| 
									
										
										
										
											2021-08-29 15:41:41 +01:00
										 |  |  | func NewStatusCache() *StatusCache { | 
					
						
							| 
									
										
										
										
											2022-07-10 16:18:21 +01:00
										 |  |  | 	c := &StatusCache{} | 
					
						
							|  |  |  | 	c.cache = cache.NewLookup(cache.LookupCfg[string, string, *gtsmodel.Status]{ | 
					
						
							|  |  |  | 		RegisterLookups: func(lm *cache.LookupMap[string, string]) { | 
					
						
							|  |  |  | 			lm.RegisterLookup("uri") | 
					
						
							|  |  |  | 			lm.RegisterLookup("url") | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		AddLookups: func(lm *cache.LookupMap[string, string], status *gtsmodel.Status) { | 
					
						
							|  |  |  | 			if uri := status.URI; uri != "" { | 
					
						
							|  |  |  | 				lm.Set("uri", uri, status.ID) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if url := status.URL; url != "" { | 
					
						
							|  |  |  | 				lm.Set("url", url, status.ID) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		DeleteLookups: func(lm *cache.LookupMap[string, string], status *gtsmodel.Status) { | 
					
						
							|  |  |  | 			if uri := status.URI; uri != "" { | 
					
						
							|  |  |  | 				lm.Delete("uri", uri) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if url := status.URL; url != "" { | 
					
						
							|  |  |  | 				lm.Delete("url", url) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2021-08-29 15:41:41 +01:00
										 |  |  | 	}) | 
					
						
							| 
									
										
										
										
											2022-07-10 16:18:21 +01:00
										 |  |  | 	c.cache.SetTTL(time.Minute*5, false) | 
					
						
							|  |  |  | 	c.cache.Start(time.Second * 10) | 
					
						
							|  |  |  | 	return c | 
					
						
							| 
									
										
										
										
											2021-08-29 15:41:41 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-01 10:08:21 +01:00
										 |  |  | // GetByID attempts to fetch a status from the cache by its ID, you will receive a copy for thread-safety | 
					
						
							| 
									
										
										
										
											2021-08-29 15:41:41 +01:00
										 |  |  | func (c *StatusCache) GetByID(id string) (*gtsmodel.Status, bool) { | 
					
						
							| 
									
										
										
										
											2022-07-10 16:18:21 +01:00
										 |  |  | 	return c.cache.Get(id) | 
					
						
							| 
									
										
										
										
											2021-08-29 15:41:41 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-01 10:08:21 +01:00
										 |  |  | // GetByURL attempts to fetch a status from the cache by its URL, you will receive a copy for thread-safety | 
					
						
							| 
									
										
										
										
											2021-08-29 15:41:41 +01:00
										 |  |  | func (c *StatusCache) GetByURL(url string) (*gtsmodel.Status, bool) { | 
					
						
							| 
									
										
										
										
											2022-07-10 16:18:21 +01:00
										 |  |  | 	return c.cache.GetBy("url", url) | 
					
						
							| 
									
										
										
										
											2021-08-29 15:41:41 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-01 10:08:21 +01:00
										 |  |  | // GetByURI attempts to fetch a status from the cache by its URI, you will receive a copy for thread-safety | 
					
						
							| 
									
										
										
										
											2021-08-29 15:41:41 +01:00
										 |  |  | func (c *StatusCache) GetByURI(uri string) (*gtsmodel.Status, bool) { | 
					
						
							| 
									
										
										
										
											2022-07-10 16:18:21 +01:00
										 |  |  | 	return c.cache.GetBy("uri", uri) | 
					
						
							| 
									
										
										
										
											2021-08-29 15:41:41 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-01 10:08:21 +01:00
										 |  |  | // Put places a status in the cache, ensuring that the object place is a copy for thread-safety | 
					
						
							| 
									
										
										
										
											2021-08-29 15:41:41 +01:00
										 |  |  | func (c *StatusCache) Put(status *gtsmodel.Status) { | 
					
						
							| 
									
										
										
										
											2021-09-01 10:08:21 +01:00
										 |  |  | 	if status == nil || status.ID == "" { | 
					
						
							| 
									
										
										
										
											2021-08-29 15:41:41 +01:00
										 |  |  | 		panic("invalid status") | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-09-01 10:08:21 +01:00
										 |  |  | 	c.cache.Set(status.ID, copyStatus(status)) | 
					
						
							| 
									
										
										
										
											2021-08-29 15:41:41 +01:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2021-09-01 10:08:21 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-21 19:55:52 +02:00
										 |  |  | // Invalidate invalidates one status from the cache using the ID of the status as key. | 
					
						
							|  |  |  | func (c *StatusCache) Invalidate(statusID string) { | 
					
						
							|  |  |  | 	c.cache.Invalidate(statusID) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-01 10:08:21 +01:00
										 |  |  | // copyStatus performs a surface-level copy of status, 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 copyStatus(status *gtsmodel.Status) *gtsmodel.Status { | 
					
						
							|  |  |  | 	return >smodel.Status{ | 
					
						
							|  |  |  | 		ID:                       status.ID, | 
					
						
							|  |  |  | 		URI:                      status.URI, | 
					
						
							|  |  |  | 		URL:                      status.URL, | 
					
						
							|  |  |  | 		Content:                  status.Content, | 
					
						
							|  |  |  | 		AttachmentIDs:            status.AttachmentIDs, | 
					
						
							|  |  |  | 		Attachments:              nil, | 
					
						
							|  |  |  | 		TagIDs:                   status.TagIDs, | 
					
						
							|  |  |  | 		Tags:                     nil, | 
					
						
							|  |  |  | 		MentionIDs:               status.MentionIDs, | 
					
						
							|  |  |  | 		Mentions:                 nil, | 
					
						
							|  |  |  | 		EmojiIDs:                 status.EmojiIDs, | 
					
						
							|  |  |  | 		Emojis:                   nil, | 
					
						
							| 
									
										
										
										
											2022-08-15 12:35:05 +02:00
										 |  |  | 		Local:                    copyBoolPtr(status.Local), | 
					
						
							| 
									
										
										
										
											2021-09-01 10:08:21 +01:00
										 |  |  | 		CreatedAt:                status.CreatedAt, | 
					
						
							|  |  |  | 		UpdatedAt:                status.UpdatedAt, | 
					
						
							|  |  |  | 		AccountID:                status.AccountID, | 
					
						
							|  |  |  | 		Account:                  nil, | 
					
						
							|  |  |  | 		AccountURI:               status.AccountURI, | 
					
						
							|  |  |  | 		InReplyToID:              status.InReplyToID, | 
					
						
							|  |  |  | 		InReplyTo:                nil, | 
					
						
							|  |  |  | 		InReplyToURI:             status.InReplyToURI, | 
					
						
							|  |  |  | 		InReplyToAccountID:       status.InReplyToAccountID, | 
					
						
							|  |  |  | 		InReplyToAccount:         nil, | 
					
						
							|  |  |  | 		BoostOfID:                status.BoostOfID, | 
					
						
							|  |  |  | 		BoostOf:                  nil, | 
					
						
							|  |  |  | 		BoostOfAccountID:         status.BoostOfAccountID, | 
					
						
							|  |  |  | 		BoostOfAccount:           nil, | 
					
						
							|  |  |  | 		ContentWarning:           status.ContentWarning, | 
					
						
							|  |  |  | 		Visibility:               status.Visibility, | 
					
						
							| 
									
										
										
										
											2022-08-15 12:35:05 +02:00
										 |  |  | 		Sensitive:                copyBoolPtr(status.Sensitive), | 
					
						
							| 
									
										
										
										
											2021-09-01 10:08:21 +01:00
										 |  |  | 		Language:                 status.Language, | 
					
						
							|  |  |  | 		CreatedWithApplicationID: status.CreatedWithApplicationID, | 
					
						
							|  |  |  | 		ActivityStreamsType:      status.ActivityStreamsType, | 
					
						
							|  |  |  | 		Text:                     status.Text, | 
					
						
							| 
									
										
										
										
											2022-08-15 12:35:05 +02:00
										 |  |  | 		Pinned:                   copyBoolPtr(status.Pinned), | 
					
						
							|  |  |  | 		Federated:                copyBoolPtr(status.Federated), | 
					
						
							|  |  |  | 		Boostable:                copyBoolPtr(status.Boostable), | 
					
						
							|  |  |  | 		Replyable:                copyBoolPtr(status.Replyable), | 
					
						
							|  |  |  | 		Likeable:                 copyBoolPtr(status.Likeable), | 
					
						
							| 
									
										
										
										
											2021-09-01 10:08:21 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | } |