Release 1.11.0
OWA 1.11.0 adds two subsystems that work together: date partitioning for the fact tables, and a job scheduler that keeps them maintained from a single cron entry.
Upgrading: three things to do
1. Apply the database updates. The required schema version moves from 12 to 15. OWA prompts you in the browser, or:
/path/to/php cli.php cmd=updateUntil this runs, the scheduler refuses every job and says so.
2. Add the cron entry. This is new, and nothing periodic runs without it:
* * * * * cd /path/to/owa && php cli.php cmd=schedule-run
One line, whatever you schedule later. Because a scheduler that is not running produces no output, OWA reminds you at the top of every admin page until the entry exists. Check it took with cli.php cmd=schedule-status.
3. Run partition-init when you are ready. New installations are partitioned automatically. An existing installation is deliberately not converted during the update, so partitioning does nothing for you until you convert it yourself:
/path/to/php cli.php cmd=partition-init --dry-run # see the plan, change nothing
/path/to/php cli.php cmd=partition-init # convertRun it in a maintenance window. It rewrites each fact table twice, once to widen the primary key and once to apply the partitioning, and MySQL blocks writes on a table for the duration. Budget roughly five seconds per million rows, per table. That is why it is not part of the update: an upgrade should not decide for you when your tracking stops accepting writes.
There is no hurry and nothing degrades while you wait. Until you convert, the rotate-partitions job refuses with "no fact table is partitioned", which is the expected state rather than a fault. What you are waiting for is the payoff: retention becomes a metadata operation instead of a DELETE over millions of rows, and reports read only the periods covering the reporting period.
See Partitioning Fact Tables for what the layout looks like, how granularity is chosen, and what the conversion does.
Partitioning the fact tables (#989, #994)
All seven fact tables are split into periods on their yyyymmdd column. Dropping old data becomes a metadata operation instead of a DELETE over millions of rows, and reports read only the periods covering the reporting period.
- Tiered layouts. Recent months keep full granularity; older history is merged into whole years, and into runs of years if needed, so a long-running installation stays inside the server's open-file budget. Controlled by
OWA_PARTITION_DETAIL_MONTHS(36). - Nothing is deleted by default.
partition-rotateships with nokeep, so it maintains the twelve-month lead and merges the tail without discarding data. Retention is opt-in, viaOWA_SCHEDULED_JOBS. - Four commands:
partition-status(read-only),partition-init(one-time conversion),partition-rotate(maintenance),partition-reorganize(change granularity),partition-drop(remove periods past a cutoff).
A job scheduler (#997, #1000)
Periodic work is registered in code and dispatched from one cron entry, rather than an entry per task.
- One registered job:
rotate-partitions, monthly, runningpartition-rotatewith no arguments. - Configurable per installation through
OWA_SCHEDULED_JOBSinowa-config.php: retune what ships, add jobs, or turn one off. Overrides are per key, so changing arguments keeps the shipped schedule. - A missed job runs once, not once per miss. The scheduler records the occurrence a run satisfied, so a machine that was off for three days runs a daily job once when it comes back.
- Jobs never overlap themselves, via a per-job lock.
schedule-statusexplains why a job is not running, working through the possible causes and naming the first that applies rather than reporting only that something is behind.
Fixes
- Password reset returned a 500 on PHP 8, and never sent mail when a
Fromaddress was configured (#990, @digikwal) - Visitors roster showed the wrong day (#991)
- JS bundles leaked globals; they are now wrapped in an IIFE (#993, @digikwal)
- Asset URLs were built with a doubled slash (#998)
- A missing site id, and an unresolvable action, are now answered rather than raising (#983, #996)
addIndex()no longer adds duplicate copies of an index, and exact duplicate indexes are dropped (#985, #986)visitor_idis now indexed on the fact tables (#988)- The error log is created group-writable (#987)
- CLI boolean arguments accept
--switchsyntax (#995) - Pinned patched
js-yamlandfast-urithrough overrides (#984)
Documentation
New wiki pages: Scheduled Jobs and Partitioning Fact Tables. Installation, Updating and Technical Requirements now cover the cron entry.
Contributors
Thank you to @digikwal for the PHP 8 password-reset fix and mailer From handling (#990), and for wrapping the JS bundles so they stop leaking globals (#993).
Internal
Test and CI work, not user facing: an isolation sweep that runs every test file in its own process, and the defects it found — settings flushed from a destructor could be lost and could exit the process 255, and Mysql::close() was not idempotent (#1001, #1002, #1003).