package view import ( "encoding/json" "fmt" "git.novox.be/novox/mesh-delivery/modules/mesh-delivery-contracts/go/seats/meshwants" "git.novox.be/novox/mesh-sdk/go/buscalls" ) // The seat mesh-wants' verbs revision and difference as the view's invokes names them: the tiers of a source revision are // read through them and worked out nowhere in the view (design 47 G §512, §186, A-242). const ( RevisionVerb = "seat:" + meshwants.Seat + "." + meshwants.VerbRevision DifferenceVerb = "seat:" + meshwants.Seat + "." + meshwants.VerbDifference ) // WalkMost is the most kept assignment revisions a source revision's revision is looked for through, newest first. const WalkMost = 256 // callSeat asks verb with body through call and reads its declared answer into out. func callSeat(call func(key string, body any) (json.RawMessage, error), verb string, body, out any) error { raw, err := call(verb, body) if err != nil { return fmt.Errorf("%s: %w", verb, err) } answer, said, ok := buscalls.Unwrap(raw) if !ok { return fmt.Errorf("%s answered: %s", verb, said) } if err := json.Unmarshal(answer, out); err != nil { return fmt.Errorf("the answer of %s does not read: %w", verb, err) } return nil } // AssignmentOf asks the seat for one kept assignment graph revision (0: the trunk's newest). func AssignmentOf(call func(key string, body any) (json.RawMessage, error)) func(revision int64) (meshwants.AssignmentRevision, error) { return func(revision int64) (meshwants.AssignmentRevision, error) { var a meshwants.RevisionAnswer err := callSeat(call, RevisionVerb, meshwants.RevisionInput{Revision: revision}, &a) return a.Revision, err } } // DifferenceOf asks the seat for the difference of two kept revisions. func DifferenceOf(call func(key string, body any) (json.RawMessage, error)) func(from, to int64) (meshwants.Difference, error) { return func(from, to int64) (meshwants.Difference, error) { var d meshwants.Difference err := callSeat(call, DifferenceVerb, meshwants.DifferenceInput{From: from, To: to}, &d) return d, err } } // revisionsOf finds the kept assignment revisions that carry the source revision for a watched branch: to the first of them // (the one whose change it is) and from the revision kept before it, walking back from the newest. A zero from says there is // none before it. func (r Reader) revisionsOf(source uint64) (from, to int64, err error) { if r.Assignment == nil || r.Difference == nil { return 0, 0, fmt.Errorf("the assigner's revisions cannot be read here") } newest, err := r.Assignment(0) if err != nil { return 0, 0, fmt.Errorf("the assigner's newest revision: %w", err) } carries := func(rev meshwants.AssignmentRevision) bool { for _, c := range rev.Catalogs { if c.Source > 0 && uint64(c.Source) == source { return true } } return false } for n, steps := newest.Revision, 0; n >= 1 && steps < WalkMost; n, steps = n-1, steps+1 { rev := newest if n != newest.Revision { if rev, err = r.Assignment(n); err != nil { continue // a revision no longer kept } } if !carries(rev) { if to != 0 { return rev.Revision, to, nil // the kept revision before the first that carries it } continue } to = rev.Revision } if to == 0 { return 0, 0, fmt.Errorf("no kept assignment revision of the assigner carries the source revision %d", source) } return 0, to, nil }