summaryrefslogtreecommitdiff
path: root/internal/cache
diff options
context:
space:
mode:
authorLibravatar tobi <31960611+tsmethurst@users.noreply.github.com>2023-09-21 12:12:04 +0200
committerLibravatar GitHub <noreply@github.com>2023-09-21 12:12:04 +0200
commit183eaa5b298235acb8f25ba8f18b98e31471d965 (patch)
tree55f42887edeb5206122d92eb30e0eedf145a3615 /internal/cache
parent[docs] Add a note on cluster support (#2214) (diff)
downloadgotosocial-183eaa5b298235acb8f25ba8f18b98e31471d965.tar.xz
[feature] Implement explicit domain allows + allowlist federation mode (#2200)
* love like winter! wohoah, wohoah * domain allow side effects * tests! logging! unallow! * document federation modes * linty linterson * test * further adventures in documentation * finish up domain block documentation (i think) * change wording a wee little bit * docs, example * consolidate shared domainPermission code * call mode once * fetch federation mode within domain blocked func * read domain perm import in streaming manner * don't use pointer to slice for domain perms * don't bother copying blocks + allows before deleting * admonish! * change wording just a scooch * update docs
Diffstat (limited to 'internal/cache')
-rw-r--r--internal/cache/domain/domain.go51
-rw-r--r--internal/cache/domain/domain_test.go30
-rw-r--r--internal/cache/gts.go17
3 files changed, 56 insertions, 42 deletions
diff --git a/internal/cache/domain/domain.go b/internal/cache/domain/domain.go
index 37e97472a..051ec5c1b 100644
--- a/internal/cache/domain/domain.go
+++ b/internal/cache/domain/domain.go
@@ -26,23 +26,28 @@ import (
"golang.org/x/exp/slices"
)
-// BlockCache provides a means of caching domain blocks in memory to reduce load
-// on an underlying storage mechanism, e.g. a database.
+// Cache provides a means of caching domains in memory to reduce
+// load on an underlying storage mechanism, e.g. a database.
//
-// The in-memory block list is kept up-to-date by means of a passed loader function during every
-// call to .IsBlocked(). In the case of a nil internal block list, the loader function is called to
-// hydrate the cache with the latest list of domain blocks. The .Clear() function can be used to
-// invalidate the cache, e.g. when a domain block is added / deleted from the database.
-type BlockCache struct {
+// The in-memory domain list is kept up-to-date by means of a passed
+// loader function during every call to .Matches(). In the case of
+// a nil internal domain list, the loader function is called to hydrate
+// the cache with the latest list of domains.
+//
+// The .Clear() function can be used to invalidate the cache,
+// e.g. when an entry is added / deleted from the database.
+type Cache struct {
// atomically updated ptr value to the
- // current domain block cache radix trie.
+ // current domain cache radix trie.
rootptr unsafe.Pointer
}
-// IsBlocked checks whether domain is blocked. If the cache is not currently loaded, then the provided load function is used to hydrate it.
-func (b *BlockCache) IsBlocked(domain string, load func() ([]string, error)) (bool, error) {
+// Matches checks whether domain matches an entry in the cache.
+// If the cache is not currently loaded, then the provided load
+// function is used to hydrate it.
+func (c *Cache) Matches(domain string, load func() ([]string, error)) (bool, error) {
// Load the current root pointer value.
- ptr := atomic.LoadPointer(&b.rootptr)
+ ptr := atomic.LoadPointer(&c.rootptr)
if ptr == nil {
// Cache is not hydrated.
@@ -67,7 +72,7 @@ func (b *BlockCache) IsBlocked(domain string, load func() ([]string, error)) (bo
// Store the new node ptr.
ptr = unsafe.Pointer(root)
- atomic.StorePointer(&b.rootptr, ptr)
+ atomic.StorePointer(&c.rootptr, ptr)
}
// Look for a match in the trie node.
@@ -75,22 +80,20 @@ func (b *BlockCache) IsBlocked(domain string, load func() ([]string, error)) (bo
}
// Clear will drop the currently loaded domain list,
-// triggering a reload on next call to .IsBlocked().
-func (b *BlockCache) Clear() {
- atomic.StorePointer(&b.rootptr, nil)
+// triggering a reload on next call to .Matches().
+func (c *Cache) Clear() {
+ atomic.StorePointer(&c.rootptr, nil)
}
-// String returns a string representation of stored domains in block cache.
-func (b *BlockCache) String() string {
- if ptr := atomic.LoadPointer(&b.rootptr); ptr != nil {
+// String returns a string representation of stored domains in cache.
+func (c *Cache) String() string {
+ if ptr := atomic.LoadPointer(&c.rootptr); ptr != nil {
return (*root)(ptr).String()
}
return "<empty>"
}
-// root is the root node in the domain
-// block cache radix trie. this is the
-// singular access point to the trie.
+// root is the root node in the domain cache radix trie. this is the singular access point to the trie.
type root struct{ root node }
// Add will add the given domain to the radix trie.
@@ -99,14 +102,14 @@ func (r *root) Add(domain string) {
}
// Match will return whether the given domain matches
-// an existing stored domain block in this radix trie.
+// an existing stored domain in this radix trie.
func (r *root) Match(domain string) bool {
return r.root.match(strings.Split(domain, "."))
}
// Sort will sort the entire radix trie ensuring that
// child nodes are stored in alphabetical order. This
-// MUST be done to finalize the block cache in order
+// MUST be done to finalize the domain cache in order
// to speed up the binary search of node child parts.
func (r *root) Sort() {
r.root.sort()
@@ -154,7 +157,7 @@ func (n *node) add(parts []string) {
if len(parts) == 0 {
// Drop all children here as
- // this is a higher-level block
+ // this is a higher-level domain
// than that we previously had.
nn.child = nil
return
diff --git a/internal/cache/domain/domain_test.go b/internal/cache/domain/domain_test.go
index 8f975497b..9e091e1d0 100644
--- a/internal/cache/domain/domain_test.go
+++ b/internal/cache/domain/domain_test.go
@@ -24,21 +24,21 @@ import (
"github.com/superseriousbusiness/gotosocial/internal/cache/domain"
)
-func TestBlockCache(t *testing.T) {
- c := new(domain.BlockCache)
+func TestCache(t *testing.T) {
+ c := new(domain.Cache)
- blocks := []string{
+ cachedDomains := []string{
"google.com",
"google.co.uk",
"pleroma.bad.host",
}
loader := func() ([]string, error) {
- t.Log("load: returning blocked domains")
- return blocks, nil
+ t.Log("load: returning cached domains")
+ return cachedDomains, nil
}
- // Check a list of known blocked domains.
+ // Check a list of known cached domains.
for _, domain := range []string{
"google.com",
"mail.google.com",
@@ -47,13 +47,13 @@ func TestBlockCache(t *testing.T) {
"pleroma.bad.host",
"dev.pleroma.bad.host",
} {
- t.Logf("checking domain is blocked: %s", domain)
- if b, _ := c.IsBlocked(domain, loader); !b {
- t.Errorf("domain should be blocked: %s", domain)
+ t.Logf("checking domain matches: %s", domain)
+ if b, _ := c.Matches(domain, loader); !b {
+ t.Errorf("domain should be matched: %s", domain)
}
}
- // Check a list of known unblocked domains.
+ // Check a list of known uncached domains.
for _, domain := range []string{
"askjeeves.com",
"ask-kim.co.uk",
@@ -62,9 +62,9 @@ func TestBlockCache(t *testing.T) {
"gts.bad.host",
"mastodon.bad.host",
} {
- t.Logf("checking domain isn't blocked: %s", domain)
- if b, _ := c.IsBlocked(domain, loader); b {
- t.Errorf("domain should not be blocked: %s", domain)
+ t.Logf("checking domain isn't matched: %s", domain)
+ if b, _ := c.Matches(domain, loader); b {
+ t.Errorf("domain should not be matched: %s", domain)
}
}
@@ -76,10 +76,10 @@ func TestBlockCache(t *testing.T) {
knownErr := errors.New("known error")
// Check that reload is actually performed and returns our error
- if _, err := c.IsBlocked("", func() ([]string, error) {
+ if _, err := c.Matches("", func() ([]string, error) {
t.Log("load: returning known error")
return nil, knownErr
}); !errors.Is(err, knownErr) {
- t.Errorf("is blocked did not return expected error: %v", err)
+ t.Errorf("matches did not return expected error: %v", err)
}
}
diff --git a/internal/cache/gts.go b/internal/cache/gts.go
index 12e917919..16a1585f7 100644
--- a/internal/cache/gts.go
+++ b/internal/cache/gts.go
@@ -36,7 +36,8 @@ type GTSCaches struct {
block *result.Cache[*gtsmodel.Block]
blockIDs *SliceCache[string]
boostOfIDs *SliceCache[string]
- domainBlock *domain.BlockCache
+ domainAllow *domain.Cache
+ domainBlock *domain.Cache
emoji *result.Cache[*gtsmodel.Emoji]
emojiCategory *result.Cache[*gtsmodel.EmojiCategory]
follow *result.Cache[*gtsmodel.Follow]
@@ -72,6 +73,7 @@ func (c *GTSCaches) Init() {
c.initBlock()
c.initBlockIDs()
c.initBoostOfIDs()
+ c.initDomainAllow()
c.initDomainBlock()
c.initEmoji()
c.initEmojiCategory()
@@ -139,8 +141,13 @@ func (c *GTSCaches) BoostOfIDs() *SliceCache[string] {
return c.boostOfIDs
}
+// DomainAllow provides access to the domain allow database cache.
+func (c *GTSCaches) DomainAllow() *domain.Cache {
+ return c.domainAllow
+}
+
// DomainBlock provides access to the domain block database cache.
-func (c *GTSCaches) DomainBlock() *domain.BlockCache {
+func (c *GTSCaches) DomainBlock() *domain.Cache {
return c.domainBlock
}
@@ -384,8 +391,12 @@ func (c *GTSCaches) initBoostOfIDs() {
)}
}
+func (c *GTSCaches) initDomainAllow() {
+ c.domainAllow = new(domain.Cache)
+}
+
func (c *GTSCaches) initDomainBlock() {
- c.domainBlock = new(domain.BlockCache)
+ c.domainBlock = new(domain.Cache)
}
func (c *GTSCaches) initEmoji() {