Skip to content

Commit 358483d

Browse files
committed
Merge branch 'feat/branch-snapshot-auto-deletion' into 'master'
feat: deletion protection and auto-deletion for branches and snapshots Closes #727 See merge request postgres-ai/database-lab!1161
2 parents fa2c24e + cebe82c commit 358483d

77 files changed

Lines changed: 4507 additions & 454 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,9 +114,10 @@ Read more:
114114
- Recovery & management
115115
- Fast Point in Time Recovery (PITR) for physical mode
116116
- Auto-deletion of unused clones
117+
- Time-based auto-deletion of unused branches and snapshots (`retention` config; safe-only, never force-deletes dependents)
117118
- Snapshot retention policies in DBLab configuration
118-
- Clones
119-
- "Deletion protection" for preventing clone deletion
119+
- Clones, branches & snapshots
120+
- "Deletion protection" for clones, branches, and snapshots (blocks manual and auto-deletion, plus count-based retention for snapshots)
120121
- Persistent clones withstand DBLab restarts
121122
- "Reset" command for data version switching
122123
- Resource quotas: CPU, RAM

docs/plans/completed/20260617-branch-snapshot-auto-deletion-protection.md

Lines changed: 543 additions & 0 deletions
Large diffs are not rendered by default.

engine/api/swagger-spec/dblab_openapi.yaml

Lines changed: 174 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -301,7 +301,8 @@ paths:
301301
- Snapshots
302302
summary: Delete a snapshot
303303
description: "Permanently delete the specified snapshot.
304-
If the snapshot has dependent clones or datasets, `force=true` can be provided as a query parameter."
304+
If the snapshot has dependent clones or datasets, `force=true` can be provided as a query parameter.
305+
Deletion of a protected snapshot returns 400; remove protection via PATCH first."
305306
parameters:
306307
- name: id
307308
in: path
@@ -334,6 +335,53 @@ paths:
334335
'*/*':
335336
schema:
336337
$ref: '#/components/schemas/Error'
338+
patch:
339+
tags:
340+
- Snapshots
341+
summary: Update a snapshot
342+
description: "Update deletion protection or scheduled deletion of the specified snapshot.
343+
Protection and scheduled deletion are mutually exclusive: enabling protection clears any
344+
scheduled deletion, and scheduling deletion clears protection."
345+
operationId: updateSnapshot
346+
parameters:
347+
- name: id
348+
in: path
349+
required: true
350+
description: The ID of the snapshot to update.
351+
schema:
352+
type: string
353+
pattern: '.*'
354+
- name: Verification-Token
355+
in: header
356+
required: true
357+
schema:
358+
type: string
359+
requestBody:
360+
description: Snapshot protection settings
361+
content:
362+
application/json:
363+
schema:
364+
$ref: '#/components/schemas/UpdateSnapshot'
365+
required: true
366+
responses:
367+
200:
368+
description: Successfully updated the specified snapshot
369+
content:
370+
application/json:
371+
schema:
372+
$ref: '#/components/schemas/Snapshot'
373+
400:
374+
description: Bad request
375+
content:
376+
'*/*':
377+
schema:
378+
$ref: '#/components/schemas/Error'
379+
401:
380+
description: Unauthorized access
381+
content:
382+
application/json:
383+
schema:
384+
$ref: '#/components/schemas/Error'
337385
/clones:
338386
get:
339387
tags:
@@ -920,7 +968,10 @@ paths:
920968
tags:
921969
- Branches
922970
summary: Delete a branch
923-
description: "Permanently delete the specified branch. It cannot be undone."
971+
description: "Permanently delete the specified branch. It cannot be undone.
972+
Deletion of a protected branch returns 400; remove protection via PATCH first.
973+
Deletion of a branch whose snapshots are the fork point of another branch returns 400;
974+
delete the child branches first."
924975
parameters:
925976
- name: branchName
926977
in: path
@@ -947,6 +998,53 @@ paths:
947998
schema:
948999
$ref: '#/components/schemas/Error'
9491000
x-codegen-request-body-name: body
1001+
patch:
1002+
tags:
1003+
- Branches
1004+
summary: Update a branch
1005+
description: "Update deletion protection or scheduled deletion of the specified branch.
1006+
Protection and scheduled deletion are mutually exclusive: enabling protection clears any
1007+
scheduled deletion, and scheduling deletion clears protection."
1008+
operationId: updateBranch
1009+
parameters:
1010+
- name: branchName
1011+
in: path
1012+
required: true
1013+
schema:
1014+
type: string
1015+
description: "The name of the branch to update."
1016+
- name: Verification-Token
1017+
in: header
1018+
required: true
1019+
schema:
1020+
type: string
1021+
requestBody:
1022+
description: Branch protection settings
1023+
content:
1024+
application/json:
1025+
schema:
1026+
$ref: '#/components/schemas/UpdateBranch'
1027+
required: true
1028+
responses:
1029+
200:
1030+
description: Successfully updated the specified branch
1031+
content:
1032+
application/json:
1033+
schema:
1034+
$ref: '#/components/schemas/UpdateBranchResponse'
1035+
400:
1036+
description: Bad request
1037+
content:
1038+
'*/*':
1039+
schema:
1040+
$ref: '#/components/schemas/Error'
1041+
401:
1042+
description: Unauthorized access
1043+
content:
1044+
application/json:
1045+
schema:
1046+
$ref: '#/components/schemas/Error'
1047+
x-codegen-request-body-name: body
9501048
/branch/{branchName}/log:
9511049
get:
9521050
tags:
@@ -1632,6 +1730,17 @@ components:
16321730
numClones:
16331731
type: integer
16341732
format: int
1733+
protected:
1734+
type: boolean
1735+
description: Whether the snapshot is protected from deletion (manual, retention, and auto-deletion).
1736+
protectedTill:
1737+
type: string
1738+
format: date-time
1739+
description: Time until which the snapshot is protected; omitted means indefinite when protected, or none.
1740+
deleteAt:
1741+
type: string
1742+
format: date-time
1743+
description: Scheduled auto-deletion time; omitted means none. Mutually exclusive with protection.
16351744
Database:
16361745
type: object
16371746
properties:
@@ -1753,6 +1862,58 @@ components:
17531862
format: int64
17541863
minimum: 0
17551864
description: Protection duration in minutes. 0 means forever, omit for default duration.
1865+
UpdateSnapshot:
1866+
type: object
1867+
description: "Protection update for a snapshot. Set 'protected' to toggle protection (optionally timed via
1868+
'protectionDurationMinutes'), or 'deleteAt' to schedule deletion. The two are mutually exclusive."
1869+
properties:
1870+
protected:
1871+
type: boolean
1872+
description: Enable or disable deletion protection. Omit to leave unchanged.
1873+
protectionDurationMinutes:
1874+
type: integer
1875+
format: int64
1876+
minimum: 0
1877+
description: Protection duration in minutes. 0 or omitted means indefinite, unless the server's protectionMaxDurationMinutes cap is set, in which case it is limited to that many minutes.
1878+
deleteAt:
1879+
type: string
1880+
format: date-time
1881+
description: Schedule deletion at this time. Clears protection. Mutually exclusive with 'protected'.
1882+
UpdateBranch:
1883+
type: object
1884+
description: "Protection update for a branch. Set 'protected' to toggle protection (optionally timed via
1885+
'protectionDurationMinutes'), or 'deleteAt' to schedule deletion. The two are mutually exclusive."
1886+
properties:
1887+
protected:
1888+
type: boolean
1889+
description: Enable or disable deletion protection. Omit to leave unchanged.
1890+
protectionDurationMinutes:
1891+
type: integer
1892+
format: int64
1893+
minimum: 0
1894+
description: Protection duration in minutes. 0 or omitted means indefinite, unless the server's protectionMaxDurationMinutes cap is set, in which case it is limited to that many minutes.
1895+
deleteAt:
1896+
type: string
1897+
format: date-time
1898+
description: Schedule deletion at this time. Clears protection. Mutually exclusive with 'protected'.
1899+
UpdateBranchResponse:
1900+
type: object
1901+
description: "Result of a branch protection update. Only the branch name and the protection
1902+
fields are populated; other branch attributes are not returned by this endpoint."
1903+
properties:
1904+
name:
1905+
type: string
1906+
protected:
1907+
type: boolean
1908+
description: Whether the branch is protected from deletion (manual and auto-deletion).
1909+
protectedTill:
1910+
type: string
1911+
format: date-time
1912+
description: Time until which the branch is protected; omitted means indefinite when protected, or none.
1913+
deleteAt:
1914+
type: string
1915+
format: date-time
1916+
description: Scheduled auto-deletion time; omitted means none. Mutually exclusive with protection.
17561917
StartObservationRequest:
17571918
type: object
17581919
properties:
@@ -1938,6 +2099,17 @@ components:
19382099
format: date-time
19392100
snapshotID:
19402101
type: string
2102+
protected:
2103+
type: boolean
2104+
description: Whether the branch is protected from deletion (manual and auto-deletion).
2105+
protectedTill:
2106+
type: string
2107+
format: date-time
2108+
description: Time until which the branch is protected; omitted means indefinite when protected, or none.
2109+
deleteAt:
2110+
type: string
2111+
format: date-time
2112+
description: Scheduled auto-deletion time; omitted means none. Mutually exclusive with protection.
19412113
SnapshotDetails:
19422114
type: object
19432115
properties:

0 commit comments

Comments
 (0)