commit 5d55e8d920cd5969e5cff567ee88afb13f40a1b9
parent 9be16852f212f56637fd4a41f3361d30ce7deb5c
Author: kim <89579420+NyaaaWhatsUpDoc@users.noreply.github.com>
Date: Sun, 20 Nov 2022 16:33:49 +0000
[performance] add account block DB cache and remove block query joins (#1085)
* add account block DB cache and remove reliance on relational joins
* actually include cache key arguments...
* add a PutBlock() method which also updates the block cache, update tests accordingly
* use `PutBlock` instead of `Put(ctx, block)`
* add + use functions for deleting + invalidating blocks
Signed-off-by: kim <grufwub@gmail.com>
Co-authored-by: tsmethurst <tobi.smethurst@protonmail.com>
Diffstat:
11 files changed, 315 insertions(+), 76 deletions(-)
diff --git a/internal/api/s2s/user/inboxpost_test.go b/internal/api/s2s/user/inboxpost_test.go
@@ -153,7 +153,7 @@ func (suite *InboxPostTestSuite) TestPostUnblock() {
TargetAccountID: blockedAccount.ID,
}
- err = suite.db.Put(context.Background(), dbBlock)
+ err = suite.db.PutBlock(context.Background(), dbBlock)
suite.NoError(err)
asBlock, err := suite.tc.BlockToAS(context.Background(), dbBlock)
diff --git a/internal/db/bundb/bundb.go b/internal/db/bundb/bundb.go
@@ -166,6 +166,7 @@ func NewBunDBService(ctx context.Context) (db.DB, error) {
notif := ¬ificationDB{conn: conn}
status := &statusDB{conn: conn}
emoji := &emojiDB{conn: conn}
+ relationship := &relationshipDB{conn: conn}
timeline := &timelineDB{conn: conn}
tombstone := &tombstoneDB{conn: conn}
user := &userDB{conn: conn}
@@ -174,6 +175,7 @@ func NewBunDBService(ctx context.Context) (db.DB, error) {
account.emojis = emoji
account.status = status
admin.users = user
+ relationship.accounts = account
status.accounts = account
status.emojis = emoji
status.mentions = mention
@@ -185,6 +187,7 @@ func NewBunDBService(ctx context.Context) (db.DB, error) {
emoji.init()
mention.init()
notif.init()
+ relationship.init()
status.init()
tombstone.init()
user.init()
@@ -209,9 +212,7 @@ func NewBunDBService(ctx context.Context) (db.DB, error) {
},
Mention: mention,
Notification: notif,
- Relationship: &relationshipDB{
- conn: conn,
- },
+ Relationship: relationship,
Session: &sessionDB{
conn: conn,
},
diff --git a/internal/db/bundb/relationship.go b/internal/db/bundb/relationship.go
@@ -21,23 +21,37 @@ package bundb
import (
"context"
"database/sql"
+ "errors"
"fmt"
+ "time"
+ "codeberg.org/gruf/go-cache/v3/result"
"github.com/superseriousbusiness/gotosocial/internal/db"
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
"github.com/uptrace/bun"
)
type relationshipDB struct {
- conn *DBConn
+ conn *DBConn
+ accounts *accountDB
+ blockCache *result.Cache[*gtsmodel.Block]
}
-func (r *relationshipDB) newBlockQ(block *gtsmodel.Block) *bun.SelectQuery {
- return r.conn.
- NewSelect().
- Model(block).
- Relation("Account").
- Relation("TargetAccount")
+func (r *relationshipDB) init() {
+ // Initialize block result cache
+ r.blockCache = result.NewSized([]result.Lookup{
+ {Name: "ID"},
+ {Name: "AccountID.TargetAccountID"},
+ {Name: "URI"},
+ }, func(b1 *gtsmodel.Block) *gtsmodel.Block {
+ b2 := new(gtsmodel.Block)
+ *b2 = *b1
+ return b2
+ }, 1000)
+
+ // Set cache TTL and start sweep routine
+ r.blockCache.SetTTL(time.Minute*5, false)
+ r.blockCache.Start(time.Second * 10)
}
func (r *relationshipDB) newFollowQ(follow interface{}) *bun.SelectQuery {
@@ -49,43 +63,143 @@ func (r *relationshipDB) newFollowQ(follow interface{}) *bun.SelectQuery {
}
func (r *relationshipDB) IsBlocked(ctx context.Context, account1 string, account2 string, eitherDirection bool) (bool, db.Error) {
+ // Look for a block in direction of account1->account2
+ block1, err := r.getBlock(ctx, account1, account2)
+ if err != nil && !errors.Is(err, db.ErrNoEntries) {
+ return false, err
+ }
+
+ if block1 != nil {
+ // account1 blocks account2
+ return true, nil
+ } else if !eitherDirection {
+ // Don't check for mutli-directional
+ return false, nil
+ }
+
+ // Look for a block in direction of account2->account1
+ block2, err := r.getBlock(ctx, account2, account1)
+ if err != nil && !errors.Is(err, db.ErrNoEntries) {
+ return false, err
+ }
+
+ return (block2 != nil), nil
+}
+
+func (r *relationshipDB) GetBlock(ctx context.Context, account1 string, account2 string) (*gtsmodel.Block, db.Error) {
+ // Fetch block from database
+ block, err := r.getBlock(ctx, account1, account2)
+ if err != nil {
+ return nil, err
+ }
+
+ // Set the block originating account
+ block.Account, err = r.accounts.GetAccountByID(ctx, block.AccountID)
+ if err != nil {
+ return nil, err
+ }
+
+ // Set the block target account
+ block.TargetAccount, err = r.accounts.GetAccountByID(ctx, block.TargetAccountID)
+ if err != nil {
+ return nil, err
+ }
+
+ return block, nil
+}
+
+func (r *relationshipDB) getBlock(ctx context.Context, account1 string, account2 string) (*gtsmodel.Block, db.Error) {
+ return r.blockCache.Load("AccountID.TargetAccountID", func() (*gtsmodel.Block, error) {
+ var block gtsmodel.Block
+
+ q := r.conn.NewSelect().Model(&block).
+ Where("? = ?", bun.Ident("block.account_id"), account1).
+ Where("? = ?", bun.Ident("block.target_account_id"), account2)
+ if err := q.Scan(ctx); err != nil {
+ return nil, r.conn.ProcessError(err)
+ }
+
+ return &block, nil
+ }, account1, account2)
+}
+
+func (r *relationshipDB) PutBlock(ctx context.Context, block *gtsmodel.Block) db.Error {
+ return r.blockCache.Store(block, func() error {
+ _, err := r.conn.NewInsert().Model(block).Exec(ctx)
+ return r.conn.ProcessError(err)
+ })
+}
+
+func (r *relationshipDB) DeleteBlockByID(ctx context.Context, id string) db.Error {
+ if _, err := r.conn.
+ NewDelete().
+ TableExpr("? AS ?", bun.Ident("blocks"), bun.Ident("block")).
+ Where("? = ?", bun.Ident("block.id"), id).
+ Exec(ctx); err != nil {
+ return r.conn.ProcessError(err)
+ }
+
+ // Drop any old value from cache by this ID
+ r.blockCache.Invalidate("ID", id)
+ return nil
+}
+
+func (r *relationshipDB) DeleteBlockByURI(ctx context.Context, uri string) db.Error {
+ if _, err := r.conn.
+ NewDelete().
+ TableExpr("? AS ?", bun.Ident("blocks"), bun.Ident("block")).
+ Where("? = ?", bun.Ident("block.uri"), uri).
+ Exec(ctx); err != nil {
+ return r.conn.ProcessError(err)
+ }
+
+ // Drop any old value from cache by this URI
+ r.blockCache.Invalidate("URI", uri)
+ return nil
+}
+
+func (r *relationshipDB) DeleteBlocksByOriginAccountID(ctx context.Context, originAccountID string) db.Error {
+ blockIDs := []string{}
+
q := r.conn.
NewSelect().
TableExpr("? AS ?", bun.Ident("blocks"), bun.Ident("block")).
- Column("block.id")
+ Column("block.id").
+ Where("? = ?", bun.Ident("block.account_id"), originAccountID)
- if eitherDirection {
- q = q.
- WhereGroup(" OR ", func(inner *bun.SelectQuery) *bun.SelectQuery {
- return inner.
- Where("? = ?", bun.Ident("block.account_id"), account1).
- Where("? = ?", bun.Ident("block.target_account_id"), account2)
- }).
- WhereGroup(" OR ", func(inner *bun.SelectQuery) *bun.SelectQuery {
- return inner.
- Where("? = ?", bun.Ident("block.account_id"), account2).
- Where("? = ?", bun.Ident("block.target_account_id"), account1)
- })
- } else {
- q = q.
- Where("? = ?", bun.Ident("block.account_id"), account1).
- Where("? = ?", bun.Ident("block.target_account_id"), account2)
+ if err := q.Scan(ctx, &blockIDs); err != nil {
+ return r.conn.ProcessError(err)
}
- return r.conn.Exists(ctx, q)
+ for _, blockID := range blockIDs {
+ if err := r.DeleteBlockByID(ctx, blockID); err != nil {
+ return err
+ }
+ }
+
+ return nil
}
-func (r *relationshipDB) GetBlock(ctx context.Context, account1 string, account2 string) (*gtsmodel.Block, db.Error) {
- block := >smodel.Block{}
+func (r *relationshipDB) DeleteBlocksByTargetAccountID(ctx context.Context, targetAccountID string) db.Error {
+ blockIDs := []string{}
- q := r.newBlockQ(block).
- Where("? = ?", bun.Ident("block.account_id"), account1).
- Where("? = ?", bun.Ident("block.target_account_id"), account2)
+ q := r.conn.
+ NewSelect().
+ TableExpr("? AS ?", bun.Ident("blocks"), bun.Ident("block")).
+ Column("block.id").
+ Where("? = ?", bun.Ident("block.target_account_id"), targetAccountID)
- if err := q.Scan(ctx); err != nil {
- return nil, r.conn.ProcessError(err)
+ if err := q.Scan(ctx, &blockIDs); err != nil {
+ return r.conn.ProcessError(err)
}
- return block, nil
+
+ for _, blockID := range blockIDs {
+ if err := r.DeleteBlockByID(ctx, blockID); err != nil {
+ return err
+ }
+ }
+
+ return nil
}
func (r *relationshipDB) GetRelationship(ctx context.Context, requestingAccount string, targetAccount string) (*gtsmodel.Relationship, db.Error) {
@@ -144,30 +258,18 @@ func (r *relationshipDB) GetRelationship(ctx context.Context, requestingAccount
rel.Requested = requested
// check if the requesting account is blocking the target account
- blockingQ := r.conn.
- NewSelect().
- TableExpr("? AS ?", bun.Ident("blocks"), bun.Ident("block")).
- Column("block.id").
- Where("? = ?", bun.Ident("block.account_id"), requestingAccount).
- Where("? = ?", bun.Ident("block.target_account_id"), targetAccount)
- blocking, err := r.conn.Exists(ctx, blockingQ)
- if err != nil {
+ blockA2T, err := r.getBlock(ctx, requestingAccount, targetAccount)
+ if err != nil && !errors.Is(err, db.ErrNoEntries) {
return nil, fmt.Errorf("GetRelationship: error checking blocking: %s", err)
}
- rel.Blocking = blocking
+ rel.Blocking = (blockA2T != nil)
// check if the requesting account is blocked by the target account
- blockedByQ := r.conn.
- NewSelect().
- TableExpr("? AS ?", bun.Ident("blocks"), bun.Ident("block")).
- Column("block.id").
- Where("? = ?", bun.Ident("block.account_id"), targetAccount).
- Where("? = ?", bun.Ident("block.target_account_id"), requestingAccount)
- blockedBy, err := r.conn.Exists(ctx, blockedByQ)
- if err != nil {
+ blockT2A, err := r.getBlock(ctx, targetAccount, requestingAccount)
+ if err != nil && !errors.Is(err, db.ErrNoEntries) {
return nil, fmt.Errorf("GetRelationship: error checking blockedBy: %s", err)
}
- rel.BlockedBy = blockedBy
+ rel.BlockedBy = (blockT2A != nil)
return rel, nil
}
diff --git a/internal/db/bundb/relationship_test.go b/internal/db/bundb/relationship_test.go
@@ -47,7 +47,7 @@ func (suite *RelationshipTestSuite) TestIsBlocked() {
suite.False(blocked)
// have account1 block account2
- if err := suite.db.Put(ctx, >smodel.Block{
+ if err := suite.db.PutBlock(ctx, >smodel.Block{
ID: "01G202BCSXXJZ70BHB5KCAHH8C",
URI: "http://localhost:8080/some_block_uri_1",
AccountID: account1,
@@ -81,7 +81,7 @@ func (suite *RelationshipTestSuite) TestGetBlock() {
account1 := suite.testAccounts["local_account_1"].ID
account2 := suite.testAccounts["local_account_2"].ID
- if err := suite.db.Put(ctx, >smodel.Block{
+ if err := suite.db.PutBlock(ctx, >smodel.Block{
ID: "01G202BCSXXJZ70BHB5KCAHH8C",
URI: "http://localhost:8080/some_block_uri_1",
AccountID: account1,
@@ -96,6 +96,130 @@ func (suite *RelationshipTestSuite) TestGetBlock() {
suite.Equal("01G202BCSXXJZ70BHB5KCAHH8C", block.ID)
}
+func (suite *RelationshipTestSuite) TestDeleteBlockByID() {
+ ctx := context.Background()
+
+ // put a block in first
+ account1 := suite.testAccounts["local_account_1"].ID
+ account2 := suite.testAccounts["local_account_2"].ID
+ if err := suite.db.PutBlock(ctx, >smodel.Block{
+ ID: "01G202BCSXXJZ70BHB5KCAHH8C",
+ URI: "http://localhost:8080/some_block_uri_1",
+ AccountID: account1,
+ TargetAccountID: account2,
+ }); err != nil {
+ suite.FailNow(err.Error())
+ }
+
+ // make sure the block is in the db
+ block, err := suite.db.GetBlock(ctx, account1, account2)
+ suite.NoError(err)
+ suite.NotNil(block)
+ suite.Equal("01G202BCSXXJZ70BHB5KCAHH8C", block.ID)
+
+ // delete the block by ID
+ err = suite.db.DeleteBlockByID(ctx, "01G202BCSXXJZ70BHB5KCAHH8C")
+ suite.NoError(err)
+
+ // block should be gone
+ block, err = suite.db.GetBlock(ctx, account1, account2)
+ suite.ErrorIs(err, db.ErrNoEntries)
+ suite.Nil(block)
+}
+
+func (suite *RelationshipTestSuite) TestDeleteBlockByURI() {
+ ctx := context.Background()
+
+ // put a block in first
+ account1 := suite.testAccounts["local_account_1"].ID
+ account2 := suite.testAccounts["local_account_2"].ID
+ if err := suite.db.PutBlock(ctx, >smodel.Block{
+ ID: "01G202BCSXXJZ70BHB5KCAHH8C",
+ URI: "http://localhost:8080/some_block_uri_1",
+ AccountID: account1,
+ TargetAccountID: account2,
+ }); err != nil {
+ suite.FailNow(err.Error())
+ }
+
+ // make sure the block is in the db
+ block, err := suite.db.GetBlock(ctx, account1, account2)
+ suite.NoError(err)
+ suite.NotNil(block)
+ suite.Equal("01G202BCSXXJZ70BHB5KCAHH8C", block.ID)
+
+ // delete the block by uri
+ err = suite.db.DeleteBlockByURI(ctx, "http://localhost:8080/some_block_uri_1")
+ suite.NoError(err)
+
+ // block should be gone
+ block, err = suite.db.GetBlock(ctx, account1, account2)
+ suite.ErrorIs(err, db.ErrNoEntries)
+ suite.Nil(block)
+}
+
+func (suite *RelationshipTestSuite) TestDeleteBlocksByOriginAccountID() {
+ ctx := context.Background()
+
+ // put a block in first
+ account1 := suite.testAccounts["local_account_1"].ID
+ account2 := suite.testAccounts["local_account_2"].ID
+ if err := suite.db.PutBlock(ctx, >smodel.Block{
+ ID: "01G202BCSXXJZ70BHB5KCAHH8C",
+ URI: "http://localhost:8080/some_block_uri_1",
+ AccountID: account1,
+ TargetAccountID: account2,
+ }); err != nil {
+ suite.FailNow(err.Error())
+ }
+
+ // make sure the block is in the db
+ block, err := suite.db.GetBlock(ctx, account1, account2)
+ suite.NoError(err)
+ suite.NotNil(block)
+ suite.Equal("01G202BCSXXJZ70BHB5KCAHH8C", block.ID)
+
+ // delete the block by originAccountID
+ err = suite.db.DeleteBlocksByOriginAccountID(ctx, account1)
+ suite.NoError(err)
+
+ // block should be gone
+ block, err = suite.db.GetBlock(ctx, account1, account2)
+ suite.ErrorIs(err, db.ErrNoEntries)
+ suite.Nil(block)
+}
+
+func (suite *RelationshipTestSuite) TestDeleteBlocksByTargetAccountID() {
+ ctx := context.Background()
+
+ // put a block in first
+ account1 := suite.testAccounts["local_account_1"].ID
+ account2 := suite.testAccounts["local_account_2"].ID
+ if err := suite.db.PutBlock(ctx, >smodel.Block{
+ ID: "01G202BCSXXJZ70BHB5KCAHH8C",
+ URI: "http://localhost:8080/some_block_uri_1",
+ AccountID: account1,
+ TargetAccountID: account2,
+ }); err != nil {
+ suite.FailNow(err.Error())
+ }
+
+ // make sure the block is in the db
+ block, err := suite.db.GetBlock(ctx, account1, account2)
+ suite.NoError(err)
+ suite.NotNil(block)
+ suite.Equal("01G202BCSXXJZ70BHB5KCAHH8C", block.ID)
+
+ // delete the block by targetAccountID
+ err = suite.db.DeleteBlocksByTargetAccountID(ctx, account2)
+ suite.NoError(err)
+
+ // block should be gone
+ block, err = suite.db.GetBlock(ctx, account1, account2)
+ suite.ErrorIs(err, db.ErrNoEntries)
+ suite.Nil(block)
+}
+
func (suite *RelationshipTestSuite) TestGetRelationship() {
requestingAccount := suite.testAccounts["local_account_1"]
targetAccount := suite.testAccounts["admin_account"]
diff --git a/internal/db/relationship.go b/internal/db/relationship.go
@@ -36,6 +36,21 @@ type Relationship interface {
// not if you're just checking for the existence of a block.
GetBlock(ctx context.Context, account1 string, account2 string) (*gtsmodel.Block, Error)
+ // PutBlock attempts to place the given account block in the database.
+ PutBlock(ctx context.Context, block *gtsmodel.Block) Error
+
+ // DeleteBlockByID removes block with given ID from the database.
+ DeleteBlockByID(ctx context.Context, id string) Error
+
+ // DeleteBlockByURI removes block with given AP URI from the database.
+ DeleteBlockByURI(ctx context.Context, uri string) Error
+
+ // DeleteBlocksByOriginAccountID removes any blocks with accountID equal to originAccountID.
+ DeleteBlocksByOriginAccountID(ctx context.Context, originAccountID string) Error
+
+ // DeleteBlocksByTargetAccountID removes any blocks with given targetAccountID.
+ DeleteBlocksByTargetAccountID(ctx context.Context, targetAccountID string) Error
+
// GetRelationship retrieves the relationship of the targetAccount to the requestingAccount.
GetRelationship(ctx context.Context, requestingAccount string, targetAccount string) (*gtsmodel.Relationship, Error)
diff --git a/internal/federation/federatingdb/create.go b/internal/federation/federatingdb/create.go
@@ -103,7 +103,7 @@ func (f *federatingDB) activityBlock(ctx context.Context, asType vocab.Type, rec
}
block.ID = newID
- if err := f.db.Put(ctx, block); err != nil {
+ if err := f.db.PutBlock(ctx, block); err != nil {
return fmt.Errorf("activityBlock: database error inserting block: %s", err)
}
diff --git a/internal/federation/federatingdb/undo.go b/internal/federation/federatingdb/undo.go
@@ -114,7 +114,7 @@ func (f *federatingDB) Undo(ctx context.Context, undo vocab.ActivityStreamsUndo)
return errors.New("UNDO: block object account and inbox account were not the same")
}
// delete any existing BLOCK
- if err := f.db.DeleteWhere(ctx, []db.Where{{Key: "uri", Value: gtsBlock.URI}}, >smodel.Block{}); err != nil {
+ if err := f.db.DeleteBlockByURI(ctx, gtsBlock.URI); err != nil {
return fmt.Errorf("UNDO: db error removing block: %s", err)
}
l.Debug("block undone")
diff --git a/internal/federation/federatingprotocol_test.go b/internal/federation/federatingprotocol_test.go
@@ -312,7 +312,7 @@ func (suite *FederatingProtocolTestSuite) TestBlocked2() {
ctxWithOtherInvolvedIRIs := context.WithValue(ctxWithRequestingAccount, ap.ContextOtherInvolvedIRIs, otherInvolvedIRIs)
// insert a block from inboxAccount targeting sendingAccount
- if err := suite.db.Put(context.Background(), >smodel.Block{
+ if err := suite.db.PutBlock(context.Background(), >smodel.Block{
ID: "01G3KBEMJD4VQ2D615MPV7KTRD",
URI: "whatever",
AccountID: inboxAccount.ID,
@@ -350,7 +350,7 @@ func (suite *FederatingProtocolTestSuite) TestBlocked3() {
ctxWithOtherInvolvedIRIs := context.WithValue(ctxWithRequestingAccount, ap.ContextOtherInvolvedIRIs, otherInvolvedIRIs)
// insert a block from inboxAccount targeting CCed account
- if err := suite.db.Put(context.Background(), >smodel.Block{
+ if err := suite.db.PutBlock(context.Background(), >smodel.Block{
ID: "01G3KBEMJD4VQ2D615MPV7KTRD",
URI: "whatever",
AccountID: inboxAccount.ID,
diff --git a/internal/processing/account/createblock.go b/internal/processing/account/createblock.go
@@ -65,7 +65,7 @@ func (p *processor) BlockCreate(ctx context.Context, requestingAccount *gtsmodel
block.URI = uris.GenerateURIForBlock(requestingAccount.Username, newBlockID)
// whack it in the database
- if err := p.db.Put(ctx, block); err != nil {
+ if err := p.db.PutBlock(ctx, block); err != nil {
return nil, gtserror.NewErrorInternalError(fmt.Errorf("BlockCreate: error creating block in db: %s", err))
}
diff --git a/internal/processing/account/delete.go b/internal/processing/account/delete.go
@@ -99,12 +99,12 @@ func (p *processor) Delete(ctx context.Context, account *gtsmodel.Account, origi
// 2. Delete account's blocks
l.Trace("deleting account blocks")
// first delete any blocks that this account created
- if err := p.db.DeleteWhere(ctx, []db.Where{{Key: "account_id", Value: account.ID}}, &[]*gtsmodel.Block{}); err != nil {
+ if err := p.db.DeleteBlocksByOriginAccountID(ctx, account.ID); err != nil {
l.Errorf("error deleting blocks created by account: %s", err)
}
// now delete any blocks that target this account
- if err := p.db.DeleteWhere(ctx, []db.Where{{Key: "target_account_id", Value: account.ID}}, &[]*gtsmodel.Block{}); err != nil {
+ if err := p.db.DeleteBlocksByTargetAccountID(ctx, account.ID); err != nil {
l.Errorf("error deleting blocks targeting account: %s", err)
}
diff --git a/internal/processing/account/removeblock.go b/internal/processing/account/removeblock.go
@@ -20,6 +20,7 @@ package account
import (
"context"
+ "errors"
"fmt"
"github.com/superseriousbusiness/gotosocial/internal/ap"
@@ -37,23 +38,17 @@ func (p *processor) BlockRemove(ctx context.Context, requestingAccount *gtsmodel
return nil, gtserror.NewErrorNotFound(fmt.Errorf("BlockCreate: error getting account %s from the db: %s", targetAccountID, err))
}
- // check if a block exists, and remove it if it does (storing the URI for later)
- var blockChanged bool
- block := >smodel.Block{}
- if err := p.db.GetWhere(ctx, []db.Where{
- {Key: "account_id", Value: requestingAccount.ID},
- {Key: "target_account_id", Value: targetAccountID},
- }, block); err == nil {
+ // check if a block exists, and remove it if it does
+ block, err := p.db.GetBlock(ctx, requestingAccount.ID, targetAccountID)
+ if err == nil {
+ // we got a block, remove it
block.Account = requestingAccount
block.TargetAccount = targetAccount
- if err := p.db.DeleteByID(ctx, block.ID, >smodel.Block{}); err != nil {
+ if err := p.db.DeleteBlockByID(ctx, block.ID); err != nil {
return nil, gtserror.NewErrorInternalError(fmt.Errorf("BlockRemove: error removing block from db: %s", err))
}
- blockChanged = true
- }
- // block status changed so send the UNDO activity to the channel for async processing
- if blockChanged {
+ // send the UNDO activity to the client worker for async processing
p.clientWorker.Queue(messages.FromClientAPI{
APObjectType: ap.ActivityBlock,
APActivityType: ap.ActivityUndo,
@@ -61,6 +56,8 @@ func (p *processor) BlockRemove(ctx context.Context, requestingAccount *gtsmodel
OriginAccount: requestingAccount,
TargetAccount: targetAccount,
})
+ } else if !errors.Is(err, db.ErrNoEntries) {
+ return nil, gtserror.NewErrorInternalError(fmt.Errorf("BlockRemove: error getting possible block from db: %s", err))
}
// return whatever relationship results from all this