Files
mesh-delivery/modules/mesh-delivery-builder/internal/versions/publish.go
T
jschoubben 00903e9149 F-delivery 7: the builder's old-form window steps by mesh-sdk's delivery.StepWindow
A read naming no node (an empty node_haves, the placement not read yet) closed the window for good (security
review F3, second of a kind). The window embeds delivery.WindowHeld and steps by the shared rule, named being
the placement's nodes before any is dropped. The builder's expiring keys share one state, bounds (the publish
bound of F-delivery 5 renamed), for the old-form bound next.

Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
2026-11-04 16:40:44 +01:00

51 lines
2.6 KiB
Go

package versions
import (
"strings"
"time"
)
// **A publish that ends badly is loud** (design 51 *Health and conditions*; review round 1): the builder raises the
// finding publish-refused when a holder says refused, and publish-unanswered when a version it built and numbered is
// neither published nor refused within PublishBound. Each is about the name, so a later published of any version of it
// clears both. A seat's outcome that does not read is the finding seat-outcome-unread about the seat, cleared by its
// next outcome that reads.
//
// The bound is a key of the builder's state bounds per version (PublishBoundKey), written with its own time to live
// when the build is done and the version is still numbered, deleted at the holder's word; the bus's marker of its end,
// heard on the watch, is what raises publish-unanswered while the version is still numbered. No timer.
const (
// BoundsState is the builder's state of its expiring keys, each with its own time to live: a publish's bound
// (PublishBoundKey) and a node's seven days holding the old form's window (OldFormBoundKey). Its end, the bus's
// marker heard on the watch, is what acts.
BoundsState = "bounds"
BoundsBucket = "mesh-delivery-builder_bounds"
// PublishBound is the build module's own wait for the holder's word (design 51 *How a publish ends*: at most
// 10 minutes), so a version unanswered past it is one the holder never answered.
PublishBound = 10 * time.Minute
PublishRefused = "publish-refused"
PublishUnanswered = "publish-unanswered"
SeatOutcomeUnread = "seat-outcome-unread"
)
// The prefixes of the keys of BoundsState.
const (
publishBoundPrefix = "publish."
oldFormBoundPrefix = "old-form."
)
// PublishBoundKey is the bound of name's version: `publish.<versions key>`.
func PublishBoundKey(name, version string) string { return publishBoundPrefix + Key(name, version) }
// OldFormBoundKey is the bound of node's seven days holding the old form's window: `old-form.<node>`.
func OldFormBoundKey(node string) string { return oldFormBoundPrefix + EscapeToken(node) }
// PublishBoundOf is the versions key a publish's bound names, and whether key is one; a key that is no publish's
// bound is an old form's (IsOldFormBound) or nothing the builder wrote.
func PublishBoundOf(key string) (string, bool) { return strings.CutPrefix(key, publishBoundPrefix) }
// IsOldFormBound says key is a node's bound of the old form's window: its end steps the window, which raises the
// finding for every node past FindingAfter.
func IsOldFormBound(key string) bool { return strings.HasPrefix(key, oldFormBoundPrefix) }