Skip to content

fix(history): attach download history rows to the audiobook they belong to - #983

Open
m4bard wants to merge 1 commit into
Listenarrs:canaryfrom
m4bard:fix/history-audiobook-id
Open

m4bard wants to merge 1 commit into
Listenarrs:canaryfrom
m4bard:fix/history-audiobook-id

Conversation

@m4bard

@m4bard m4bard commented Sep 14, 2026

Copy link
Copy Markdown

Fixes #974.

DownloadHistoryService.AddUnifiedAsync never sets History.AudiobookId. It writes the value into AudiobookExternalId instead, because the object it is handed carries the audiobook id as a Guid? while History.AudiobookId is int?, and the Guid cannot go in that column. The per-book History tab (AudiobookDetailView.vue) filters on History.AudiobookId, so no download event has ever been able to match it, and the tab is empty for every book. There is a second contributing gap: the one production caller of RecordGrabbedAsync already holds the audiobook id as an int? and, having no Guid to convert, calls the method with no audiobook id at all.

The library key is int everywhere else that matters (Audiobook.Id, History.AudiobookId, HistoryQuery.AudiobookId, the repository's GetByAudiobookIdAsync). The Guid? on DownloadHistory is the outlier, and as far as I can tell it has no production caller left. So this branch takes the audiobook id as int? instead of converting a Guid:

  • IDownloadHistoryService.RecordGrabbedAsync and RecordImportedAsync take int? audiobookId.
  • AddUnifiedAsync writes that id to History.AudiobookId directly; AudiobookExternalId keeps its existing meaning.
  • DownloadService passes the audiobookId it already holds at the grab site, guarded so zero or negative stays null.

No migration. Changing DownloadHistory.AudiobookId from Guid? to int? would also change the DownloadHistories table's column type and pull in other callers, none of which is needed to make the History tab work.

Four tests added to DownloadHistoryServiceTests, three of which read back through the same GetByAudiobookIdAsync query the History tab actually uses rather than asserting on the column directly, plus one confirming a grab with no audiobook id leaves the row unattached. Reverting the single production line that sets History.AudiobookId fails three of the four.

Suite run against current canary (upstream/canary at a630572e9, which this branch is built on): targeted filter DownloadHistoryServiceTests, 11 passed, 0 failed.

Note from the issue: this touches the same method as the separate Protocol column fix (#973), so the two need applying in a chosen order rather than merged blind. Reproduction steps and the excluded DownloadHashRetrievalService path (which has the identical gap but is out of scope here) are in the issue.

Disclosure: drafted with Claude Code at my direction; I read the cited code at commit a630572 and reviewed this before posting.

DownloadHistoryService.AddUnifiedAsync wrote every download event into the
unified History table without ever setting History.AudiobookId. It put the id
into AudiobookExternalId instead, because the id it had to hand was the Guid? on
DownloadHistory while History.AudiobookId is an int?.

The per-book History tab reads through EfHistoryRepository.GetByAudiobookIdAsync,
which filters on the int? column. No row written by AddUnifiedAsync could ever
match it, so grabs, imports and failures never appeared under a book. That holds
for Grabbed rows that already exist, not only for failures.

The library key is an int: Audiobook.Id is int, History.AudiobookId is int?, and
DownloadService already carries the audiobook as int?. The Guid? on
DownloadHistory is the odd one out and is legacy compatibility plumbing with no
production caller, so this takes the audiobook id as an int? on
RecordGrabbedAsync and RecordImportedAsync, carries it into AddUnifiedAsync, and
writes it to History.AudiobookId. DownloadService now passes the id it already
holds, which it previously dropped because the Guid? parameter could not take it.

No schema change, so no migration. The legacy DownloadHistories table and its
Guid? column are untouched.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@m4bard
m4bard requested a review from a team September 14, 2026 09:20
@m4bard
m4bard force-pushed the fix/history-audiobook-id branch from 2e79c83 to 32ee37e Compare September 15, 2026 18:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Download history never attaches to an audiobook, so the per-book History tab stays empty

1 participant