Skip to content

Abort a course archive when the database dump actually fails#3042

Open
drdrew42 wants to merge 1 commit into
openwebwork:WeBWorK-2.21from
drdrew42:bugfix/archive-dump-failure-not-silent
Open

Abort a course archive when the database dump actually fails#3042
drdrew42 wants to merge 1 commit into
openwebwork:WeBWorK-2.21from
drdrew42:bugfix/archive-dump-failure-not-silent

Conversation

@drdrew42

@drdrew42 drdrew42 commented Jul 7, 2026

Copy link
Copy Markdown
Member

Description:

Problem

A failed database dump produces a "successful" archive with no database. Because WeBWorK::DB::dump_tables and NewSQL::Std::dump_table both return 1 unconditionally, archiveCourse's existing guard —

  my $dump_db_result = $db->dump_tables($dump_dir);
  unless ($dump_db_result) { ...; croak "$courseID: course database dump failed.\n"; }

— never fires. Any mysqldump failure (wrong mysqldump path, auth failure, disk full, a MariaDB column-statistics incompatibility, …) is swallowed with only a warn to the server log, and the archive is written anyway. The empty database is discovered only later, when the archive is unarchived and no tables are restored.

Fix

Make the failure propagate:

  • dump_table returns 0 when mysqldump exits non-zero.
  • dump_tables aggregates the per-table results and returns false if any table's dump
    failed, so archiveCourse aborts instead of writing a DB-less archive.

The existing tolerance for courses created with an earlier version of WeBWorK (which may predate some tables) is preserved: dump_tables skips tables that don't exist (via tableExists) rather than counting them as failures, so only a genuine mysqldump error aborts the archive. Because absent tables now produce no dump file, restore_tables skips missing dump files instead of restoring from a nonexistent path.

Scope note

This intentionally does not change the restore side to abort on failure — restore_tables/restore_table still return success and only warn, matching current behavior where a partial restore is preferred over none. Only the missing-file skip was added there, as a direct consequence of no longer dumping absent tables.

Testing

  • Point $externalPrograms{mysqldump} at a nonexistent path (or otherwise break the dump,
    e.g. a mysqldump that rejects --column-statistics against MariaDB) and archive a course.
    • Before: archive completes "successfully"; the .tar.gz has an empty/absent
      DATA/mysqldump, and a later unarchive restores no tables.
    • After: archiveCourse dies with course database dump failed. and no archive is left behind.
  • Regression: archive a normal current course — all tables dump and the archive is byte-for-byte
    equivalent to before.
  • Regression: archive a course missing a newer table — that table is skipped (no longer a warn),
    the rest dump, and the archive succeeds.

dump_tables() and NewSQL::Std::dump_table() unconditionally returned 1, so
archiveCourse()'s `unless ($dump_db_result) { croak }` guard never fired. A
mysqldump failure (wrong mysqldump path, auth failure, disk full, a MariaDB
column-statistics incompatibility, ...) therefore produced a "successful"
archive whose database was empty or missing -- discovered only later, when the
archive was unarchived and no tables were restored.

Make the failure propagate:

- dump_table() returns 0 when mysqldump exits non-zero.
- dump_tables() aggregates the per-table results and returns false if any
  table's dump failed, so archiveCourse() aborts instead of writing a DB-less
  archive.

Preserve the existing tolerance for courses created with an earlier version of
WeBWorK that predate some tables: dump_tables() skips tables that do not exist
(via tableExists) rather than treating them as failures, so only a genuine
mysqldump error aborts the archive. Because absent tables now produce no dump
file, restore_tables() skips missing dump files instead of restoring from a
nonexistent path.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@drdrew42 drdrew42 force-pushed the bugfix/archive-dump-failure-not-silent branch from 6c0e5eb to c395ca7 Compare July 7, 2026 21:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant