1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
//! The thread a window's searches run on (§8.5) — never the frame, and since
//! bl-44e9 **over the wire** (REMOTE §1.2, §9.7).
//!
//! The frame renders published values and derives nothing (§7.2); a search walks
//! every transcript in the world, so it is the derivation worker's shape applied
//! to a second question: the frame *asks* through the
//! [`SearchCell`](crate::state::SearchCell) and renders whatever answer has
//! landed, exactly as it renders whatever snapshot has landed. There is no
//! frame-side wait to make the window stutter, and no request channel — the cell
//! is both directions.
//!
//! **What bl-44e9 changed is where the walk happens, and nothing else.** The
//! window read its own snapshot here; it asks the engine now, like every other
//! read the window makes. It stays a thread of its own, and §9.7 weighed exactly
//! that: `Query::Search` walks every transcript in the world and a standing
//! question is re-asked every `ASK_PERIOD`, so riding the
//! [`asker`](crate::wire::asker) would turn a once-per-ask walk into a 2 Hz one
//! **and** put it in front of every other surface's answer — the poster's own
//! ruling (*"an act runs as long as the verb behind it"*) pointed at a read. So
//! the mechanism is unchanged and the read crosses; the win is §1.2 compliance,
//! not one fewer thread.
//!
//! It is a thread of its own rather than a stage of the derivation pass for its
//! original reason too: a long search must not delay a re-derivation — staleness
//! is what the §7.3 wound banner is *for*, and a search is not a wound.
//!
//! **A refusal is an unreadable source.** The engine can say no — an unresolved
//! world, a dead listener — and [`Found::unreadable`] is already *"each
//! unreadable source, named with why"*, which is exactly what that sentence is.
//! So a refused search paints the reason where a mangled transcript would have,
//! with no second state and no false *"no matches"*.
//!
//! **The abandon predicate went with the walk.** In process a superseded search
//! stopped mid-walk; over the wire the engine finishes what it was asked and the
//! answer for a question nobody is asking any more is dropped on publish. The
//! cost is one wasted walk on the engine, and the alternative — a cancel the
//! boundary would have to carry — is a mechanism for an optimisation.
//!
//! The other two seats need none of this. `yog gesture` and the deposit consumer
//! are already off-frame, and a process that asked has nothing else to do, so
//! they run [`run`](super::run) straight through
//! [`answer`](crate::boundary::answer::answer). One engine, three seats.
use Found;
use crateReply;
use crate;
use crateSearchCell;
use crateSeat;
use Arc;
use ;
use JoinHandle;
use Duration;
/// How often the searcher looks for an ask. A latency knob only: an ask waits,
/// it never rots — the same reading the §8.5 consumer poll gets.
const SEARCH_POLL: Duration = from_millis;
/// One window's searcher: its seat on the wire, and the cell it is asked
/// through. Built by [`Engine::searcher`](crate::engine::Engine::searcher) so
/// the model never spawns its own thread — a test drives [`pass`](Self::pass) by
/// hand, which is the same reason `Engine::asker` hands back a value.
/// The searcher thread's handle; [`Drop`] signals stop, unparks and joins.