File: design-google-drive/designgoogledrive.py

Date: 2026-06-05

Time: 13:25

Purpose

This file is a single-module simulation of Google Drive's backend storage layer, built as a system design interview reference implementation. It owns the core file storage domain: CRUD operations on files and folders, version history, chunked uploads for large files, permission-based sharing, conflict detection for multi-device sync, quota management, and trash/recovery. Everything runs in-memory — no database, no network — isolating the *design decisions* from infrastructure concerns.

Key Components

Data Classes

Permission — Three-tier enum (READ < WRITE < ADMIN) with a companion PERMISSION_LEVEL dict that maps each variant to an integer for comparison. This is the authorization primitive used everywhere.

FileMetadata — The central entity. Represents both files and folders (discriminated by is_folder). Notable fields:

FileVersion — Immutable snapshot of file state at a point in time. Stores both metadata (contenthash, sizebytes) and the actual content: bytes. The version list is the full edit history.

ChunkedUpload — Tracks an in-progress multipart upload session. Holds individual chunks and checksums until completechunkedupload assembles them.

FileStore — The Main Class

Single class that acts as the entire storage service. Constructor parameters set system-wide policy: maxversions (cap on version history depth, default 100) and defaultquota_bytes (1 GB per user).

Internal state is organized into parallel dictionaries keyed by file_id:

Key Methods by Category

Folder ops: createfolder, listfolder, getpath — standard tree operations. getpath walks parent pointers to reconstruct the full /a/b/c path.

File CRUD: uploadfile, downloadfile, updatefile, deletefile, movefile, renamefile. Every mutating operation checks permissions and updates quotas.

Versioning: getversions, restoreversion — restoreversion doesn't do a raw rollback; it calls updatefile with the old content, creating a *new* version that happens to match an old one. This preserves the audit trail.

Chunked upload: initchunkedupload → uploadchunk (repeated) → completechunkedupload. Quota is reserved upfront at init, then released-and-reaccounted at completion. abortchunked_upload releases the reservation.

Sharing: share, revoke, getsharedwith — ACL management. Only owner or ADMIN-level users can share.

Conflict detection: detectconflict uses version vectors to distinguish true conflicts (concurrent edits from different devices) from simple staleness. resolveconflict supports two strategies: latestwins (no-op, server version stands) and keepboth (creates a (conflict) copy).

Trash: listtrash, restorefromtrash, emptytrash — soft-delete with time-based permanent deletion (default 30 days, computed via auto_days * 86400 seconds).

Search: Linear scan over all files with substring name matching and optional MIME type filter. Only returns files the user can read.

Patterns

Soft delete — Files are never immediately removed from self.files. Deletion sets isdeleted=True and records deletedat. Permanent removal only happens in empty_trash based on age.

Lazy root creation — getorcreateroot ensures every user has a root folder, created on first access. This avoids upfront user registration.

Quota reservation — Chunked uploads reserve quota at init time, not completion. This prevents a user from starting multiple uploads that collectively exceed their quota. The reservation is released then re-accounted when the upload finalizes.

Permission inheritance — checkpermission walks up the folder tree via parentfolderid pointers. If any ancestor grants sufficient access, the check passes. This models Google Drive's "shared folder" semantics.

Version vectors for conflict detection — Rather than simple version counters, each file tracks which version each device last wrote. A conflict is detected when another device has a version newer than what the requesting device last saw — distinguishing concurrent edits from sequential ones.

Content-addressed integrity — SHA-256 checksums are computed on upload/update and stored in both FileMetadata.checksum and FileVersion.content_hash.

Dependencies

Imports: All stdlib — hashlib (checksums), math (ceiling division for chunks), uuid (ID generation), dataclasses, enum, typing. No external dependencies.

Imported by: testdesigngoogle_drive.py — the test suite is the sole consumer.

Flow

A typical file lifecycle:

1. Upload: upload_file → quota check → generate UUID → compute SHA-256 → create FileMetadata → store content → create initial FileVersion (v1)

2. Edit: updatefile → permission check → quota delta adjustment → new checksum → bump currentversion → update version vector for device → append FileVersion → prune if over max_versions

3. Sync conflict: Device B calls detectconflict(fileid, "deviceB", baseversion=1) → file is at v3, device A wrote v2 and v3 → versionvector["deviceA"] > version_vector.get("deviceB", 0) → returns True

4. Delete: deletefile → soft-delete → if folder, cascade to all descendants via BFS in get_descendants

5. Trash cleanup: emptytrash → filter by deletedat <= cutoff → hard-delete from all stores → release quota

For chunked uploads: initchunkedupload reserves quota → N calls to uploadchunk storing individual chunks → completechunkedupload assembles chunks in order, releases reservation, delegates to uploadfile for the actual storage, then cleans up the upload session.

Invariants

Error Handling

Three exception types are used consistently:

| Exception | Raised when |

|-----------|------------|

| FileNotFoundError | File ID doesn't exist or file is soft-deleted |

| PermissionError | User lacks required permission level |

| ValueError | Quota exceeded, missing chunks, unknown conflict strategy, or version not found |

Errors are raised immediately — nothing is swallowed. Callers (the test suite) are expected to handle them. There's no retry logic or partial-failure recovery. abortchunkedupload and delete_file are the only methods that return bool success/failure instead of raising.

Topics to Explore

Beliefs