[bugfix] add ON CONFLICT statements to status updates (#1580)
This commit is contained in:
parent
e6cde25466
commit
bfccf4e450
|
@ -200,7 +200,9 @@ func (s *statusDB) PutStatus(ctx context.Context, status *gtsmodel.Status) db.Er
|
||||||
Model(>smodel.StatusToEmoji{
|
Model(>smodel.StatusToEmoji{
|
||||||
StatusID: status.ID,
|
StatusID: status.ID,
|
||||||
EmojiID: i,
|
EmojiID: i,
|
||||||
}).Exec(ctx); err != nil {
|
}).
|
||||||
|
On("CONFLICT (?, ?) DO NOTHING", bun.Ident("status_id"), bun.Ident("emoji_id")).
|
||||||
|
Exec(ctx); err != nil {
|
||||||
err = s.conn.ProcessError(err)
|
err = s.conn.ProcessError(err)
|
||||||
if !errors.Is(err, db.ErrAlreadyExists) {
|
if !errors.Is(err, db.ErrAlreadyExists) {
|
||||||
return err
|
return err
|
||||||
|
@ -215,7 +217,9 @@ func (s *statusDB) PutStatus(ctx context.Context, status *gtsmodel.Status) db.Er
|
||||||
Model(>smodel.StatusToTag{
|
Model(>smodel.StatusToTag{
|
||||||
StatusID: status.ID,
|
StatusID: status.ID,
|
||||||
TagID: i,
|
TagID: i,
|
||||||
}).Exec(ctx); err != nil {
|
}).
|
||||||
|
On("CONFLICT (?, ?) DO NOTHING", bun.Ident("status_id"), bun.Ident("tag_id")).
|
||||||
|
Exec(ctx); err != nil {
|
||||||
err = s.conn.ProcessError(err)
|
err = s.conn.ProcessError(err)
|
||||||
if !errors.Is(err, db.ErrAlreadyExists) {
|
if !errors.Is(err, db.ErrAlreadyExists) {
|
||||||
return err
|
return err
|
||||||
|
@ -261,7 +265,9 @@ func (s *statusDB) UpdateStatus(ctx context.Context, status *gtsmodel.Status, co
|
||||||
Model(>smodel.StatusToEmoji{
|
Model(>smodel.StatusToEmoji{
|
||||||
StatusID: status.ID,
|
StatusID: status.ID,
|
||||||
EmojiID: i,
|
EmojiID: i,
|
||||||
}).Exec(ctx); err != nil {
|
}).
|
||||||
|
On("CONFLICT (?, ?) DO NOTHING", bun.Ident("status_id"), bun.Ident("emoji_id")).
|
||||||
|
Exec(ctx); err != nil {
|
||||||
err = s.conn.ProcessError(err)
|
err = s.conn.ProcessError(err)
|
||||||
if !errors.Is(err, db.ErrAlreadyExists) {
|
if !errors.Is(err, db.ErrAlreadyExists) {
|
||||||
return err
|
return err
|
||||||
|
@ -276,7 +282,9 @@ func (s *statusDB) UpdateStatus(ctx context.Context, status *gtsmodel.Status, co
|
||||||
Model(>smodel.StatusToTag{
|
Model(>smodel.StatusToTag{
|
||||||
StatusID: status.ID,
|
StatusID: status.ID,
|
||||||
TagID: i,
|
TagID: i,
|
||||||
}).Exec(ctx); err != nil {
|
}).
|
||||||
|
On("CONFLICT (?, ?) DO NOTHING", bun.Ident("status_id"), bun.Ident("tag_id")).
|
||||||
|
Exec(ctx); err != nil {
|
||||||
err = s.conn.ProcessError(err)
|
err = s.conn.ProcessError(err)
|
||||||
if !errors.Is(err, db.ErrAlreadyExists) {
|
if !errors.Is(err, db.ErrAlreadyExists) {
|
||||||
return err
|
return err
|
||||||
|
@ -300,7 +308,7 @@ func (s *statusDB) UpdateStatus(ctx context.Context, status *gtsmodel.Status, co
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finally, insert the status
|
// Finally, update the status
|
||||||
_, err := tx.
|
_, err := tx.
|
||||||
NewUpdate().
|
NewUpdate().
|
||||||
Model(status).
|
Model(status).
|
||||||
|
|
|
@ -26,6 +26,7 @@ import (
|
||||||
|
|
||||||
"github.com/stretchr/testify/suite"
|
"github.com/stretchr/testify/suite"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/db"
|
"github.com/superseriousbusiness/gotosocial/internal/db"
|
||||||
|
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
||||||
)
|
)
|
||||||
|
|
||||||
type StatusTestSuite struct {
|
type StatusTestSuite struct {
|
||||||
|
@ -176,7 +177,10 @@ func (suite *StatusTestSuite) TestGetStatusChildren() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *StatusTestSuite) TestDeleteStatus() {
|
func (suite *StatusTestSuite) TestDeleteStatus() {
|
||||||
targetStatus := suite.testStatuses["admin_account_status_1"]
|
// Take a copy of the status.
|
||||||
|
targetStatus := >smodel.Status{}
|
||||||
|
*targetStatus = *suite.testStatuses["admin_account_status_1"]
|
||||||
|
|
||||||
err := suite.db.DeleteStatusByID(context.Background(), targetStatus.ID)
|
err := suite.db.DeleteStatusByID(context.Background(), targetStatus.ID)
|
||||||
suite.NoError(err)
|
suite.NoError(err)
|
||||||
|
|
||||||
|
@ -184,6 +188,31 @@ func (suite *StatusTestSuite) TestDeleteStatus() {
|
||||||
suite.ErrorIs(err, db.ErrNoEntries)
|
suite.ErrorIs(err, db.ErrNoEntries)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This test was added specifically to ensure that Postgres wasn't getting upset
|
||||||
|
// about trying to use a transaction in which an error has already occurred, which
|
||||||
|
// was previously leading to errors like 'current transaction is aborted, commands
|
||||||
|
// ignored until end of transaction block' when updating a status that already had
|
||||||
|
// emojis or tags set on it.
|
||||||
|
//
|
||||||
|
// To run this test for postgres specifically, start a postgres container on localhost
|
||||||
|
// and then run:
|
||||||
|
//
|
||||||
|
// GTS_DB_TYPE=postgres GTS_DB_ADDRESS=localhost go test ./internal/db/bundb -run '^TestStatusTestSuite$' -testify.m '^(TestUpdateStatus)$' github.com/superseriousbusiness/gotosocial/internal/db/bundb
|
||||||
|
func (suite *StatusTestSuite) TestUpdateStatus() {
|
||||||
|
// Take a copy of the status.
|
||||||
|
targetStatus := >smodel.Status{}
|
||||||
|
*targetStatus = *suite.testStatuses["admin_account_status_1"]
|
||||||
|
|
||||||
|
targetStatus.PinnedAt = time.Time{}
|
||||||
|
|
||||||
|
err := suite.db.UpdateStatus(context.Background(), targetStatus, "pinned_at")
|
||||||
|
suite.NoError(err)
|
||||||
|
|
||||||
|
updated, err := suite.db.GetStatusByID(context.Background(), targetStatus.ID)
|
||||||
|
suite.NoError(err)
|
||||||
|
suite.True(updated.PinnedAt.IsZero())
|
||||||
|
}
|
||||||
|
|
||||||
func TestStatusTestSuite(t *testing.T) {
|
func TestStatusTestSuite(t *testing.T) {
|
||||||
suite.Run(t, new(StatusTestSuite))
|
suite.Run(t, new(StatusTestSuite))
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue