Build an in-memory database in four stages. Each key owns string field/value pairs.
Question
Build an in-memory database in four stages. Each key owns string field/value pairs.
```python
class InMemoryDB:
def set(self, key, field, value) -> None: ...
def get(self, key, field) -> str: ...
def delete(self, key, field) -> bool: ...
def scan(self, key) -> list[str]: ...
def scan_by_prefix(self, key, prefix) -> list[str]: ...
def set_at(self, key, field, value, timestamp) -> None: ...
def set_at_with_ttl(self, key, field, value, timestamp, ttl) -> None: ...
def get_at(self, key, field, timestamp) -> str: ...
def delete_at(self, key, field, timestamp) -> bool: ...
def scan_at(self, key, timestamp) -> list[str]: ...
def scan_by_prefix_at(self, key, prefix, timestamp) -> list[str]: ...
def backup(self, timestamp) -> None: ...
def restore(self, timestamp, timestamp_to_restore) -> None: ...
```
Missing values return `""`. Scans emit `field(value)` entries sorted by field. A TTL value is live over `[created_at, created_at + ttl)`. A backup captures all live fields and each field's remaining lifetime. Restore selects the newest backup at or before `timestamp_to_restore`, replaces current state, and restarts remaining lifetimes at `timestamp`.
Assume timestamps supplied to mutating timed operations are nondecreasing. Backups must not share mutable state with the live database.
Timed reads/deletes/scans must not expose a field before its creation, including fields without expiry. Untimed methods ignore TTL-bearing records and do not consult a clock. Inputs use string keys/fields/values, integer timestamps and positive integer TTLs. This stores current field records, not historical overwritten versions. Restoring without an eligible backup leaves current state unchanged; equal-time backups select the last created. Backup/restore/set return `None`. The supplied `run_case` owns batch dispatch and creates a fresh database per case.
## Design discussion (not graded)
1. Explain why snapshots store remaining lifetime rather than absolute expiry.
2. Reclaim expired records without scanning the full database on every operation.
3. Add nested transactions with commit and rollback.
4. Persist snapshots and an operation log for crash recovery.The public brief is identical for people and crawlers. Account access changes tools, not the indexed description.