mirror of
https://github.com/alexbelgium/hassio-addons.git
synced 2026-10-24 17:00:10 +02:00
fix(wger): arm the import guard up front instead of on each failure path
A refused prerequisite short-circuited the guard. With PS_DATABASE_URI set to a Postgres URI but PS_STORAGE_PG_URI missing - exactly the mistake the refusal messages exist to catch - prepare() returned before import_sqlite_data() ever ran, so no marker was written, the boot continued, and the upstream entrypoint bootstrapped the empty Postgres database into a new instance. From the next start the target held users, the import was skipped for good, and the SQLite rows were stranded. Reproduced before fixing: marker absent, boot would proceed. The marker is now armed as soon as an import is pending rather than written on each way out, so anything that stops this script leaves it in place, including an error nobody anticipated. Only two paths clear it: a completed import, and a target that already holds data. Also cleared when there is no SQLite database to move. It is armed only when Django is actually about to use Postgres and there is something to move, so it cannot block a boot that was never at risk. Verified across both axes: armed for a refused prerequisite, a failed dumpdata, a failed loaddata and an unreachable database; cleared for a successful import, an already-populated target, the feature switched off, PS_DATABASE_URI unset or pointing at SQLite, and no SQLite file present. Also narrow the claim in the README and CHANGELOG. The test is User.objects.exists() and nothing more, so a Postgres database holding rows but no users at all still counts as never set up and would be imported into. Saying it "never overwrites what is already there" was broader than the code. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
## 2.8.0-dev.1.2 (2026-10-17)
|
||||
|
||||
- Add optional PowerSync support, so the official wger mobile app (2.0.3 and newer) can sync offline (#2950). Set the new `POWERSYNC_ENABLED` option to start a PowerSync service inside the add-on, reached at `<SITE_URL>/ps/` through the add-on's own nginx, exactly as upstream's docker deployment serves it.
|
||||
- ⚠ PowerSync cannot replicate from SQLite, so enabling it means pointing wger at a Postgres database (for example the Postgres 17 add-on) with `PS_DATABASE_URI`. **The add-on copies your SQLite data across for you on the first start.** It never writes to the SQLite file — it reads a copy — and it only ever imports into a Postgres database with no user accounts, so turning PowerSync off and on again later never overwrites what is already there. The two databases do not stay in step afterwards: whichever one wger is pointed at is the live one. If the import cannot finish, the add-on refuses to start wger rather than let the empty Postgres database be set up as a new instance, which would make the SQLite data look unnecessary for ever after. Read the PowerSync section of the add-on documentation before switching.
|
||||
- ⚠ PowerSync cannot replicate from SQLite, so enabling it means pointing wger at a Postgres database (for example the Postgres 17 add-on) with `PS_DATABASE_URI`. **The add-on copies your SQLite data across for you on the first start.** It never writes to the SQLite file — it reads a copy — and it only ever imports into a Postgres database with no user accounts at all, which is wger's own test for a database that was never set up, so once your data is there turning PowerSync off and on again later imports nothing and leaves it alone. The two databases do not stay in step afterwards: whichever one wger is pointed at is the live one. If the import cannot finish, the add-on refuses to start wger rather than let the empty Postgres database be set up as a new instance, which would make the SQLite data look unnecessary for ever after. Read the PowerSync section of the add-on documentation before switching.
|
||||
- PowerSync settings can be supplied either through the add-on's `env_vars` option or through the `CONFIG_LOCATION` config.yaml file; both are read.
|
||||
- With `POWERSYNC_ENABLED` unset, the option defaults to off, no new process runs, no database is touched and the SQLite database stays the default. Two things are different even then, both harmless: a `/ps/` route left behind by an earlier enabled run is removed at startup, and nginx parses one additional `map` that nothing uses. The PowerSync files ship in the image either way, which makes it about 90 MB larger to download.
|
||||
|
||||
|
||||
@@ -77,10 +77,12 @@ SQLite database into the PostgreSQL one. Two things are guaranteed about that:
|
||||
`PS_DATABASE_URI` again puts wger straight back onto it — remove it from *everywhere*
|
||||
you set it, both the `env_vars` option and the `CONFIG_LOCATION` file, since either
|
||||
one takes precedence over the SQLite default.
|
||||
- **An import only ever happens into an empty PostgreSQL database.** "Empty" here means
|
||||
one with no user accounts at all, which is wger's own test for a database that was
|
||||
never set up. So if you turn PowerSync off and on again later, whatever is already in
|
||||
PostgreSQL is left alone and nothing is overwritten.
|
||||
- **An import only ever happens into a PostgreSQL database with no user accounts.** That
|
||||
is wger's own test for a database that was never set up, since its bootstrap creates
|
||||
the admin user as the very last step. So once your data is in PostgreSQL, turning
|
||||
PowerSync off and on again later imports nothing and leaves it alone. The test is that
|
||||
one and no more: a PostgreSQL database holding rows but no users at all — a half-built
|
||||
one, say — still counts as never set up and would be imported into.
|
||||
|
||||
What the import does not do is keep the two databases in step. After the switch,
|
||||
PostgreSQL is the live database and the SQLite file is a frozen copy of the moment you
|
||||
|
||||
@@ -67,6 +67,28 @@ fi
|
||||
|
||||
bashio::log.info "PowerSync is enabled"
|
||||
|
||||
# From here on the marker is armed rather than written on failure. Anything that stops
|
||||
# this script - a refused prerequisite, a failed import, an error nobody anticipated -
|
||||
# then leaves it in place, and the patched upstream entrypoint refuses to start wger.
|
||||
#
|
||||
# That is the fail-safe direction. Letting the boot continue is what loses the data: the
|
||||
# entrypoint would bootstrap the empty Postgres database into a new instance with its own
|
||||
# admin user, and from then on this script would see a database holding users and skip
|
||||
# the import for good. The rows would still be in the SQLite file, and the add-on would
|
||||
# never offer to move them again.
|
||||
#
|
||||
# It is armed only when Django is actually about to use Postgres and there is something
|
||||
# to move, so none of this applies to a database wger is not being pointed at. The two
|
||||
# places that clear it are a completed import and a target that already holds data.
|
||||
case "${PS_DATABASE_URI:-}" in
|
||||
postgres://* | postgresql://*)
|
||||
if [ -s "${DJANGO_DB_DATABASE:-/data/database.sqlite}" ]; then
|
||||
mkdir -p "$(dirname "$IMPORT_FAILED_MARKER")"
|
||||
touch "$IMPORT_FAILED_MARKER"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
#########################
|
||||
# Refuse bad prerequisites
|
||||
#########################
|
||||
@@ -260,6 +282,7 @@ import_sqlite_data() {
|
||||
|
||||
if [ ! -s "$sqlite_db" ]; then
|
||||
bashio::log.info "No SQLite database at $sqlite_db, nothing to import"
|
||||
rm -f "$IMPORT_FAILED_MARKER"
|
||||
return 0
|
||||
fi
|
||||
|
||||
@@ -279,6 +302,7 @@ import_sqlite_data() {
|
||||
|
||||
if [ "$state" = "populated" ]; then
|
||||
bashio::log.info "The Postgres database already holds wger data; leaving it as it is and importing nothing"
|
||||
rm -f "$IMPORT_FAILED_MARKER"
|
||||
return 0
|
||||
fi
|
||||
|
||||
@@ -341,23 +365,19 @@ import_sqlite_data() {
|
||||
fi
|
||||
|
||||
rm -rf "$IMPORT_DIR"
|
||||
rm -f "$IMPORT_FAILED_MARKER"
|
||||
bashio::log.info "Import finished. wger is now running on Postgres; $sqlite_db is left behind unchanged in case you want to go back"
|
||||
return 0
|
||||
}
|
||||
|
||||
if ! prepare; then
|
||||
# The marker armed above is deliberately left in place; see the comment there.
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if ! import_sqlite_data; then
|
||||
# Letting the boot continue here is what loses the data: the upstream entrypoint
|
||||
# would bootstrap the empty Postgres database into a new instance, complete with its
|
||||
# own admin user, and from then on this script would see a database that holds users
|
||||
# and skip the import for good. So leave a marker the patched entrypoint checks, and
|
||||
# let the add-on fail to start with the reason in the log instead.
|
||||
bashio::log.error "PowerSync not started: the SQLite import did not complete, see above."
|
||||
bashio::log.error "wger will not be started, so that the empty Postgres database is not set up as a new instance and your SQLite data stays importable. Fix the cause, or remove PS_DATABASE_URI to go back to SQLite."
|
||||
touch "$IMPORT_FAILED_MARKER"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
|
||||
Reference in New Issue
Block a user