v6.5.0
Performance and stability (#144). Three real implementations + three "already done in earlier releases" honest no-ops + one deferred-as-follow-up. Minor bump because the migration adds indexes on existing tables and changes the create() invariant on audience bookings (now atomic).
Added
Activator::maybe_add_perf_indexes()(#144 S1). AddsKEY idx_created (created_at)toffc_recruitment_candidate,ffc_recruitment_notice, andffc_reregistration_submissionson installs that didn't have them. Idempotent — gated onffc_perf_indexes_db_versionkeyed toFFC_VERSION. Hooked fromLoader::init_plugin()so existing installs pick up the indexes on next page load. The audit also asked aboutidx_updated/ other tables; investigation showedffc_activity_log,ffc_rate_limit_logs,ffc_device_signalsalready declareidx_created, and tables likeffc_user_profileshave no query orders/filters oncreated_at— adding indexes there would be pure write overhead, so left alone.ReregistrationSubmissionRepository::stream_for_export()(#144 S5). Generator yielding rows in 500-row chunks, used byReregistrationCsvExporterinstead of materialising the full result set. Bounded memory for 50k+ row exports.- Cron
cleanup_stale_export_jobs()(#144 S6). Hooked into the existingffcertificate_daily_cleanup_hook, walks_transient_ffc_csv_export_*and_transient_ffc_public_csv_*rows inwp_options, unlinks the temp CSV files referenced in the payload, deletes the transient. Reclaims disk space + DB rows from CSV exports the user abandoned mid-flight.
Changed
AudienceBookingRepository::create()is now atomic (#144 S2). Conflict-check + insert run inside aSTART TRANSACTION ... COMMITblock, with aSELECT ... FOR UPDATEon the conflict predicate. Before this commit, two concurrent requests for the same(environment, date, time)slot could both pass the conflict check (no row existed yet) and both insert. Theidx_env_date_statusindex already declared on the table gives InnoDB the row + gap locks needed to block concurrent inserts in the locked range. Mirrors the pattern atSelfSchedulingAppointmentHandler::create_or_update():140.
Honest no-ops (audit findings already implemented)
- #144 S4 — N+1 in admin user columns: already batch-loaded since v4.9.7 (
load_certificate_counts,load_appointment_counts,load_recruitment_notice_counts). Three GROUP BY queries per page render, regardless of user count. - #144 S7 — Activity log pagination: already implemented;
class-ffc-admin-activity-log-page.phpuses$per_page = 50(smaller than the requested LIMIT 100) and$total_pagesfor navigation. Export path keeps the full dump (limit => 999999). - #144 S8 — Conditional asset enqueue: every public-frontend
wp_enqueue_scriptshook in the plugin already gates onhas_shortcode()against the rendered post content (or enqueues from inside the shortcode'srender()). No unconditional enqueue exists.
Deferred to follow-up
- #144 S3 — Async ficha generation via Action Scheduler: the work requires bundling Action Scheduler (~150 LOC + two custom tables + a new admin page) which is a wider surface than this PR's scope. Tracked as #148.