Skip to content
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 3 additions & 17 deletions migrate/migration.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (
"fmt"
"io"
"io/fs"
"sort"
"strings"
"text/template"
"time"
Expand Down Expand Up @@ -232,7 +231,7 @@ func (ms MigrationSlice) Applied() MigrationSlice {
applied = append(applied, ms[i])
}
}
sortDesc(applied)
SafeDescSort(applied)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems that MigrationSlice.Applied is no longer used internally in Bun?

return applied
}

Expand All @@ -245,7 +244,7 @@ func (ms MigrationSlice) Unapplied() MigrationSlice {
unapplied = append(unapplied, ms[i])
}
}
sortAsc(unapplied)
SafeAscSort(unapplied)
return unapplied
}

Expand Down Expand Up @@ -275,6 +274,7 @@ func (ms MigrationSlice) LastGroup() *MigrationGroup {
group.Migrations = append(group.Migrations, ms[i])
}
}

return group
}

Expand Down Expand Up @@ -321,17 +321,3 @@ func WithNopMigration() MigrationOption {
cfg.nop = true
}
}

//------------------------------------------------------------------------------

func sortAsc(ms MigrationSlice) {
sort.Slice(ms, func(i, j int) bool {
return ms[i].Name < ms[j].Name
})
}

func sortDesc(ms MigrationSlice) {
sort.Slice(ms, func(i, j int) bool {
return ms[i].Name > ms[j].Name
})
}
2 changes: 1 addition & 1 deletion migrate/migrations.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ func NewMigrations(opts ...MigrationsOption) *Migrations {
func (m *Migrations) Sorted() MigrationSlice {
migrations := make(MigrationSlice, len(m.ms))
copy(migrations, m.ms)
sortAsc(migrations)
SafeAscSort(migrations)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this is the only place where sorting needs to be applied, could we allow users to pass in a sorting function when calling it, making the parameter optional?

If we do that, we can store the sorting logic in the migrator, thereby avoiding the need to implement any locking-related logic.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a breaking change. You said you breaking changes weren't allowed...

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@j2gg0s do you mean passing as an option to NewMigrator? Because I don't think users ever call ms.Sorted directly so something like ms.SortedFunc(fn sort.Less) probably won't be that convenient.

Personally, I think having a package-level sorting is fine -- seems like something you'd only want to set once.

Re: maintenance, the overhead of that locking is immaterial + we needn't configure it for AutoMigrator separately.

wdyt?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ping @j2gg0s

return migrations
}

Expand Down
9 changes: 9 additions & 0 deletions migrate/migrator.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,15 @@ func WithTemplateData(data any) MigratorOption {
}
}

// WithSort overrides the default ascending sort function for all migrations.
// This affects all sorting operations in the entire migrate package.
func WithSort(ascSortFn, descSortFn MigrationSortFunc) {
sortMutex.Lock()
defer sortMutex.Unlock()
AscSort = ascSortFn
DescSort = descSortFn
}

type Migrator struct {
db *bun.DB
migrations *Migrations
Expand Down
49 changes: 49 additions & 0 deletions migrate/sort.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package migrate

import (
"sort"
"sync"
)

// MigrationSortFunc defines the signature for functions that sort migrations.
type MigrationSortFunc func(ms MigrationSlice)

// sortMutex protects access to the global sort functions.
var sortMutex sync.RWMutex

// Default sort implementations
var defaultAscSort MigrationSortFunc = func(ms MigrationSlice) {
sort.Slice(ms, func(i, j int) bool {
return ms[i].Name < ms[j].Name
})
}

var defaultDescSort MigrationSortFunc = func(ms MigrationSlice) {
sort.Slice(ms, func(i, j int) bool {
return ms[i].Name > ms[j].Name
})
}

// AscSort is the global ascending sort function.
// Default is to sort by migration name in ascending order.
// Can be overridden to use custom sorting logic.
var AscSort MigrationSortFunc = defaultAscSort

// DescSort is the global descending sort function.
// Default is to sort by migration name in descending order.
// Can be overridden to use custom sorting logic.
var DescSort MigrationSortFunc = defaultDescSort

// SafeAscSort applies the current ascending sort function in a thread-safe manner.
func SafeAscSort(ms MigrationSlice) {
sortMutex.RLock()
defer sortMutex.RUnlock()
AscSort(ms)
}

// SafeDescSort applies the current descending sort function in a thread-safe manner.
func SafeDescSort(ms MigrationSlice) {
sortMutex.RLock()
defer sortMutex.RUnlock()
DescSort(ms)
}
Loading