Skip to content

v4.1.0 — resilience

Choose a tag to compare

@ejosterberg ejosterberg released this 26 Jul 05:14

A resilience release. Everything here came out of real installs run by real people this week — a power loss that looked like total data loss, a Docker deployment with no way to run the radio bridge, and a database table that existed in two incompatible shapes at once.

Upgrading is a git pull. If you cloned the repository, that is the whole update:

git pull
php sql/run_migrations.php

Docker installs need the rebuild step too — a pull alone does not update a running container:

git pull && docker compose up -d --build

Two schema-normalizing migrations are included. Both are idempotent, neither deletes a row, and both report anything they cannot safely decide rather than guessing. Back up first anyway — and after this release, that is one command.

Added

Automatic backups, on by default. A daily backup now runs on its own. No setup, no scheduler required — though it also works from cron or Windows Task Scheduler via tools/backup_run.php. Interval, retention and destination are configurable, and a warning appears if there has been no recent verified backup.

Backups are verified, not assumed. Every archive is reopened and checked to contain a real database dump before it counts as a success. A backup that silently produced an empty file is not a backup.

A restore tool — tools/restore.php. There previously was no supported way to restore one. It is dry-run by default, verifies the archive before touching anything, and takes a safety backup of the current database first — so restoring the wrong file is itself undoable.

restore.php --drill — prove a backup restores. Restores a backup into a throwaway database, reports how many tables and rows came back next to what is live, then drops it. Your real database is only read. Untested backups are the ones that fail when you need them; this is how you stop having untested backups.

Docker deployment for the DMR bridgeservices/dvswitch/docker/ and docs/RADIO-DMR-DOCKER.md. Runs the bridge and its AMBE vocoder together in one container, configured entirely by environment variables, with no systemd required. It refuses to start if the vocoder is not answering — a bridge with a dead vocoder otherwise connects normally and transmits silence, which is a miserable thing to debug from the receiving end.

A getting-started guide for beginners — what TicketsCAD is, how to open it, the address-versus-folder gotcha, and free links for learning the command line, Docker and git.

Fixed

A damaged database table no longer looks like an empty list. After an unclean shutdown, a single unreadable table could make a whole screen render empty — which reads as "my data is gone" when the records are safe on disk. Affected screens now say which table is damaged, that the data is likely recoverable, and where the repair steps are.

Teams could exist with no name, and on some installs the Teams screen would not load or save. The teams table had two competing definitions, so the columns an install ended up with depended on the order the setup scripts ran — and the built-in seed wrote to columns that later became read-only, which is where the four unnamed teams came from. There is now one canonical definition, and sql/run_teams_schema_normalize.php brings any install onto it.

The same hazard is now impossible. member, member_types, member_status and constituents were each defined by two different files as well. All are consolidated, and a test now fails the build if any table is ever defined twice again.

MySQL troubleshooting for two situations that each cost a user an evening: MySQL not starting or not staying running, and recovering a crashed table after a power loss. See docs/TROUBLESHOOTING.md.

Docker updates now say plainly that git pull alone does not update a running container.

Keeping up to date

TicketsCAD is developed in the open and fixes land continuously. If you clone with git, staying current is git pull — you get documentation corrections and small fixes as they happen, without waiting for a tagged release. Two short walkthroughs if you have not used git before:

Full changelog: CHANGELOG.md