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, restoreversionrestoreversion 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: initchunkeduploaduploadchunk (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 creationgetorcreateroot 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 inheritancecheckpermission 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