Skip to content

Commit

Permalink
fix migration logic
Browse files Browse the repository at this point in the history
  • Loading branch information
umputun committed Dec 31, 2024
1 parent cbc9baa commit 7f58038
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 37 deletions.
3 changes: 2 additions & 1 deletion .dockerignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
data/ham-dynamic.txt
data/spam-dynamic.txt
data/tg-spam.db*
docker-compose*.yml
docker-compose*.yml
var/
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,5 @@ tg-spam.db-wal
logs/
site/public/
_examples/simplechat/messages.db
*.loaded
*.loaded
var/
30 changes: 15 additions & 15 deletions app/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -198,8 +198,8 @@ func execute(ctx context.Context, opts options) error {
log.Print("[WARN] dry mode, no actual bans")
}

concertOnly := opts.Convert == "only"
if !opts.Server.Enabled && !concertOnly && (opts.Telegram.Token == "" || opts.Telegram.Group == "") {
convertOnly := opts.Convert == "only"
if !opts.Server.Enabled && !convertOnly && (opts.Telegram.Token == "" || opts.Telegram.Group == "") {
return errors.New("telegram token and group are required")
}

Expand All @@ -220,6 +220,16 @@ func execute(ctx context.Context, opts options) error {
// make detector with all sample files loaded
detector := makeDetector(opts)

// make spam bot
spamBot, err := makeSpamBot(ctx, opts, dataDB, detector)
if err != nil {
return fmt.Errorf("can't make spam bot, %w", err)
}
if opts.Convert == "only" {
log.Print("[WARN] convert only mode, converting text samples and exit")
return nil
}

// make store and load approved users
approvedUsersStore, auErr := storage.NewApprovedUsers(ctx, dataDB)
if auErr != nil {
Expand All @@ -232,16 +242,6 @@ func execute(ctx context.Context, opts options) error {
}
log.Printf("[DEBUG] approved users from: %s, loaded: %d", dbFile, count)

// make spam bot
spamBot, err := makeSpamBot(ctx, opts, dataDB, detector)
if err != nil {
return fmt.Errorf("can't make spam bot, %w", err)
}
if opts.Convert == "only" {
log.Print("[WARN] convert only mode, converting text samples and exit")
return nil
}

// make locator
locator, err := storage.NewLocator(ctx, opts.HistoryDuration, opts.HistoryMinSize, dataDB)
if err != nil {
Expand Down Expand Up @@ -370,9 +370,9 @@ func activateServer(ctx context.Context, opts options, sf *bot.SpamFilter, loc *
}

// make store and load approved users
detectedSpamStore, auErr := storage.NewDetectedSpam(ctx, db)
if auErr != nil {
return fmt.Errorf("can't make approved users store, %w", auErr)
detectedSpamStore, dsErr := storage.NewDetectedSpam(ctx, db)
if dsErr != nil {
return fmt.Errorf("can't make detected spam store, %w", dsErr)
}

settings := webapi.Settings{
Expand Down
28 changes: 18 additions & 10 deletions app/storage/approved_users.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,19 +46,27 @@ func NewApprovedUsers(ctx context.Context, db *Engine) (*ApprovedUsers, error) {
return nil, fmt.Errorf("db connection is nil")
}

// create schema in a single transaction
tx, err := db.Begin()
var exists int
err := db.Get(&exists, "SELECT COUNT(*) FROM sqlite_master WHERE type='table' AND name='approved_users'")
if err != nil {
return nil, fmt.Errorf("failed to start transaction: %w", err)
return nil, fmt.Errorf("failed to check for approved_users table existence: %w", err)
}
defer tx.Rollback()

if _, err = tx.ExecContext(ctx, approvedUsersSchema); err != nil {
return nil, fmt.Errorf("failed to create schema: %w", err)
}
// create schema in a single transaction if the table does not exist
if exists == 0 {
tx, err := db.Begin()
if err != nil {
return nil, fmt.Errorf("failed to start transaction: %w", err)
}
defer tx.Rollback()

if err = tx.Commit(); err != nil {
return nil, fmt.Errorf("failed to commit transaction: %w", err)
if _, err = tx.ExecContext(ctx, approvedUsersSchema); err != nil {
return nil, fmt.Errorf("failed to create schema: %w", err)
}

if err = tx.Commit(); err != nil {
return nil, fmt.Errorf("failed to commit transaction: %w", err)
}
}

if err := migrateTable(&db.DB, db.GID()); err != nil {
Expand Down Expand Up @@ -208,7 +216,7 @@ func migrateTable(db *sqlx.DB, gid string) error {
if err := tx.Commit(); err != nil {
return fmt.Errorf("failed to commit migration: %w", err)
}
log.Printf("[DEBUG] approved_users table migrated")
log.Printf("[DEBUG] approved_users table migrated, records: %d", len(rows))

return nil
}
36 changes: 26 additions & 10 deletions app/storage/detected_spam.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,20 +54,31 @@ func NewDetectedSpam(ctx context.Context, db *Engine) (*DetectedSpam, error) {
return nil, fmt.Errorf("db connection is nil")
}

tx, err := db.Begin()
// first check if the table exists. we can't do this in a transaction
// because missing columns will cause the transaction to fail
var exists int
err := db.Get(&exists, "SELECT COUNT(*) FROM sqlite_master WHERE type='table' AND name='detected_spam'")
if err != nil {
return nil, fmt.Errorf("failed to start transaction: %w", err)
return nil, fmt.Errorf("failed to check for detected_spam table existence: %w", err)
}
defer tx.Rollback()

if _, err = tx.ExecContext(ctx, detectedSpamSchema); err != nil {
return nil, fmt.Errorf("failed to create schema: %w", err)
}
if exists == 0 { // table does not exist, create it
tx, err := db.Begin()
if err != nil {
return nil, fmt.Errorf("failed to start transaction: %w", err)
}
defer tx.Rollback()

if _, err = tx.ExecContext(ctx, detectedSpamSchema); err != nil {
return nil, fmt.Errorf("failed to create schema: %w", err)
}

if err = tx.Commit(); err != nil {
return nil, fmt.Errorf("failed to commit transaction: %w", err)
if err = tx.Commit(); err != nil {
return nil, fmt.Errorf("failed to commit transaction: %w", err)
}
}

// migrate detected_spam table
if err := migrateDetectedSpam(&db.DB, db.GID()); err != nil {
return nil, fmt.Errorf("failed to migrate detected_spam: %w", err)
}
Expand Down Expand Up @@ -151,10 +162,15 @@ func migrateDetectedSpam(db *sqlx.DB, gid string) error {
}

// update existing records with the provided gid
if _, err = db.Exec("UPDATE detected_spam SET gid = ? WHERE gid = ''", gid); err != nil {
res, err := db.Exec("UPDATE detected_spam SET gid = ? WHERE gid = ''", gid)
if err != nil {
return fmt.Errorf("failed to update gid for existing records: %w", err)
}
rowsAffected, err := res.RowsAffected()
if err != nil {
return fmt.Errorf("failed to get rows affected: %w", err)
}

log.Printf("[DEBUG] detected_spam table migrated, gid updated to %q", gid)
log.Printf("[DEBUG] detected_spam table migrated, gid updated to %q, records: %d", gid, rowsAffected)
return nil
}

0 comments on commit 7f58038

Please sign in to comment.