Conversation
…data Session persistence refuses to serialize a torrent whose storage factory isn't a FilesystemStorageFactory, and persistence is on by default - so a session configured with any other storage fails every add outright. The check is about a type, but what it is protecting is a promise. The persisted record is the torrent, an output folder, a file selection and a paused flag, with a have-bitfield beside it; it names no storage at all. A restart replays the record through add_torrent, which builds the session's default storage. So a storage is persistable when two things hold. One: the storage the restart builds reaches the same data - free for the filesystem one, since the record carries the output folder and the bytes are laid out as the torrent's own files. Two: the data is still there when the next process asks, because the have-bitfield outlives the process and the restart takes it at its word - it hashes one piece per file plus at most 64 sampled ones, of a torrent however large. Neither of those is a property of a type, and both are things only the storage knows. StorageFactory::ensure_persistable() is that promise. It defaults to no and names the factory that didn't make it, so a storage persistence can't handle is refused when the torrent is added rather than at the next restart, and it forwards through boxing and through the middlewares that forward is_type_id - losing it there would refuse a perfectly persistable storage, or worse, invent a promise nobody made. FilesystemStorageFactory promises it, so the default path is unchanged. The tests drive all three cases end to end: a storage that keeps the torrent as one flat blob of its own, persisted and restored across a session restart with a factory rebuilt from scratch; a storage that doesn't promise, refused at add time with a message naming it; and the filesystem storage, asserted rather than assumed. Co-Authored-By: Claude Opus 5 <[email protected]>
zond
force-pushed
the
storage-persistable-promise
branch
from
September 7, 2026 13:46
007ac0b to
b5b5188
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Session persistence refuses to serialize a torrent whose storage factory isn't a FilesystemStorageFactory, and persistence is on by default - so a session configured with any other storage fails every add outright.
The check is about a type, but what it is protecting is a promise. The persisted record is the torrent, an output folder, a file selection and a paused flag, with a have-bitfield beside it; it names no storage at all. A restart replays the record through add_torrent, which builds the session's default storage. So a storage is persistable when two things hold. One: the storage the restart builds reaches the same data - free for the filesystem one, since the record carries the output folder and the bytes are laid out as the torrent's own files. Two: the data is still there when the next process asks, because the have-bitfield outlives the process and the restart takes it at its word - it hashes one piece per file plus at most 64 sampled ones, of a torrent however large. Neither of those is a property of a type, and both are things only the storage knows.
StorageFactory::ensure_persistable() is that promise. It defaults to no and names the factory that didn't make it, so a storage persistence can't handle is refused when the torrent is added rather than at the next restart, and it forwards through boxing and through the middlewares that forward is_type_id - losing it there would refuse a perfectly persistable storage, or worse, invent a promise nobody made. FilesystemStorageFactory promises it, so the default path is unchanged.
The tests drive all three cases end to end: a storage that keeps the torrent as one flat blob of its own, persisted and restored across a session restart with a factory rebuilt from scratch; a storage that doesn't promise, refused at add time with a message naming it; and the filesystem storage, asserted rather than assumed.
Also created by my Claude Fable. This one is a bit of a design change, but I think it makes sense, other storages than the default FS storage are able to restart, right?