macula_download behaviour (macula v10.1.1)
View SourceBehaviour for supervised content downloads (the get/fetch side).
start_link/4,5 returns immediately with a pid, delivers the outcome to Module:handle_downloaded/2, and publishes sharing.get_started_v1 / sharing.get_completed_v1 mesh facts around the transfer — including outcome => cancelled if the download is cancelled before the get resolves.
This is content sharing, not general-purpose RPC streaming — see macula_streamer / macula_stream_sink for that (streaming.* facts belong to that pair).
Real cancel, real underneath
Internally this drives macula_content_transfer (PLAN_PUSH_UPLOAD.md Phase 4) rather than a blocking macula:get_content/2 call run in a linked worker — see macula_feeder's module doc for the full reasoning (the same gap, the same fix, mirrored here): a blocking call gives cancel/1 no addressable handle to the actual transfer, so it could only ever kill the local worker waiting on it, leaving the underlying macula_content_transfer orphaned — running to completion or sitting resolved-but-never-reaped forever, since nothing links a gen_server:call caller's death to the callee. This module now holds the macula_content_transfer pid directly (a content_transfer state field, alongside the lightweight resolve + await proxy worker that reports it back) so cancel/1 reaches it for a real, peer-visible QUIC RESET_STREAM abort. The share_id this module already minted for its own sharing.* mesh facts is threaded through as macula_content_transfer's own share_id too.
Direct-dial
start_link/4,5 fetches through the pool's own connected link (whichever pick_connected_link/1 picks), reaching a copy via that station's 1-hop peer relay. start_link_direct/4,5 is the direct-dial counterpart: it resolves Mcid's provider from its signed content_announcement (published automatically by the provider's station on receipt — nothing to advertise explicitly, no direct-dial counterpart needed on the macula_feeder side, a fast, non-addressable DHT lookup that stays a plain blocking call inside the resolve+await proxy — nothing has ever needed to cancel mid-resolve) and dials that station directly, in one hop, via macula_content_transfer:start_get_station/5, instead of depending on the caller's own station being able to reach it via relay. Only chunked content is discoverable this way — see macula:find_content_providers/2. See macula_direct_dial's module doc, "Content" section, for the trust model (deliberately lighter than RPC's — content is self-verifying by hash).
Example
-module(doc_download).
-behaviour(macula_download).
-export([init/1, handle_downloaded/2]).
init(Parent) -> {ok, Parent}.
handle_downloaded(Result, Parent) ->
Parent ! {downloaded, Result},
{stop, normal, Parent}. {ok, Pid} = macula_download:start_link(doc_download, Pool, Realm,
Mcid, self()).
Summary
Functions
Cancel an in-flight download. Publishes sharing.get_completed_v1 with outcome => cancelled if the get had not resolved yet.
Start a download. Fetches Mcid via Pool.
As start_link/4, with Args passed to Module:init/1.
As start_link/4, but resolves and dials the MCID's provider directly instead of fetching through the pool's existing links. See the "Direct-dial" section above.
As start_link_direct/4, with Args passed to Module:init/1.
Callbacks
Functions
-spec cancel(pid()) -> ok.
Cancel an in-flight download. Publishes sharing.get_completed_v1 with outcome => cancelled if the get had not resolved yet.
-spec start_link(module(), macula:pool(), macula:realm(), macula:mcid()) -> {ok, pid()} | {error, term()}.
Start a download. Fetches Mcid via Pool.
-spec start_link(module(), macula:pool(), macula:realm(), macula:mcid(), term()) -> {ok, pid()} | {error, term()}.
As start_link/4, with Args passed to Module:init/1.
-spec start_link_direct(module(), macula:pool(), macula:realm(), macula:mcid()) -> {ok, pid()} | {error, term()}.
As start_link/4, but resolves and dials the MCID's provider directly instead of fetching through the pool's existing links. See the "Direct-dial" section above.
-spec start_link_direct(module(), macula:pool(), macula:realm(), macula:mcid(), term()) -> {ok, pid()} | {error, term()}.
As start_link_direct/4, with Args passed to Module:init/1.