Implement an In-Memory File Storage Class with Unique IDs and Duplicate-Name Suffixes
Company: Cresta
Role: Software Engineer
Category: Software Engineering Fundamentals
Difficulty: medium
Interview Round: Technical Screen
Implement an in-memory file storage service as a single class, `FileStorage`, in a language of your choice. The interviewer gives only the description below: there is no starter code and no test code, so how the class is organised and how it is tested are entirely up to you. The description was recalled after the interview, so details may differ slightly from the original.
```python
class FileStorage:
def upload_file(self, file_name: str, file_content: bytes) -> str: ...
def get_file(self, file_id: str) -> bytes: ...
def delete_file(self, file_id: str) -> bool: ...
def get_all_files(self) -> list[dict]: ...
```
- `upload_file` stores the file and returns a unique `file_id`. If a file with the same name already exists, a suffix is added to the new file's name.
- `get_file` returns the file's content and raises an error if the file does not exist.
- `delete_file` deletes the file and returns `True`, or returns `False` if the file did not exist.
- `get_all_files` returns metadata for every stored file as a list of dictionaries of the form `{"file_id": ..., "file_name": ..., "file_size": ..., "upload_timestamp": ...}`.
The round lasts about 60 minutes in a shared online editor, introductions included, so the time for writing and testing the code is shorter than that.
### Clarifying Questions
- What exact suffix should a duplicate name receive (for example `report (1).txt` or `report_1.txt`), and does it go before the file extension?
- Once a file is deleted, may a later upload reuse its name? May its `file_id` ever be reused?
- If `report.txt` and `report (1).txt` are both stored and `report (1).txt` is uploaded again, what name should the new file get?
- In what order should `get_all_files` list the files, and what unit or format should `upload_timestamp` use (epoch seconds, milliseconds, an ISO 8601 string)?
- Which error should `get_file` raise for an unknown id, and should invalid input, such as an empty name or content that is not bytes, be rejected?
- Is single-threaded use enough, or can several callers upload and delete at the same time?
### Part 1 — Implement FileStorage
Implement the four methods with the behaviour described above. Decide how file ids are generated, how a duplicate name is made unique, and which data structures hold the files and their metadata.
```hint Two kinds of lookup
Three of the methods find a file by its id, but the duplicate check finds a file by its name. Decide which lookups must be fast and what structure serves each one.
```
```hint A name that already looks suffixed
Consider a user who uploads a file whose name already ends the way one of your generated names would.
```
#### What This Part Should Cover
- Data structures for lookups by id and by name, kept consistent on every upload and delete
- An explicit unique-name rule: suffix format, position relative to the extension, and names freed by deletion
- Id generation that never repeats, and file size and timestamp captured at upload
- Clear error behaviour for unknown ids and invalid arguments
### Part 2 — Test it without a harness
No test code is provided. Write the tests you would run before the round ends, and make the class testable, including the timestamp.
```hint Control the clock
Think about how a test can assert an exact `upload_timestamp` without sleeping or reading the real time.
```
#### What This Part Should Cover
- A test for the normal path and the failure path of each method
- Duplicate-name cases: second and third uploads of one name, names without an extension, and a name freed by deletion
- An injected clock, and optionally an injected id generator, so that expected values are exact
- Pacing: tests written and run as the methods appear, not left for the last minute
### What a Strong Answer Covers
- Raises the unresolved rules (suffix format, name reuse, list order, timestamp format) and settles them before coding
- A small, readable class whose id and name indexes can never disagree
- Correct suffixing in the edge cases, including collisions with names that already carry a suffix
- Tests that actually run within the time box, rather than finished code that was never executed
- Complexity of each method, and what would change for very large files or concurrent callers
### Follow-up Questions
- How would you make the class safe when several threads upload and delete files at once?
- Files can be several gigabytes. How would you change the storage and the signatures of `upload_file` and `get_file`?
- How would you avoid storing the same bytes twice when different file names hold identical content?
- How would you persist the files so that they survive a restart of the process?
Overview: Implement an in-memory FileStorage class with upload, get, delete and list methods, where every upload receives a unique id and duplicate file names get a suffix. Tests class design, name-collision edge cases, error handling and writing your own tests with no starter code or harness.
Read the full Cresta Software Engineer interview experience this question came from