database migration: track previosu travelynx version; offer rollback hints

This commit is contained in:
Daniel Friesel 2022-12-12 22:35:08 +01:00
parent 2f7669a520
commit 4b37560640
No known key found for this signature in database
GPG key ID: 100D5BFB5166E005

View file

@ -1198,6 +1198,20 @@ my @migrations = (
} }
); );
}, },
# v28 -> v29
# add pre-migration travelynx version. This way, a failed migration can
# print a helpful "git checkout" command.
sub {
my ($db) = @_;
$db->query(
qq{
alter table schema_version
add column travelynx varchar(64);
update schema_version set version = 29;
}
);
},
); );
sub sync_stations { sub sync_stations {
@ -1393,27 +1407,56 @@ sub setup_db {
} }
} }
sub failure_hints {
my ($old_version) = @_;
say STDERR 'This travelynx instance has reached an undefined state:';
say STDERR
'The source code is expecting a different schema version than present in the database.';
say STDERR
'Please file a detailed bug report at <https://github.com/derf/travelynx/issues>';
say STDERR 'or send an e-mail to derf+travelynx@finalrewind.org.';
if ($old_version) {
say STDERR '';
say STDERR
"The last migration was performed with travelynx v${old_version}.";
say STDERR
'You may be able to return to a working state with the following command:';
say STDERR "git checkout ${old_version}";
say STDERR '';
say STDERR 'We apologize for any inconvenience.';
}
}
sub migrate_db { sub migrate_db {
my ($db) = @_; my ( $self, $db ) = @_;
my $tx = $db->begin; my $tx = $db->begin;
my $schema_version = get_schema_version($db); my $schema_version = get_schema_version($db);
say "Found travelynx schema v${schema_version}"; say "Found travelynx schema v${schema_version}";
my $old_version;
if ( $schema_version >= 29 ) {
$old_version = get_schema_version( $db, 'travelynx' );
}
if ( $schema_version == @migrations ) { if ( $schema_version == @migrations ) {
say 'Database layout is up-to-date'; say 'Database layout is up-to-date';
} }
else {
eval { eval {
for my $i ( $schema_version .. $#migrations ) { for my $i ( $schema_version .. $#migrations ) {
printf( "Updating to v%d ...\n", $i + 1 ); printf( "Updating to v%d ...\n", $i + 1 );
$migrations[$i]($db); $migrations[$i]($db);
}
say 'Update complete.';
};
if ($@) {
say STDERR "Migration failed: $@";
say STDERR "Rolling back to v${schema_version}";
failure_hints($old_version);
exit(1);
} }
};
if ($@) {
say STDERR "Migration failed: $@";
say STDERR "Rolling back to v${schema_version}";
exit(1);
} }
my $iris_version = get_schema_version( $db, 'iris' ); my $iris_version = get_schema_version( $db, 'iris' );
@ -1426,16 +1469,24 @@ sub migrate_db {
say say
"Synchronizing with Travel::Status::DE::IRIS $Travel::Status::DE::IRIS::Stations::VERSION"; "Synchronizing with Travel::Status::DE::IRIS $Travel::Status::DE::IRIS::Stations::VERSION";
sync_stations( $db, $iris_version ); sync_stations( $db, $iris_version );
say 'Synchronization complete.';
}; };
if ($@) { if ($@) {
say STDERR "Synchronization failed: $@"; say STDERR "Synchronization failed: $@";
say STDERR "Rolling back to v${schema_version}"; if ( $schema_version != @migrations ) {
say STDERR "Rolling back to v${schema_version}";
failure_hints($old_version);
}
exit(1); exit(1);
} }
} }
$db->update( 'schema_version',
{ travelynx => $self->app->config->{version} } );
if ( get_schema_version($db) == @migrations ) { if ( get_schema_version($db) == @migrations ) {
$tx->commit; $tx->commit;
say 'Changes committed to database. Have a nice day.';
} }
else { else {
printf STDERR ( printf STDERR (
@ -1444,6 +1495,8 @@ sub migrate_db {
get_schema_version($db) get_schema_version($db)
); );
say STDERR "Rolling back to v${schema_version}"; say STDERR "Rolling back to v${schema_version}";
say STDERR "";
failure_hints($old_version);
exit(1); exit(1);
} }
} }
@ -1462,7 +1515,7 @@ sub run {
if ( not defined get_schema_version($db) ) { if ( not defined get_schema_version($db) ) {
setup_db($db); setup_db($db);
} }
migrate_db($db); $self->migrate_db($db);
} }
elsif ( $command eq 'has-current-schema' ) { elsif ( $command eq 'has-current-schema' ) {
if ( get_schema_version($db) == @migrations if ( get_schema_version($db) == @migrations