mirror of
				https://github.com/superseriousbusiness/gotosocial.git
				synced 2025-10-31 01:22:28 -05:00 
			
		
		
		
	[bugfix] add ON CONFLICT statements to status updates (#1580)
This commit is contained in:
		
					parent
					
						
							
								e6cde25466
							
						
					
				
			
			
				commit
				
					
						bfccf4e450
					
				
			
		
					 2 changed files with 43 additions and 6 deletions
				
			
		|  | @ -200,7 +200,9 @@ func (s *statusDB) PutStatus(ctx context.Context, status *gtsmodel.Status) db.Er | |||
| 					Model(>smodel.StatusToEmoji{ | ||||
| 						StatusID: status.ID, | ||||
| 						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) | ||||
| 					if !errors.Is(err, db.ErrAlreadyExists) { | ||||
| 						return err | ||||
|  | @ -215,7 +217,9 @@ func (s *statusDB) PutStatus(ctx context.Context, status *gtsmodel.Status) db.Er | |||
| 					Model(>smodel.StatusToTag{ | ||||
| 						StatusID: status.ID, | ||||
| 						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) | ||||
| 					if !errors.Is(err, db.ErrAlreadyExists) { | ||||
| 						return err | ||||
|  | @ -261,7 +265,9 @@ func (s *statusDB) UpdateStatus(ctx context.Context, status *gtsmodel.Status, co | |||
| 				Model(>smodel.StatusToEmoji{ | ||||
| 					StatusID: status.ID, | ||||
| 					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) | ||||
| 				if !errors.Is(err, db.ErrAlreadyExists) { | ||||
| 					return err | ||||
|  | @ -276,7 +282,9 @@ func (s *statusDB) UpdateStatus(ctx context.Context, status *gtsmodel.Status, co | |||
| 				Model(>smodel.StatusToTag{ | ||||
| 					StatusID: status.ID, | ||||
| 					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) | ||||
| 				if !errors.Is(err, db.ErrAlreadyExists) { | ||||
| 					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. | ||||
| 			NewUpdate(). | ||||
| 			Model(status). | ||||
|  |  | |||
|  | @ -26,6 +26,7 @@ import ( | |||
| 
 | ||||
| 	"github.com/stretchr/testify/suite" | ||||
| 	"github.com/superseriousbusiness/gotosocial/internal/db" | ||||
| 	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel" | ||||
| ) | ||||
| 
 | ||||
| type StatusTestSuite struct { | ||||
|  | @ -176,7 +177,10 @@ func (suite *StatusTestSuite) TestGetStatusChildren() { | |||
| } | ||||
| 
 | ||||
| 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) | ||||
| 	suite.NoError(err) | ||||
| 
 | ||||
|  | @ -184,6 +188,31 @@ func (suite *StatusTestSuite) TestDeleteStatus() { | |||
| 	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) { | ||||
| 	suite.Run(t, new(StatusTestSuite)) | ||||
| } | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue