ICT:Dashboard autopurge architecture: Difference between revisions
Created page with "= ICT: Dashboard Auto‑Purge Architecture = This page documents why dashboards in this wiki require an automatic purge after saving a Page Forms form, why several intuitive approaches fail, and why the final solution works reliably. It is written for future administrators and maintainers of the Costa Sano Research infrastructure. == 1. The Problem == Dashboards such as '''Dashboard:Place''' display data stored in Cargo tables. After saving a form, the updated Car..." |
No edit summary |
||
| Line 1: | Line 1: | ||
= ICT: Dashboard Auto‑Purge Architecture = | = ICT: Dashboard Auto‑Purge Architecture = | ||
This page documents why dashboards in this wiki require an automatic purge after saving a Page Forms form, why several intuitive approaches fail, and why the final solution works reliably | This page documents why dashboards in this wiki require an automatic purge after saving a Page Forms form, why several intuitive approaches fail, and why the final solution works reliably. | ||
== 1. The Problem == | == 1. The Problem == | ||
| Line 14: | Line 13: | ||
* Reverse proxies may cache responses | * Reverse proxies may cache responses | ||
* Page Forms redirects do not trigger a purge | * Page Forms redirects do not trigger a purge | ||
A reliable, automatic purge mechanism is required. | A reliable, automatic purge mechanism is required. | ||
| Line 26: | Line 23: | ||
'''Conclusion:''' HTML refresh cannot be used. | '''Conclusion:''' HTML refresh cannot be used. | ||
=== 2.2. Redirecting to <code>?action=purge</code> === | === 2.2. Redirecting to <code>?action=purge</code> === | ||
A redirect to | A redirect to <code>?action=purge</code> always triggers MediaWiki’s confirmation dialog. | ||
<code>?action=purge</code> | |||
always triggers MediaWiki’s confirmation dialog | |||
This dialog cannot be suppressed via GET requests. | This dialog cannot be suppressed via GET requests. | ||
'''Conclusion:''' GET‑based purge is never silent. | '''Conclusion:''' GET‑based purge is never silent. | ||
=== 2.3. Page Forms limitations === | === 2.3. Page Forms limitations === | ||
Page Forms does not provide | Page Forms does not provide hooks or callbacks that run after saving. | ||
It cannot trigger a purge. | |||
'''Conclusion:''' Page Forms cannot be used for purge logic. | |||
'''Conclusion:''' Page Forms cannot | |||
=== 2.4. JavaScript redirect loops === | === 2.4. JavaScript redirect loops === | ||
Redirecting to <code>?action=purge</code> causes: | |||
# | # Purge dialog | ||
# | # Page reload | ||
# | # JavaScript fires again | ||
# Loop | |||
# | |||
'''Conclusion:''' Redirect‑based purge is unstable. | '''Conclusion:''' Redirect‑based purge is unstable. | ||
=== 2.5. Query parameters being stripped === | === 2.5. Query parameters being stripped === | ||
Reverse proxies, skins, and canonical URL rewrites may strip unknown parameters such as | Reverse proxies, skins, and canonical URL rewrites may strip unknown parameters such as <code>?purged=1</code>. | ||
This prevents loop‑detection. | |||
<code>?purged=1</code> | |||
'''Conclusion:''' Only parameters MediaWiki preserves can be used. | |||
'''Conclusion:''' Only parameters MediaWiki preserves can be used | |||
== 3. Requirements for a Working Solution == | == 3. Requirements for a Working Solution == | ||
| Line 84: | Line 56: | ||
A correct solution must: | A correct solution must: | ||
* purge silently | * purge silently | ||
* avoid loops | * avoid loops | ||
* work for all dashboards | * work for all dashboards | ||
* survive reverse proxies | * survive reverse proxies | ||
* be centralized | * be centralized | ||
* be successor‑friendly | * be successor‑friendly | ||
== 4. The Final, Working Solution == | == 4. The Final, Working Solution == | ||
=== 4.1. Purge via the MediaWiki API === | === 4.1. Purge via the MediaWiki API === | ||
Silent purge requires: | |||
* POST request | |||
* CSRF token | |||
* API module | |||
=== 4.2. Use a preserved query parameter === | === 4.2. Use a preserved query parameter === | ||
| Line 111: | Line 77: | ||
<code>?mw_purged=1</code> | <code>?mw_purged=1</code> | ||
=== 4.3. Centralize logic in <code>MediaWiki:Common.js</code> === | === 4.3. Centralize logic in <code>MediaWiki:Common.js</code> === | ||
One place, all dashboards. | |||
== 5. The Working Code (Common.js) == | == 5. The Working Code (Common.js) == | ||
| Line 163: | Line 121: | ||
* API POST + CSRF token | * API POST + CSRF token | ||
* No confirmation dialog | * No confirmation dialog | ||
=== No loops === | === No loops === | ||
* <code>mw_purged=1</code> is preserved | * <code>mw_purged=1</code> is preserved | ||
* JS sees the marker and | * JS sees the marker and stops | ||
=== Works for all dashboards === | === Works for all dashboards === | ||
* Uses <code>wgPageName</code> | * Uses <code>wgPageName</code> | ||
=== Infrastructure‑safe === | === Infrastructure‑safe === | ||
| Line 177: | Line 133: | ||
* Survives canonical URL rewrites | * Survives canonical URL rewrites | ||
* Survives short URLs | * Survives short URLs | ||
=== Successor‑friendly === | === Successor‑friendly === | ||
* One central rule | * One central rule | ||
* No per‑page | * No per‑page hacks | ||
* | |||
== 7. Architecture Diagram == | |||
The following ASCII diagram shows the complete flow from saving a form to the final dashboard refresh. | |||
<pre> | |||
+-----------------------+ | |||
| User saves form | | |||
| (Page Forms) | | |||
+-----------+-----------+ | |||
| | |||
v | |||
+-----------------------+ | |||
| Page Forms redirect | | |||
| to Dashboard:XYZ | | |||
+-----------+-----------+ | |||
| | |||
v | |||
+-----------------------+ | |||
| Dashboard loads | | |||
| Common.js executes | | |||
+-----------+-----------+ | |||
| | |||
| JS checks: | |||
| - Is this Dashboard:* ? | |||
| - Is mw_purged=1 absent? | |||
v | |||
+-----------------------+ | |||
| Request CSRF token | | |||
| via API (GET) | | |||
+-----------+-----------+ | |||
| | |||
v | |||
+-----------------------+ | |||
| Silent purge via API | | |||
| (POST + token) | | |||
+-----------+-----------+ | |||
| | |||
v | |||
+-----------------------+ | |||
| Reload dashboard with | | |||
| ?mw_purged=1 marker | | |||
+-----------+-----------+ | |||
| | |||
v | |||
+-----------------------+ | |||
| Dashboard loads fresh | | |||
| JS sees mw_purged=1 | | |||
| -> No purge triggered | | |||
+-----------------------+ | |||
</pre> | |||
== | == 8. Summary == | ||
The final solution works because it respects all of MediaWiki’s constraints: | The final solution works because it respects all of MediaWiki’s constraints: | ||
| Line 195: | Line 200: | ||
* Only <code>mw_*</code> parameters survive reliably | * Only <code>mw_*</code> parameters survive reliably | ||
This produces a stable, silent, automatic purge mechanism for all dashboards. | |||
Revision as of 21:38, 14 February 2026
ICT: Dashboard Auto‑Purge Architecture
This page documents why dashboards in this wiki require an automatic purge after saving a Page Forms form, why several intuitive approaches fail, and why the final solution works reliably.
1. The Problem
Dashboards such as Dashboard:Place display data stored in Cargo tables. After saving a form, the updated Cargo data does not appear immediately because:
- Cargo updates are asynchronous
- MediaWiki caches parser output
- APCu/object cache may serve stale HTML
- Reverse proxies may cache responses
- Page Forms redirects do not trigger a purge
A reliable, automatic purge mechanism is required.
2. Why Simple Solutions Do Not Work
2.1. HTML <meta> refresh
MediaWiki sanitizes <meta> tags, even inside #tag:html.
The tag is displayed as text and never executed.
Conclusion: HTML refresh cannot be used.
2.2. Redirecting to ?action=purge
A redirect to ?action=purge always triggers MediaWiki’s confirmation dialog.
This dialog cannot be suppressed via GET requests.
Conclusion: GET‑based purge is never silent.
2.3. Page Forms limitations
Page Forms does not provide hooks or callbacks that run after saving. It cannot trigger a purge.
Conclusion: Page Forms cannot be used for purge logic.
2.4. JavaScript redirect loops
Redirecting to ?action=purge causes:
- Purge dialog
- Page reload
- JavaScript fires again
- Loop
Conclusion: Redirect‑based purge is unstable.
2.5. Query parameters being stripped
Reverse proxies, skins, and canonical URL rewrites may strip unknown parameters such as ?purged=1.
This prevents loop‑detection.
Conclusion: Only parameters MediaWiki preserves can be used.
3. Requirements for a Working Solution
A correct solution must:
- purge silently
- avoid loops
- work for all dashboards
- survive reverse proxies
- be centralized
- be successor‑friendly
4. The Final, Working Solution
4.1. Purge via the MediaWiki API
Silent purge requires:
- POST request
- CSRF token
- API module
4.2. Use a preserved query parameter
MediaWiki never strips parameters beginning with mw_.
We use:
?mw_purged=1
4.3. Centralize logic in MediaWiki:Common.js
One place, all dashboards.
5. The Working Code (Common.js)
$(function () {
const title = mw.config.get('wgPageName');
if (title && title.startsWith('Dashboard:')) {
// Only purge once
if (!location.search.includes('mw_purged=1')) {
new mw.Api().get({
action: 'query',
meta: 'tokens',
type: 'csrf'
}).done(function (data) {
const token = data.query.tokens.csrftoken;
new mw.Api().post({
action: 'purge',
titles: title,
token: token
}).always(function () {
// Reload the dashboard normally, marked as purged
const url = mw.util.getUrl(title, { mw_purged: 1 });
location.replace(url);
});
});
}
}
});
6. Why This Works
Silent purge
- API POST + CSRF token
- No confirmation dialog
No loops
mw_purged=1is preserved- JS sees the marker and stops
Works for all dashboards
- Uses
wgPageName
Infrastructure‑safe
- Survives reverse proxies
- Survives canonical URL rewrites
- Survives short URLs
Successor‑friendly
- One central rule
- No per‑page hacks
7. Architecture Diagram
The following ASCII diagram shows the complete flow from saving a form to the final dashboard refresh.
+-----------------------+
| User saves form |
| (Page Forms) |
+-----------+-----------+
|
v
+-----------------------+
| Page Forms redirect |
| to Dashboard:XYZ |
+-----------+-----------+
|
v
+-----------------------+
| Dashboard loads |
| Common.js executes |
+-----------+-----------+
|
| JS checks:
| - Is this Dashboard:* ?
| - Is mw_purged=1 absent?
v
+-----------------------+
| Request CSRF token |
| via API (GET) |
+-----------+-----------+
|
v
+-----------------------+
| Silent purge via API |
| (POST + token) |
+-----------+-----------+
|
v
+-----------------------+
| Reload dashboard with |
| ?mw_purged=1 marker |
+-----------+-----------+
|
v
+-----------------------+
| Dashboard loads fresh |
| JS sees mw_purged=1 |
| -> No purge triggered |
+-----------------------+
8. Summary
The final solution works because it respects all of MediaWiki’s constraints:
- Purge must be done via API POST
- CSRF token is required
- GET purge always shows a dialog
- Page Forms cannot trigger purge
- Unknown query parameters may be stripped
- Only
mw_*parameters survive reliably
This produces a stable, silent, automatic purge mechanism for all dashboards.