1
0
Fork 0
mirror of https://github.com/Eggbertx/gochan.git synced 2025-08-03 03:36:22 -07:00

Add pre-2021 post upload migration

This commit is contained in:
Eggbertx 2025-01-03 22:01:16 -08:00
parent 7cddc3e43e
commit ee0b91059f
4 changed files with 83 additions and 48 deletions

View file

@ -2,10 +2,13 @@ package pre2021
import (
"context"
"database/sql"
"time"
"github.com/gochan-org/gochan/cmd/gochan-migration/internal/common"
"github.com/gochan-org/gochan/pkg/gcsql"
"github.com/gochan-org/gochan/pkg/gcutil"
"github.com/rs/zerolog"
)
type postTable struct {
@ -37,6 +40,47 @@ func (m *Pre2021Migrator) MigratePosts() error {
return m.migratePostsToNewDB()
}
func (m *Pre2021Migrator) migratePost(tx *sql.Tx, post *postTable, errEv *zerolog.Event) error {
var err error
if post.oldParentID == 0 {
// migrating post was a thread OP, create the row in the threads table
if post.ThreadID, err = gcsql.CreateThread(tx, post.boardID, false, post.stickied, post.autosage, false); err != nil {
errEv.Err(err).Caller().
Int("boardID", post.boardID).
Msg("Failed to create thread")
}
}
// insert thread top post
if err = post.InsertWithContext(context.Background(), tx, true, post.boardID, false, post.stickied, post.autosage, false); err != nil {
errEv.Err(err).Caller().
Int("boardID", post.boardID).
Int("threadID", post.ThreadID).
Msg("Failed to insert thread OP")
}
if post.filename != "" {
if err = post.AttachFileTx(tx, &gcsql.Upload{
PostID: post.ID,
OriginalFilename: post.filenameOriginal,
Filename: post.filename,
Checksum: post.fileChecksum,
FileSize: post.filesize,
ThumbnailWidth: post.thumbW,
ThumbnailHeight: post.thumbH,
Width: post.imageW,
Height: post.imageH,
}); err != nil {
errEv.Err(err).Caller().
Int("oldPostID", post.oldID).
Msg("Failed to attach upload to migrated post")
return err
}
}
return nil
}
func (m *Pre2021Migrator) migratePostsToNewDB() error {
errEv := common.LogError()
defer errEv.Discard()
@ -57,6 +101,7 @@ func (m *Pre2021Migrator) migratePostsToNewDB() error {
var threadIDsWithInvalidBoards []int
var missingBoardIDs []int
var migratedThreads int
for rows.Next() {
var thread postTable
if err = rows.Scan(
@ -83,19 +128,8 @@ func (m *Pre2021Migrator) migratePostsToNewDB() error {
continue
}
// create the thread as not locked so migration replies can be inserted. It will be locked after they are all inserted
if thread.ThreadID, err = gcsql.CreateThread(tx, thread.boardID, false, thread.stickied, thread.autosage, false); err != nil {
errEv.Err(err).Caller().
Int("boardID", thread.boardID).
Msg("Failed to create thread")
}
// insert thread top post
if err = thread.InsertWithContext(context.Background(), tx, true, thread.boardID, false, thread.stickied, thread.autosage, false); err != nil {
errEv.Err(err).Caller().
Int("boardID", thread.boardID).
Int("threadID", thread.ThreadID).
Msg("Failed to insert thread OP")
if err = m.migratePost(tx, &thread, errEv); err != nil {
return err
}
// get and insert replies
@ -123,10 +157,7 @@ func (m *Pre2021Migrator) migratePostsToNewDB() error {
return err
}
reply.ThreadID = thread.ThreadID
if err = reply.InsertWithContext(context.Background(), tx, true, reply.boardID, false, false, false, false); err != nil {
errEv.Err(err).Caller().
Int("parentID", thread.oldID).
Msg("Failed to insert reply post")
if err = m.migratePost(tx, &reply, errEv); err != nil {
return err
}
}
@ -138,6 +169,7 @@ func (m *Pre2021Migrator) migratePostsToNewDB() error {
Msg("Unable to re-lock migrated thread")
}
}
migratedThreads++
}
if len(threadIDsWithInvalidBoards) > 0 {
errEv.Caller().
@ -149,8 +181,12 @@ func (m *Pre2021Migrator) migratePostsToNewDB() error {
if err = tx.Commit(); err != nil {
errEv.Err(err).Caller().Msg("Failed to commit transaction")
return err
}
return err
gcutil.LogInfo().
Int("migratedThreads", migratedThreads).
Msg("Migrated threads successfully")
return nil
}
func (m *Pre2021Migrator) migratePostsInPlace() error {

View file

@ -44,4 +44,8 @@ func TestMigratePostsToNewDB(t *testing.T) {
var numDeleted int
assert.NoError(t, gcsql.QueryRowSQL("SELECT COUNT(*) FROM DBPREFIXposts WHERE message_raw LIKE '%deleted%' OR is_deleted", nil, []any{&numDeleted}))
assert.Zero(t, numDeleted, "Expected no deleted threads to be migrated")
var numUploadPosts int
assert.NoError(t, gcsql.QueryRowSQL("SELECT COUNT(*) FROM DBPREFIXfiles", nil, []any{&numUploadPosts}))
assert.Equal(t, 1, numUploadPosts, "Expected to have 1 upload post")
}

View file

@ -22,14 +22,14 @@ type Pre2021Migrator struct {
options *common.MigrationOptions
config Pre2021Config
posts []postTable
boards []migrationBoard
sections []migrationSection
}
// IsMigratingInPlace implements common.DBMigrator.
func (m *Pre2021Migrator) IsMigratingInPlace() bool {
return m.config.DBname == config.GetSQLConfig().DBname
sqlConfig := config.GetSQLConfig()
return m.config.DBname == sqlConfig.DBname && m.config.DBhost == sqlConfig.DBhost && m.config.DBprefix == sqlConfig.DBprefix
}
func (m *Pre2021Migrator) readConfig() error {
@ -56,7 +56,13 @@ func (m *Pre2021Migrator) Init(options *common.MigrationOptions) error {
func (m *Pre2021Migrator) IsMigrated() (bool, error) {
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(m.config.DBTimeoutSeconds)*time.Second)
defer cancel()
return common.TableExists(ctx, m.db, nil, "DBPREFIXdatabase_version", &m.config.SQLConfig)
var sqlConfig config.SQLConfig
if m.IsMigratingInPlace() {
sqlConfig = config.GetSQLConfig()
} else {
sqlConfig = m.config.SQLConfig
}
return common.TableExists(ctx, m.db, nil, "DBPREFIXdatabase_version", &sqlConfig)
}
func (m *Pre2021Migrator) MigrateDB() (bool, error) {
@ -74,13 +80,12 @@ func (m *Pre2021Migrator) MigrateDB() (bool, error) {
}
if err := m.MigrateBoards(); err != nil {
errEv.Caller().Err(err).Msg("Failed to migrate boards")
return false, err
}
common.LogInfo().Msg("Migrated boards successfully")
// if err = m.MigratePosts(); err != nil {
// return false, err
// }
if err = m.MigratePosts(); err != nil {
return false, err
}
// if err = m.MigrateStaff("password"); err != nil {
// return false, err
// }

View file

@ -49,7 +49,7 @@ func (p *Post) nextFileOrder() (int, error) {
return next, err
}
func (p *Post) AttachFile(upload *Upload) error {
func (p *Post) AttachFileTx(tx *sql.Tx, upload *Upload) error {
if upload == nil {
return nil // no upload to attach, so no error
}
@ -69,38 +69,28 @@ func (p *Post) AttachFile(upload *Upload) error {
if upload.ID > 0 {
return ErrAlreadyAttached
}
tx, err := BeginTx()
if err != nil {
return err
}
defer tx.Rollback()
stmt, err := PrepareSQL(insertSQL, tx)
if err != nil {
return err
}
defer stmt.Close()
if upload.FileOrder < 1 {
upload.FileOrder, err = p.nextFileOrder()
if err != nil {
return err
}
}
upload.PostID = p.ID
if _, err = stmt.Exec(
if _, err = ExecTxSQL(tx, insertSQL,
&upload.PostID, &upload.FileOrder, &upload.OriginalFilename, &upload.Filename, &upload.Checksum, &upload.FileSize,
&upload.IsSpoilered, &upload.ThumbnailWidth, &upload.ThumbnailHeight, &upload.Width, &upload.Height,
); err != nil {
return err
}
if upload.ID, err = getLatestID("DBPREFIXfiles", tx); err != nil {
upload.ID, err = getLatestID("DBPREFIXfiles", tx)
return err
}
func (p *Post) AttachFile(upload *Upload) error {
tx, err := BeginTx()
if err != nil {
return err
}
if err = tx.Commit(); err != nil {
defer tx.Rollback()
if err = p.AttachFileTx(tx, upload); err != nil {
return err
}
return stmt.Close()
return tx.Commit()
}
// GetUploadFilenameAndBoard returns the filename (or an empty string) and