package versions import ( "context" "fmt" ) // The registry seats' events the builder hears on its durable consumer of each `.events` (design 51 *How a // publish ends*, DLV-B4). const ( HeardPublished = "published" HeardRefused = "refused" HeardRemoved = "removed" HeardKept = "kept" ) // Outcome is the body of a registry seat's published, refused and removed (mesh-contracts parts/registry Outcome), the // fields the builder reads. type Outcome struct { Name string `json:"name"` Version string `json:"version,omitempty"` Digest string `json:"digest"` Kind string `json:"kind"` Holder string `json:"holder"` Reason string `json:"reason,omitempty"` // Tags are, on kept, the other tags still naming its digest. Tags []string `json:"tags,omitempty"` } // RemoveOutcome is what a seat's remove answered: kept whole (another tag names its digest), with why and those tags; or // asked, the seat saying removed on its events. type RemoveOutcome struct { Kept bool Reason string Tags []string } // keep marks a tagged version kept by its seat, so it is asked no more. func (n *Numberer) keep(ctx context.Context, e Entry, reason string, tags []string) error { if reason == "" { reason = "shared-digest" } _, err := n.Versions.Mark(ctx, e.Name, e.Version, func(x *Entry) { x.State, x.Reason, x.KeptWith = Kept, reason, append([]string(nil), tags...) }) return err } // Heard takes one seat event in: a numbered version's entry turns published (with its digest when it held none), // refused with the holder's reason, removed with its reason and the event's id, or kept (another tag names its digest) // with the other tags; a by-digest publish (no version) // marks nothing. It answers the names waiting on their floor that the event wakes: a `published` says the seat // answers (design 51 *The floor*). func (n *Numberer) Heard(ctx context.Context, seat, event, id string, o Outcome) ([]string, error) { var wake []string if event == HeardPublished && n.Waits != nil { wake = n.Waits.Wake(WakePublished, seat, "", "") } if o.Version == "" { return wake, nil } var change func(*Entry) switch event { case HeardPublished: change = func(e *Entry) { e.State, e.Reason = Published, "" if e.Digest == "" { e.Digest = o.Digest } } case HeardRefused: change = func(e *Entry) { if e.State != Published { e.State, e.Reason, e.RefusedDigest = Refused, o.Reason, o.Digest } } case HeardRemoved: change = func(e *Entry) { e.State, e.Reason, e.RemovedBy = Removed, o.Reason, id } case HeardKept: change = func(e *Entry) { if e.State != Removed { e.State, e.Reason, e.KeptWith = Kept, o.Reason, append([]string(nil), o.Tags...) if e.Reason == "" { e.Reason = "shared-digest" } } } default: return wake, fmt.Errorf("%s says %q, which the builder does not hear", seat, event) } if _, err := n.Versions.Mark(ctx, o.Name, o.Version, change); err != nil { return wake, fmt.Errorf("%s's %s of %s@%s: %w", seat, event, o.Name, o.Version, err) } return wake, nil }