Resolves the Markdown notes for a lesson using a generated lessonId → key
map and a BlobStore. The adapter only reads keys the seed generator
has validated via BlobStore.exists; the UI never supplies a key.
The notes Resource is located by comparing content KEYS. Matching on the
resolved URL instead would couple this adapter to the resource adapter
having been given an identically-configured BlobStore: when the two
disagree the lookup returns null and the notes silently disappear with no
error. Keys are configuration-independent, so that failure mode is gone.
Markdown is cached by content key for the process lifetime. Against the
local driver readText is a disk read, but against a bucket it is a network
round trip on every lesson view, and notes only change when the seed is
regenerated — which restarts the process. The cache holds the in-flight
promise rather than the resolved string, so concurrent first views of the
same lesson share one read; a rejected read is evicted so a transient
network error is retried rather than remembered.
Returns the Markdown notes for the given lesson, or null when the
lesson has no Markdown resource. The implementation MUST NOT
accept or infer filesystem paths from caller input.
Driven adapter: filesystem-backed
LessonNotesRepository.Resolves the Markdown notes for a lesson using a generated
lessonId → keymap and aBlobStore. The adapter only reads keys the seed generator has validated viaBlobStore.exists; the UI never supplies a key.The notes
Resourceis located by comparing content KEYS. Matching on the resolved URL instead would couple this adapter to the resource adapter having been given an identically-configuredBlobStore: when the two disagree the lookup returnsnulland the notes silently disappear with no error. Keys are configuration-independent, so that failure mode is gone.Markdown is cached by content key for the process lifetime. Against the local driver
readTextis a disk read, but against a bucket it is a network round trip on every lesson view, and notes only change when the seed is regenerated — which restarts the process. The cache holds the in-flight promise rather than the resolved string, so concurrent first views of the same lesson share one read; a rejected read is evicted so a transient network error is retried rather than remembered.