Skip to content

Commit 1e97b70

Browse files
authored
docs: improve storage structure to eliminate redundancy (#100)
- Remove separate blobs/ directory, store everything under versions/ - Track current version via metadata.current_version field - Eliminate need to copy/move blobs when creating versions - Simplify update operations - just add new timestamp file - Add storage design notes explaining the benefits
1 parent b883792 commit 1e97b70

File tree

1 file changed

+45
-8
lines changed

1 file changed

+45
-8
lines changed

docs/SPEC.md

Lines changed: 45 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -45,14 +45,19 @@ All data stored in Cloudflare R2:
4545
```
4646
ghostpaste-bucket/
4747
├── metadata/
48-
│ └── {gist-id}.json # Mixed encrypted/unencrypted metadata
49-
├── blobs/
50-
│ └── {gist-id}.bin # Encrypted binary content
48+
│ └── {gist-id}.json # Metadata with current version pointer
5149
└── versions/
5250
└── {gist-id}/
53-
└── {timestamp}.bin # Encrypted version history
51+
└── {timestamp}.bin # All encrypted blobs (no separate blobs/ directory)
5452
```
5553

54+
**Key improvements:**
55+
56+
- No redundant storage - all blobs stored only in `versions/`
57+
- Current version tracked via `current_version` field in metadata
58+
- Simpler updates - just add new version file and update metadata pointer
59+
- No file copying/moving needed when creating versions
60+
5661
---
5762

5863
## 📊 Data Models
@@ -68,6 +73,7 @@ interface GistMetadata {
6873
created_at: string; // ISO 8601
6974
updated_at: string; // ISO 8601
7075
expires_at?: string; // ISO 8601 (optional)
76+
current_version: string; // ISO 8601 timestamp pointing to latest version
7177
version: number; // Current version number
7278
version_count: number; // Total versions
7379
total_size: number; // Total size in bytes
@@ -187,9 +193,11 @@ Response: 200 OK
187193
GET /api/blobs/{id}
188194
189195
Response: 200 OK
190-
[Binary data]
196+
[Binary data from versions/{id}/{current_version}.bin]
191197
```
192198

199+
Note: The blob endpoint internally fetches from the versions directory using the current_version timestamp from metadata.
200+
193201
### Update Gist
194202

195203
```http
@@ -273,9 +281,15 @@ Gists that delete after first decryption:
273281
### 3. Version History
274282

275283
- Last 50 versions kept
276-
- Each version timestamped
284+
- Each version stored as `versions/{gist-id}/{timestamp}.bin`
285+
- Metadata tracks `current_version` timestamp
286+
- Creating new version:
287+
1. Upload blob to `versions/{gist-id}/{new-timestamp}.bin`
288+
2. Update metadata with new `current_version` and increment `version`
289+
3. No copying/moving of blobs required
277290
- Accessible via dropdown UI
278291
- Same encryption key for all versions
292+
- Version cleanup removes old timestamp files beyond limit
279293

280294
---
281295

@@ -420,7 +434,16 @@ export interface Env {
420434

421435
// Example usage in API route
422436
export async function POST(request: Request, env: Env) {
423-
// Direct R2 access without credentials
437+
// Store new version
438+
const timestamp = new Date().toISOString();
439+
await env.GHOSTPASTE_BUCKET.put(
440+
`versions/${id}/${timestamp}.bin`,
441+
encryptedBlob
442+
);
443+
444+
// Update metadata to point to new version
445+
metadata.current_version = timestamp;
446+
metadata.version += 1;
424447
await env.GHOSTPASTE_BUCKET.put(
425448
`metadata/${id}.json`,
426449
JSON.stringify(metadata)
@@ -463,4 +486,18 @@ const keyBase64 = btoa(String.fromCharCode(...new Uint8Array(keyData)));
463486

464487
---
465488

466-
Last updated: 2025-06-04
489+
## 📝 Storage Design Notes
490+
491+
The storage structure uses a single `versions/` directory for all blobs rather than separate `blobs/` and `versions/` directories. This design:
492+
493+
1. **Eliminates redundancy** - No duplicate storage of current blob
494+
2. **Simplifies updates** - New versions just add a timestamp file
495+
3. **Improves atomicity** - Single write operation for new versions
496+
4. **Reduces complexity** - No file copying or moving operations
497+
5. **Better consistency** - Metadata always points to valid version file
498+
499+
When fetching the current blob, the system reads metadata to get the `current_version` timestamp, then fetches from `versions/{id}/{current_version}.bin`.
500+
501+
---
502+
503+
Last updated: 2025-06-07

0 commit comments

Comments
 (0)