Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deleting all enums in migration causes fatal error #456

Open
corymosiman12 opened this issue Sep 16, 2021 · 0 comments
Open

Deleting all enums in migration causes fatal error #456

corymosiman12 opened this issue Sep 16, 2021 · 0 comments
Labels
bug Something isn't working

Comments

@corymosiman12
Copy link

corymosiman12 commented Sep 16, 2021

Describe the bug

Attempting to remove all enum data as part of a migration causes a fatal error when running vapor run migrate --revert

To Reproduce

Forward migration works as expected. Revert migration is causing issue:

struct AddEnumDataMigration: Migration {
    func prepare(on db: Database) -> EventLoopFuture<Void> {
        let data = [
            _addActorTypeEnums(on: db),
            _addUnitCategoryEnums(on: db),
            _addUnitEnums(on: db)
        ]
        return EventLoopFuture.andAllSucceed(data, on: db.eventLoop)
    }

    func revert(on db: Database) -> EventLoopFuture<Void> {
        let data = [
            db.enum(ActorType.name.description).delete(),
            db.enum(UnitCategory.name.description).delete(),
            db.enum(Unit.name.description).delete()
        ]
        
        return EventLoopFuture.andAllSucceed(data, on: db.eventLoop)
    }
}

func _addActorTypeEnums(on db: Database) -> EventLoopFuture<Void> {
    var enumBuilder = db.enum(ActorType.name.description)
    for option in ActorType.allCases {
        enumBuilder = enumBuilder.case(option.rawValue)
    }
    return enumBuilder.create().transform(to: ())
}

func _addUnitCategoryEnums(on db: Database) -> EventLoopFuture<Void> {
    var enumBuilder = db.enum(UnitCategory.name.description)
    for option in UnitCategory.allCases {
        enumBuilder = enumBuilder.case(option.rawValue)
    }
    return enumBuilder.create().transform(to: ())
    
}

func _addUnitEnums(on db: Database) -> EventLoopFuture<Void> {
    var enumBuilder = db.enum(Unit.name.description)
    for option in Unit.allCases {
        enumBuilder = enumBuilder.case(option.rawValue)
    }
    return enumBuilder.create().transform(to: ())
    
}

I wrap everything in EventLoopFuture.andAllSucceed so I know that sets of migrations work. Running this forward works as expected. However, running vapor run migrate --revert gets me into trouble. I get one of the two following errors:

[ WARNING ] server: table "_fluent_enums" does not exist (DropErrorMsgNonExistent)
PostgresNIO/PSQLConnection.swift:110: Assertion failed: PostgresConnection deinitialized before being closed.
[ WARNING ] server: table "_fluent_enums" does not exist (DropErrorMsgNonExistent)
Swift/ErrorType.swift:200: Fatal error: Error raised at top level: server: table "_fluent_enums" does not exist (DropErrorMsgNonExistent)

Running in debug mode, here is the full extent of the output:

[ DEBUG ] query read _fluent_migrations limits=[count(1)] [database-id: psql] (FluentKit/Query/Builder/QueryBuilder.swift:291)
[ DEBUG ] SELECT "_fluent_migrations"."id" AS "_fluent_migrations_id", "_fluent_migrations"."name" AS "_fluent_migrations_name", "_fluent_migrations"."batch" AS "_fluent_migrations_batch", "_fluent_migrations"."created_at" AS "_fluent_migrations_created_at", "_fluent_migrations"."updated_at" AS "_fluent_migrations_updated_at" FROM "_fluent_migrations" ORDER BY "_fluent_migrations"."batch" DESC LIMIT 1 [] [database-id: psql] (FluentPostgresDriver/FluentPostgresDatabase.swift:29)
[ DEBUG ] No available connections on this event loop, creating a new one [database-id: psql] (AsyncKit/ConnectionPool/EventLoopConnectionPool.swift:202)
[ DEBUG ] query read _fluent_migrations filters=[_fluent_migrations[batch] = 1] [database-id: psql] (FluentKit/Query/Builder/QueryBuilder.swift:291)
[ DEBUG ] SELECT "_fluent_migrations"."id" AS "_fluent_migrations_id", "_fluent_migrations"."name" AS "_fluent_migrations_name", "_fluent_migrations"."batch" AS "_fluent_migrations_batch", "_fluent_migrations"."created_at" AS "_fluent_migrations_created_at", "_fluent_migrations"."updated_at" AS "_fluent_migrations_updated_at" FROM "_fluent_migrations" WHERE "_fluent_migrations"."batch" = $1 [1] [database-id: psql] (FluentPostgresDriver/FluentPostgresDatabase.swift:29)
[ DEBUG ] SQLDropEnum(name: SQLKit.SQLIdentifier(string: "ActorType"), ifExists: false, cascade: false) [database-id: psql] (FluentPostgresDriver/FluentPostgresDatabase.swift:77)
[ DEBUG ] SQLDropEnum(name: SQLKit.SQLIdentifier(string: "UnitCategory"), ifExists: false, cascade: false) [database-id: psql] (FluentPostgresDriver/FluentPostgresDatabase.swift:77)
[ DEBUG ] Connection pool exhausted on this event loop, adding request to waitlist [database-id: psql] (AsyncKit/ConnectionPool/EventLoopConnectionPool.swift:207)
[ DEBUG ] SQLDropEnum(name: SQLKit.SQLIdentifier(string: "Unit"), ifExists: false, cascade: false) [database-id: psql] (FluentPostgresDriver/FluentPostgresDatabase.swift:77)
[ DEBUG ] Connection pool exhausted on this event loop, adding request to waitlist [database-id: psql] (AsyncKit/ConnectionPool/EventLoopConnectionPool.swift:207)
[ DEBUG ] Fulfilling connection waitlist request [database-id: psql] (AsyncKit/ConnectionPool/EventLoopConnectionPool.swift:276)
[ DEBUG ] query delete _fluent_enums filters=[_fluent_enums[name] = "ActorType"] [database-id: psql] (FluentKit/Query/Builder/QueryBuilder.swift:291)
[ DEBUG ] DELETE FROM "_fluent_enums" WHERE "_fluent_enums"."name" = $1 ["ActorType"] [database-id: psql] (FluentPostgresDriver/FluentPostgresDatabase.swift:29)
[ DEBUG ] Connection pool exhausted on this event loop, adding request to waitlist [database-id: psql] (AsyncKit/ConnectionPool/EventLoopConnectionPool.swift:207)
[ DEBUG ] Fulfilling connection waitlist request [database-id: psql] (AsyncKit/ConnectionPool/EventLoopConnectionPool.swift:276)
[ DEBUG ] query delete _fluent_enums filters=[_fluent_enums[name] = "UnitCategory"] [database-id: psql] (FluentKit/Query/Builder/QueryBuilder.swift:291)
[ DEBUG ] DELETE FROM "_fluent_enums" WHERE "_fluent_enums"."name" = $1 ["UnitCategory"] [database-id: psql] (FluentPostgresDriver/FluentPostgresDatabase.swift:29)
[ DEBUG ] Connection pool exhausted on this event loop, adding request to waitlist [database-id: psql] (AsyncKit/ConnectionPool/EventLoopConnectionPool.swift:207)
[ DEBUG ] Fulfilling connection waitlist request [database-id: psql] (AsyncKit/ConnectionPool/EventLoopConnectionPool.swift:276)
[ DEBUG ] query delete _fluent_enums filters=[_fluent_enums[name] = "Unit"] [database-id: psql] (FluentKit/Query/Builder/QueryBuilder.swift:291)
[ DEBUG ] DELETE FROM "_fluent_enums" WHERE "_fluent_enums"."name" = $1 ["Unit"] [database-id: psql] (FluentPostgresDriver/FluentPostgresDatabase.swift:29)
[ DEBUG ] Connection pool exhausted on this event loop, adding request to waitlist [database-id: psql] (AsyncKit/ConnectionPool/EventLoopConnectionPool.swift:207)
[ DEBUG ] Fulfilling connection waitlist request [database-id: psql] (AsyncKit/ConnectionPool/EventLoopConnectionPool.swift:276)
[ DEBUG ] query aggregate(count(_fluent_enums[id])) _fluent_enums [database-id: psql] (FluentKit/Query/Builder/QueryBuilder.swift:291)
[ DEBUG ] SELECT COUNT("_fluent_enums"."id") AS "aggregate" FROM "_fluent_enums" [] [database-id: psql] (FluentPostgresDriver/FluentPostgresDatabase.swift:29)
[ DEBUG ] Connection pool exhausted on this event loop, adding request to waitlist [database-id: psql] (AsyncKit/ConnectionPool/EventLoopConnectionPool.swift:207)
[ DEBUG ] Fulfilling connection waitlist request [database-id: psql] (AsyncKit/ConnectionPool/EventLoopConnectionPool.swift:276)
[ DEBUG ] query aggregate(count(_fluent_enums[id])) _fluent_enums [database-id: psql] (FluentKit/Query/Builder/QueryBuilder.swift:291)
[ DEBUG ] SELECT COUNT("_fluent_enums"."id") AS "aggregate" FROM "_fluent_enums" [] [database-id: psql] (FluentPostgresDriver/FluentPostgresDatabase.swift:29)
[ DEBUG ] Connection pool exhausted on this event loop, adding request to waitlist [database-id: psql] (AsyncKit/ConnectionPool/EventLoopConnectionPool.swift:207)
[ DEBUG ] Fulfilling connection waitlist request [database-id: psql] (AsyncKit/ConnectionPool/EventLoopConnectionPool.swift:276)
[ DEBUG ] query aggregate(count(_fluent_enums[id])) _fluent_enums [database-id: psql] (FluentKit/Query/Builder/QueryBuilder.swift:291)
[ DEBUG ] SELECT COUNT("_fluent_enums"."id") AS "aggregate" FROM "_fluent_enums" [] [database-id: psql] (FluentPostgresDriver/FluentPostgresDatabase.swift:29)
[ DEBUG ] Connection pool exhausted on this event loop, adding request to waitlist [database-id: psql] (AsyncKit/ConnectionPool/EventLoopConnectionPool.swift:207)
[ DEBUG ] DROP TABLE "_fluent_enums" [] [database-id: psql] (FluentPostgresDriver/FluentPostgresDatabase.swift:43)
[ DEBUG ] Connection pool exhausted on this event loop, adding request to waitlist [database-id: psql] (AsyncKit/ConnectionPool/EventLoopConnectionPool.swift:207)
[ DEBUG ] Fulfilling connection waitlist request [database-id: psql] (AsyncKit/ConnectionPool/EventLoopConnectionPool.swift:276)
[ DEBUG ] DROP TABLE "_fluent_enums" [] [database-id: psql] (FluentPostgresDriver/FluentPostgresDatabase.swift:43)
[ DEBUG ] Connection pool exhausted on this event loop, adding request to waitlist [database-id: psql] (AsyncKit/ConnectionPool/EventLoopConnectionPool.swift:207)
[ DEBUG ] Fulfilling connection waitlist request [database-id: psql] (AsyncKit/ConnectionPool/EventLoopConnectionPool.swift:276)
[ DEBUG ] DROP TABLE "_fluent_enums" [] [database-id: psql] (FluentPostgresDriver/FluentPostgresDatabase.swift:43)
[ DEBUG ] Connection pool exhausted on this event loop, adding request to waitlist [database-id: psql] (AsyncKit/ConnectionPool/EventLoopConnectionPool.swift:207)
[ DEBUG ] Fulfilling connection waitlist request [database-id: psql] (AsyncKit/ConnectionPool/EventLoopConnectionPool.swift:276)
[ DEBUG ] Fulfilling connection waitlist request [database-id: psql] (AsyncKit/ConnectionPool/EventLoopConnectionPool.swift:276)
[ DEBUG ] Fulfilling connection waitlist request [database-id: psql] (AsyncKit/ConnectionPool/EventLoopConnectionPool.swift:276)
[ WARNING ] server: table "_fluent_enums" does not exist (DropErrorMsgNonExistent) (Vapor/Application.swift:102)
[ DEBUG ] Application shutting down (Vapor/Application.swift:126)
[ DEBUG ] Connection pool shutting down, closing each event loop's storage (AsyncKit/ConnectionPool/EventLoopGroupConnectionPool.swift:177)
Swift/ErrorType.swift:200: Fatal error: Error raised at top level: server: table "_fluent_enums" does not exist (DropErrorMsgNonExistent)

If I understand the logic here correctly, it looks like after it deletes things from the enum table, it checks whether there is any more data in the enum table, then tries to delete the table if there is no data. my guess here is that the deletes for all three execute first, then each counts the number of items in the DB (all get 0), then they all try to delete the table (which only one does successfully, then failure).

Expected behavior

A WARNING is raised when attempting to delete a table that doesn't exist, so my expectation is that a fatal error should not occur.

Environment

  • Vapor Framework version: 4.48.5
  • Vapor Toolbox version: 18.3.3
  • ProductName: macOS
  • ProductVersion: 11.5.2
  • BuildVersion: 20G95
@corymosiman12 corymosiman12 added the bug Something isn't working label Sep 16, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

1 participant