mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-09-09 19:31:57 +02:00
docs: plan for request versioning
This commit is contained in:
@@ -0,0 +1,79 @@
|
|||||||
|
# Request versioning (IntelliJ Local History style)
|
||||||
|
|
||||||
|
Working plan for `feat/request-versioning`. Tracks
|
||||||
|
[save-request-data-for-response-history](https://yaak.app/feedback/posts/save-request-data-for-response-history).
|
||||||
|
|
||||||
|
Selecting an old response should be able to show, and restore, the request that produced it.
|
||||||
|
|
||||||
|
## Model
|
||||||
|
|
||||||
|
One table, `model_versions`, versions every request type:
|
||||||
|
|
||||||
|
| column | meaning |
|
||||||
|
| --- | --- |
|
||||||
|
| `id`, `model`, `created_at`, `updated_at` | usual model columns |
|
||||||
|
| `workspace_id` | owning workspace |
|
||||||
|
| `model_type` | `http_request` / `grpc_request` / `websocket_request` |
|
||||||
|
| `model_id` | the request the version belongs to |
|
||||||
|
| `content_hash` | sha256 of the canonical document |
|
||||||
|
| `document` | JSON of the request's editable content |
|
||||||
|
| `reason` | `send` / `switch` / `idle` / `restore` / `manual` |
|
||||||
|
|
||||||
|
`http_responses`, `grpc_connections` and `websocket_connections` each gain a nullable
|
||||||
|
`version_id`.
|
||||||
|
|
||||||
|
A version's `document` is the model's JSON with bookkeeping keys removed — `model`, `id`,
|
||||||
|
`createdAt`, `updatedAt`, `workspaceId`, `folderId`, `sortPriority`. One rule, applied the same
|
||||||
|
way to all three request types; the hash is taken over exactly what the document holds, so moving
|
||||||
|
a request between folders or re-sorting it never mints a version.
|
||||||
|
|
||||||
|
`(model_id, content_hash)` is unique, so dedup is the database's job rather than a code path that
|
||||||
|
can be forgotten. Sending an unchanged request ten times leaves one version and ten responses
|
||||||
|
pointing at it.
|
||||||
|
|
||||||
|
## Snapshot
|
||||||
|
|
||||||
|
One primitive, `ClientDb::snapshot_request(request, reason)`: build the document, hash it, return
|
||||||
|
the existing row for that hash or insert a new one, then prune. Everything calls it.
|
||||||
|
|
||||||
|
- **Sends.** `resolve_send_inputs` (HTTP, every host — desktop, CLI, plugin-triggered) snapshots
|
||||||
|
before the response row is created, and the resulting id rides down to the response.
|
||||||
|
gRPC and WebSocket connect paths do the same at their own connection upserts.
|
||||||
|
- **Edit-session boundaries the frontend can see**, all through one RPC: switching to another
|
||||||
|
request, window blur, app close, and a 60s idle timer after the last edit.
|
||||||
|
|
||||||
|
Over-triggering is free, so the trigger code stays dumb.
|
||||||
|
|
||||||
|
## Restore
|
||||||
|
|
||||||
|
`restore_request_version(version_id)`:
|
||||||
|
|
||||||
|
1. Snapshot the live request (reason `restore`), so anything newer than its last version is kept.
|
||||||
|
2. Merge the version's document over the live model, keeping bookkeeping fields.
|
||||||
|
3. Upsert. The written content's hash already exists, so no new version row appears.
|
||||||
|
|
||||||
|
The frontend calls `wasUpdatedExternally` afterwards so open editors reload.
|
||||||
|
|
||||||
|
## Retention
|
||||||
|
|
||||||
|
An unreferenced version survives only while it is among the newest 50 for its request *and* newer
|
||||||
|
than 30 days. A version referenced by a response lives as long as that response. Deleting a
|
||||||
|
request deletes its versions. Versions are local history: not synced to the filesystem, not in
|
||||||
|
Git, not exported.
|
||||||
|
|
||||||
|
## UI (v1, HTTP)
|
||||||
|
|
||||||
|
When the selected response's version differs from the live request, the response header grows a
|
||||||
|
state-labelled dropdown ("Request Changed", following the GraphQL editor's pattern) with **View
|
||||||
|
Diff** and **Restore**. The diff reuses the Git dialog's `DiffViewer` over YAML renderings of the
|
||||||
|
two documents. No versions timeline panel in v1; gRPC and WebSocket are wired on the backend from
|
||||||
|
day one and their UI can follow.
|
||||||
|
|
||||||
|
## Status
|
||||||
|
|
||||||
|
- [ ] Migration + `ModelVersion` model + bindings
|
||||||
|
- [ ] Hashing / document extraction, with tests
|
||||||
|
- [ ] Queries: snapshot, prune, restore, cascade
|
||||||
|
- [ ] Send pipelines: HTTP, gRPC, WebSocket
|
||||||
|
- [ ] RPC commands + web/wasm host
|
||||||
|
- [ ] Frontend: snapshot triggers, dropdown, diff dialog, restore
|
||||||
Reference in New Issue
Block a user