feat(12.2-01): add deferred:purge, its daily framework schedule and relation child hooks

- deferred:purge [--days] in lagoon.RuntimeCommands (purge_days, default 5)
- lagoon.FrameworkSchedule entry at purge_at (default 03:00, empty disables)
- conga prepends framework entries as summercms.lagoon[i]:<command>
- pact.Relation{Before,After}{Create,Update,Delete} optional hooks
- lagoon, conga and pact READMEs, scheduling and setup docs
This commit is contained in:
Jakub Zych
2026-10-02 17:45:41 +02:00
parent f48a886f94
commit 8818d7b023
11 changed files with 378 additions and 8 deletions

View File

@@ -144,7 +144,9 @@ func (p *Plugin) Migrations() []*gormigrate.Migration {
| `lagoon.PurgeDeferred` | Removes expired bindings, their unattached files (blobs after commit) and the children created under deferral. |
| `lagoon.PurgeOptions` | Cut-off time and created-child model resolver for `lagoon.PurgeDeferred`. |
| `lagoon.PurgeResult` | Counts of deleted bindings, files and children and of skipped bindings. |
| `lagoon.RuntimeCommands` | Returns the migrate, migrate:rollback, migrate:status and key:generate commands. |
| `lagoon.RuntimeCommands` | Returns the migrate, migrate:rollback, migrate:status, deferred:purge and key:generate commands. |
| `lagoon.FrameworkSchedule` | The framework's scheduled commands for conga: the daily `deferred:purge` at `database.deferred_bindings.purge_at`, or none when it is empty. |
| `lagoon.FrameworkScheduleID` | Plugin id the framework's schedule entries are listed under, `summercms.lagoon`. |
| `lagoon.KeyGenerateCommand` | Returns the key:generate command on its own. |
| `lagoon.LoadAppKey` | Decodes `app.key` and `app.previous_keys`. |
| `lagoon.PublishEncryptionKeys` | Installs the keys used by `lagoon.Encrypted` columns. |
@@ -214,6 +216,8 @@ Keys are read from the compass config; the `SUMMER_` environment overlay maps a
| `app.previous_keys` | empty | List of earlier base64 keys still accepted when decrypting, for key rotation. |
| `storage.uploads.bucket_url` | none (required by `attach.OpenBucket`) | Uploads bucket URL, `file://` or `mem://`. |
| `storage.uploads.public_path_prefix` | `/storage/uploads` | URL prefix used when building public file and thumbnail URLs. |
| `database.deferred_bindings.purge_days` | `5` | Age in days after which `deferred:purge` removes a deferred binding, WinterCMS's `cleanUp(5)`; the `--days` flag overrides it. |
| `database.deferred_bindings.purge_at` | `03:00` | Daily `HH:MM` (in `app.timezone`) at which the scheduler runs `deferred:purge`; an empty value disables the framework entry. |
```yaml
database:
@@ -234,6 +238,7 @@ storage:
| `migrate` | none | Runs the framework migrations (`system_files`, the backend admin tables, `deferred_bindings` and the job queue), then each plugin's migrations in dependency order. |
| `migrate:rollback` | `--plugin <id>` | Rolls back the last migration of the given plugin; without the flag, of the last activated plugin that has migrations. |
| `migrate:status` | none | Prints a table of plugin, history table and applied migration IDs. |
| `deferred:purge` | `--days <n>` | Deletes deferred bindings older than `n` days (default `database.deferred_bindings.purge_days`, else 5), with the unattached uploads they hold (blobs after the commit) and the records created under deferral, and prints the counts. Records that were only linked are kept. Model types come from every plugin's `pact.HasModels`; the uploads bucket from the published one or `storage.uploads.bucket_url`. |
| `key:generate` | none | Prints a fresh base64 32-byte key for `app.key`; writes nothing. |
## Dependencies