|
| 1 | +# Preparing a new data release |
| 2 | + |
| 3 | +FishBase and SeaLifeBase send `fbapp.7z` / `slbapp.7z` (7z-compressed |
| 4 | +`mysqldump` output) roughly annually. Publishing them is two commands: |
| 5 | + |
| 6 | +```bash |
| 7 | +# 1. drop the dumps in imports/ (git-ignored, excluded from the build), then |
| 8 | +bash data-raw/import_dumps.sh /tmp/fishbase-import |
| 9 | +# 2. read the verification summary, then publish (args are fb and slb versions) |
| 10 | +bash data-raw/upload.sh /tmp/fishbase-import 26.07 26.04 |
| 11 | +``` |
| 12 | + |
| 13 | +`import_dumps.sh` unpacks the dumps into a throwaway local MariaDB instance and |
| 14 | +calls `export_parquet.py`, which writes one zstd-compressed parquet file per |
| 15 | +table via DuckDB's `mysql` extension, then `verify_export.py`, which checks the |
| 16 | +result and exits non-zero if anything looks wrong. `upload.sh` publishes to |
| 17 | +Source Cooperative under `cboettig/fishbase/{fb,slb}/v<version>/parquet/`, |
| 18 | +which is what `fb_urls()` lists. |
| 19 | + |
| 20 | +Nothing in the R package needs to change to ship a release: |
| 21 | +`available_releases()` reads the bucket and `version = "latest"` picks the |
| 22 | +highest version present. |
| 23 | + |
| 24 | +Version tags encode the *snapshot date* of the dump (`v26.07` = July 2026). |
| 25 | +The two servers can carry different tags when their dumps arrive at different |
| 26 | +times, since releases are listed per server. |
| 27 | + |
| 28 | +Requires `p7zip-full`, `mariadb-server` (10.11+), `python3` with `duckdb`, and |
| 29 | +an `rclone` remote named `source` holding Source Cooperative credentials. |
| 30 | +Budget roughly 10 GB of scratch disk and an hour of wall clock. |
| 31 | + |
| 32 | +## What the verification covers |
| 33 | + |
| 34 | +`verify_export.py` compares every table's parquet row count against the source |
| 35 | +database, diffs the table list against the most recent release already on |
| 36 | +Source Cooperative, and checks that the two servers did not get crossed. Run |
| 37 | +it *before* uploading: it compares against whatever release is currently |
| 38 | +newest, so once you publish, the comparison baseline becomes the new release. |
| 39 | + |
| 40 | +## Notes and gotchas |
| 41 | + |
| 42 | +- The two dumps come from different MySQL versions (5.6 for `fbapp`, 8.0 for |
| 43 | + `slbapp`). MariaDB rejects MySQL 8's `utf8mb4_0900_ai_ci` collation, so the |
| 44 | + import rewrites it; only the data matters here, not collation semantics. |
| 45 | +- DuckDB's `mysql` ATTACH exposes *every* schema on the server, not just the |
| 46 | + one named in the connection string. `export_parquet.py` therefore filters on |
| 47 | + `schema_name` and fully qualifies each table — an unqualified `src."species"` |
| 48 | + silently resolves across databases and will mix FishBase and SeaLifeBase. |
| 49 | + `verify_export.py` guards against a regression here. |
| 50 | +- The publishing credentials can write the prefix but are not granted |
| 51 | + `s3:CreateBucket`, which `rclone` probes for unless given |
| 52 | + `--s3-no-check-bucket`. |
| 53 | +- Recent dumps have included working tables from the FishBase team (`*_copy`, |
| 54 | + `mp_withphotos`, `country.orig`). They are published as-is, since these are |
| 55 | + raw snapshots of the backend, but they show up in the verification diff as |
| 56 | + new tables — worth a glance before publishing. |
0 commit comments