Skip to content
Merged
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
114 changes: 103 additions & 11 deletions src/artwork/presence.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,16 +45,29 @@
//!
//! # What is deliberately not here
//!
//! THE ABSENCE IS NOT KEPT, AND #51'S THIRD CONDITION IS ABOUT KEEPING IT. That
//! condition asks that a second request for a known-absent image make no network
//! call, which means the first answer was kept.
//! `docs/decisions/0006-the-cache-contract.md` lists what may be cached and an
//! absence is none of the five entries, and
//! THE ABSENCE IS NOT KEPT, AND THIS PARAGRAPH SAID #51'S THIRD CONDITION WAS
//! ABOUT KEEPING IT. That condition read that a second request for a known-absent
//! image makes no network call, which was read here as meaning the first answer
//! had been kept. `docs/decisions/0006-the-cache-contract.md` lists what may be
//! cached and an absence is none of the five entries, and
//! `docs/decisions/0043-a-stale-answer-and-the-freshness-rule-per-kind.md`
//! closes that list by saying a sixth kind is a change to both records. So
//! keeping one is an edit to two landed records rather than a line written here,
//! closes that list by saying a sixth kind is a change to both records. Keeping
//! one is still an edit to two landed records rather than a line written here,
//! and nothing in this module writes to a store.
//!
//! What moved is the condition rather than the records. It was narrowed on
//! 2026-08-30 to what this core can promise: a second ask for a known-absent
//! image within one screenful makes no network call BECAUSE THE ANSWER CARRIES
//! NO ADDRESS FOR ONE TO BE MADE FROM, and nothing about the absence outlives
//! the ask that produced it. That is a property of
//! [`WhatTheItemHas::NoImageOfThisKind`] rather than of a store: a fetch in this
//! core is started from an [`ArtworkRequest`], the request is what
//! [`crate::artwork::address::ArtworkRequest::entry_key`] turns into the key
//! 0053 coalesces on, and an absence produces neither. The test beside this type
//! asks exactly that, with the same two asks for an image that does exist beside
//! it, because an assertion that nothing was fetched proves nothing on its own
//! in a tree that fetches nothing.
//!
//! There is also no request made for the answer that carries one. The transport
//! is #27 and nothing in this tree opens a connection, so a caller receiving
//! [`WhatTheItemHas::AnImage`] receives an address and nothing has been fetched.
Expand Down Expand Up @@ -140,13 +153,23 @@ impl WhatTheItemHas {
mod tests {
//! 0049's sentence about an item with no tag, asked of the three answers.
//!
//! What these cannot ask is #51's third condition. It asks that a second
//! request for a known-absent image make no network call, which needs an
//! absence to have been kept and a request to have been made, and this tree
//! holds neither.
//! THE LAST TWO ASK #51'S THIRD CONDITION AS IT WAS NARROWED, and this
//! comment said no test here could ask it at all. What it could not ask is
//! the condition as first written, which needed an absence to have been kept
//! and a request to have been made. The narrowed one is about the answer
//! carrying no address, which is here.
//!
//! WHAT THEY STILL CANNOT ASK IS ANYTHING ABOUT A WIRE. Nothing in this tree
//! opens a connection, so "no network call" is asserted as "no request and
//! therefore no key to start a fetch from" rather than as a socket that was
//! not opened. The second of the two is what keeps that from being vacuous:
//! the identical loop over an image that does exist starts one fetch and
//! joins it on the second ask.

use super::WhatTheItemHas;
use crate::artwork::address::{DrawnSize, ImageKind, ItemId, NotUsableInARequest};
use crate::artwork::announced::{SharedFetches, WhatTheHoldDid};
use crate::cache::key::{KeySpace, ServerPart};

fn item(id: &str) -> ItemId {
ItemId::from_server(id).expect("the fixture identifier is inside 0049's admitted set")
Expand All @@ -156,6 +179,36 @@ mod tests {
DrawnSize::asked_for(300, 450).expect("300 by 450 is 0050's poster and two rungs")
}

fn space<'a>() -> KeySpace<'a> {
KeySpace {
server: ServerPart::Reported("server-7a1b"),
account: "account-3c9d",
device: "device-9f2c",
}
}

/// Asks for one image twice, holding a fetch for every answer that carries a
/// request, and answers how many fetches that started.
///
/// One helper for both tests below so that the only difference between them
/// is the tag, which is what makes the second one a near miss of the first
/// rather than a differently written test that happens to pass.
fn two_asks_for(tag: Option<&str>) -> (SharedFetches, Vec<WhatTheHoldDid>) {
let space = space();
let mut fetches = SharedFetches::none();
let mut held = Vec::new();

for _ in 0..2 {
let answer =
WhatTheItemHas::of_kind(&item("item-one"), ImageKind::Primary, tag, size());
if let Some(request) = answer.request() {
held.push(fetches.hold(request.entry_key(&space)));
}
}

(fetches, held)
}

/// An item whose metadata carried no tag for a kind produces no request at
/// all, which is 0049's sentence and the whole of #51's first condition.
#[test]
Expand Down Expand Up @@ -239,6 +292,45 @@ mod tests {
assert_eq!(one, another);
}

/// #51's third condition as it was narrowed on 2026-08-30. A second ask for
/// a known-absent image within one screenful makes no network call, because
/// the answer carries no address for one to be made from.
///
/// Nothing is kept between the two asks: the loop holds no state of its own
/// and this module writes to no store, so the second answer is derived again
/// rather than remembered. What it is derived from is the item's metadata,
/// which 0006 does list as a cached kind, so the absence follows from
/// something the cache already holds without becoming a sixth kind in it.
#[test]
fn a_second_ask_for_a_known_absent_image_starts_no_fetch() {
let (fetches, held) = two_asks_for(None);

assert!(held.is_empty(), "an absence produced a request to hold");
assert_eq!(fetches.in_flight(), 0);
}

/// The same two asks for an image that does exist, which is what keeps the
/// assertion above from being about a loop that fetches nothing whatever it
/// is given.
///
/// One fetch is started and the second ask joins it rather than starting a
/// second, which is 0053 coalescing on the entry key. Change `of_kind` to
/// answer with a request where the metadata carried no tag and the test
/// above goes red while this one does not move.
#[test]
fn the_same_two_asks_for_an_image_that_exists_share_one_fetch() {
let (fetches, held) = two_asks_for(Some("abc123"));

assert_eq!(
held,
[
WhatTheHoldDid::StartedTheFetch,
WhatTheHoldDid::JoinedTheFetch
]
);
assert_eq!(fetches.in_flight(), 1);
}

/// The answer is per kind, over the whole set the type declares.
///
/// WHAT THIS DOES NOT ASSERT IS THAT AN ABSENCE CANNOT WIDEN, and the name
Expand Down
Loading