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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
#!/usr/bin/env python3
"""A stand-in compute worker for the dev mesh.
The broker asks a worker three things and nothing else: are you alive
(`/health`), what are you and what do you charge (`/info`), and run this
(`/execute`). That is the whole contract, so this file is the whole worker --
there is no model, no GPU and no scheduler behind it.
Why a mock rather than the real thing: this mesh exists to make *identity and
money* observable, and a real worker would drown that in model downloads and
CUDA. Every field below is env-configurable precisely so four nodes can differ
in the ways the broker actually routes on.
Two fields are load-bearing and easy to get wrong:
* `worker_type` MUST be present. `discovery.rs` accepts a localhost worker
only `if info.worker_type.is_some()` -- omit it and the broker finds the
port, gets a 200, and silently declines to register it. The mesh then comes
up healthy with zero workers.
* `price_per_hour` MUST be non-zero. A free worker makes remote execution
cost nothing, which makes reserve/commit indistinguishable from a no-op --
and the reserve/commit path is the thing this mesh was built to watch.
`sanitize_price` clamps to (0, 1000], so a zero here silently becomes the
3.6 default rather than an error.
`resources` and `pricing` are nested objects, not flat keys. The flat spelling
(`cpus_total` at the top level) is a different message -- what a broker sends a
*peer* -- and a worker that answers in it parses as all-defaults.
"""
"""Env var, falling back when unset OR set-but-empty.
Compose writes an empty string for an interpolated variable that is not in
the environment, so `os.environ.get(name, default)` would hand back "" and
`float("")` would take the container down at boot.
"""
=
return
=
=
= # peers dial this by node IP, not loopback
# How long /execute pretends to work. Default 0 -- instant, for throughput runs.
#
# Duration is not cosmetic here, it is the only input to metering. The broker
# charges `(price_per_hour / 3600 * duration_secs).max(min_charge)`
# (broker/worker.rs), so with min_charge 0.01 every job shorter than the
# breakeven costs exactly the floor: 20s at 1.80/hr, 10s at 3.60, 5s at 7.20.
# A mesh of instant jobs therefore bills a constant, and a completely wrong
# duration-to-cost calculation would produce identical output. Being able to
# exceed the floor is what makes metering falsifiable.
#
# A sleep rather than a spin: the broker meters wall-clock, which is exactly
# what a sleep produces, and burning CPU on the host would make concurrent runs
# contend with each other and with the brokers -- turning a billing measurement
# into a benchmark of this laptop.
=
= 1024 ** 3
# One /info body, built once at boot. Cheap, and it means every probe in a
# node's lifetime gets a byte-identical answer -- a worker whose advertised
# resources flickered would make routing decisions impossible to reproduce.
=
= # keep-alive; the broker reuses connections
return
# Drain the body even though it is unused. The payload the broker
# forwards is opaque to a worker this simple, but leaving it unread
# desynchronises the keep-alive stream and the next request on the
# connection parses as garbage.
=
=
# Per-request duration, so one running mesh can be billed across a range
# of durations without a restart per value. The body is the only channel
# available: the broker forwards it to the worker untouched, while
# request headers are the broker's own protocol and do not pass through.
=
=
=
# The broker may hand the payload over wrapped in an envelope, so look
# one level down as well as at the top. Unknown shapes fall back to the
# env default rather than erroring -- a malformed body is a caller's
# problem, not a reason to fail a job the broker has already paid for.
=
pass
break
# Name itself in the reply. This is what makes routing legible: the
# answer says which of the four machines actually ran the job, and that
# is exactly the fact a mesh test needs and a status code cannot carry.
# One line per request at this size is noise that buries the broker's
# own logging, which is what anyone reading `compose logs` is after.
pass
=