barrel_ngram_corpus_lifecycle (barrel_ngram v0.9.0)

View Source

One-shot corpus open/close coordinator.

Registered under {via, barrel_ngram_registry, {corpus_lock, Corpus}} so open and close for the SAME corpus can never interleave -- the registry's own register_name/2 is already serialized through its own gen_server call, making via-name registration an atomic, reusable per-corpus mutex. Registration happens as part of starting the process, BEFORE init/1 ever runs, so mutual exclusion holds regardless of where the real work runs relative to init/1 returning.

init/1 does NOT run the operation itself -- it hands back control immediately via {continue, run}, deferring the entire open/close body to handle_continue/2. This matters because the coordinator is started via supervisor:start_child(barrel_ngram_corpus_lifecycle_sup, ...): start_child/2 is a synchronous call into the SUPERVISOR's own process, which blocks handling that request until init/1 returns. Running the whole body inside init/1 would block the lifecycle supervisor's mailbox for however long that takes -- unable to process a shutdown request from its own parent during a rest_for_one cascade. Splitting the work into handle_continue/2 keeps init/1 fast regardless.

The result is sent DIRECTLY to the caller (by a reference generated before this process even starts, see barrel_ngram:lifecycle_call/3) rather than relying on this process's own exit reason: a monitor installed after start_child/2 returns can race a fast handle_continue/2 that already finished.

Two runtime persistent_term caches (barrel_ngram_shards) are involved: meta (query-trusted, published ONLY on full success) and pending_meta (discovery-only, published as soon as a request's config is reconciled, before any shard starts) -- see barrel_ngram_shards's moduledoc for why the two are never conflated.

Summary

Functions

handle_call(Msg, From, State)

handle_cast(Msg, State)

handle_continue(_, State)

init(_)

start_link(Caller, ReplyRef, Corpus, Op)

-spec start_link(pid(), reference(), term(), term()) -> {ok, pid()} | {error, term()} | ignore.