Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .jules/bolt.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,7 @@
## 2024-03-16 - Batch JSON File I/O Operations
**Learning:** When using JSON file-backed repositories, iterating over items sequentially and calling `save_item` or `record_attempt` inside a loop leads to N+1 file read/write operations. This creates a significant performance bottleneck, especially when importing progress snapshots with numerous items and attempts.
**Action:** Prefer batch processing methods (e.g., `save_items`, `record_attempts`) so file-backed adapters can load storage once, update it in memory, and write it back in a single pass.

## 2024-05-25 - [Optimize batch DB operations by avoiding full deserialization]
**Learning:** Fully deserializing and reserializing stored records to domain models for every batch update incurs O(N) CPU overhead, even when only a small subset of records change.
**Action:** To optimize JSON file-backed adapters, modify raw storage dictionary entries in-place for existing items and append new entries, bypassing unnecessary full-collection object instantiation.
Original file line number Diff line number Diff line change
Expand Up @@ -46,15 +46,24 @@ def save_items(self, items: list[LearningItem]) -> None:

storage = self._load_storage()
raw_items = storage.get("items", [])
existing_items = []
if isinstance(raw_items, list):
existing_items = [
_item_from_dict(entry) for entry in raw_items if isinstance(entry, dict)
]
by_id = {existing.id: existing for existing in existing_items}
for item in items:
by_id[item.id] = item
storage["items"] = [_item_to_dict(entry) for entry in by_id.values()]
if not isinstance(raw_items, list):
raw_items = []

new_items_by_id = {str(item.id): _item_to_dict(item) for item in items}

for i in range(len(raw_items)):
entry = raw_items[i]
if isinstance(entry, dict):
entry_id = str(entry.get("id"))
if entry_id in new_items_by_id:
raw_items[i] = new_items_by_id.pop(entry_id)
if not new_items_by_id:
break
Comment on lines +59 to +61

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Update all duplicate IDs in storage

Popping the matched ID and then breaking early means save_items only replaces the first occurrence of a duplicated id in items; any later duplicate entries remain stale. This is a regression from the previous implementation, which rebuilt items from an ID-keyed map and implicitly deduplicated. In repositories that already contain duplicate IDs (for example from seeded data or older/corrupted files), list_items() will now continue returning conflicting versions of the same logical item after an update.

Useful? React with πŸ‘Β / πŸ‘Ž.


for new_item_dict in new_items_by_id.values():
raw_items.append(new_item_dict)

storage["items"] = raw_items
self._save_storage(storage)

def list_attempts(self) -> list[Attempt]:
Expand Down
Loading