Let a module declare a log the controller creates and never removes (ADR 0297)
mesh/merge-gate pass: builds build-agent, mesh-controller, route-proxy → ace, g14, novox, shanks; no bus step; every machine composes with the change as it…
mesh/repo-check pass: its merge-check.sh passed
mesh/delivery superseded: a newer head of the same pull request

The issue tracker's history lasts seven days on the events stream and its
bucket fills toward a cap with no warning (issues 501, 502). A module may
now declare `logs`; the controller creates each as a stream on the bus
(create-or-update, never deleted or recreated, reported when undeclared),
issues it to the owner's assignments in their membership, grants the
runtime exactly the append and direct-read subjects, and raises a
condition when any module's bucket or log reaches 75% of its cap, cleared
below 70%.
This commit is contained in:
jochen
2026-10-11 19:22:43 +02:00
parent fad655532d
commit 7bd61332cb
16 changed files with 1037 additions and 2 deletions
+38
View File
@@ -448,3 +448,41 @@ func (j *JetStream) BucketNames() ([]string, error) {
}
return out, lister.Error()
}
// EnsureLog creates a module's log if it is absent and brings its configuration to match if it is
// present (novox/hq ADR 0297).
//
// **An update, never a delete and recreate**, for a bucket's reason: recreating discards what the log
// holds, and a log is a module's record. A configuration the server will not change in place (its
// storage, say, on a stream made by hand) is said as this assertion's error and the stream is left as
// it is — never removed to be made again.
func (j *JetStream) EnsureLog(l Log) error {
js, err := jetstream.New(j.conn)
if err != nil {
return err
}
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
if _, err := js.CreateOrUpdateStream(ctx, l.Config()); err != nil {
return fmt.Errorf("asserting log %s: %w", l.Stream(), err)
}
return nil
}
// LogStreams is every log stream on the server: every stream whose name starts with LogStreamPrefix.
func (j *JetStream) LogStreams() ([]string, error) {
js, err := jetstream.New(j.conn)
if err != nil {
return nil, err
}
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
lister := js.StreamNames(ctx)
var out []string
for name := range lister.Name() {
if strings.HasPrefix(name, LogStreamPrefix) {
out = append(out, name)
}
}
return out, lister.Err()
}