1966 review round 1: Composed counts the bindings written or rewritten from fields; wrap Take's comment
mesh/delivery merged: source.main moved to novox/mesh-delivery@2f1b60f2a231
mesh/check checking 7db5b0dfe479 on 2f1b60f2a231
mesh/delivery merged: source.main moved to novox/mesh-delivery@2f1b60f2a231
mesh/check checking 7db5b0dfe479 on 2f1b60f2a231
Builds: design 25 bindings-first-view §6, §8, §9 Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
This commit is contained in:
@@ -3165,8 +3165,11 @@ func TestGrants(t *testing.T) {
|
|||||||
want: map[string]string{}, status: [3]int{0, 0, 1}, said: map[string]string{}},
|
want: map[string]string{}, status: [3]int{0, 0, 1}, said: map[string]string{}},
|
||||||
// §9 (1966/AC203-3..): an answer no entry of which carries a binding.
|
// §9 (1966/AC203-3..): an answer no entry of which carries a binding.
|
||||||
{name: "§9 a key-value entry the bus holds is composed from the answer's fields, and said once per answer", answer: []any{oldBusModule},
|
{name: "§9 a key-value entry the bus holds is composed from the answer's fields, and said once per answer", answer: []any{oldBusModule},
|
||||||
want: map[string]string{"late": "mod-x_late"}, status: [3]int{1, 0, 1}, composed: 1, noted: 2, again: []any{oldBusModule},
|
want: map[string]string{"late": "mod-x_late"}, status: [3]int{1, 0, 1}, composed: 0, noted: 2, again: []any{oldBusModule},
|
||||||
wantAgn: map[string]string{"late": "mod-x_late"}},
|
wantAgn: map[string]string{"late": "mod-x_late"}},
|
||||||
|
{name: "§9 an entry an event named since the ask is not written, so it is not counted composed", answer: []any{oldBusModule},
|
||||||
|
during: func(st *setup) { hear(st, "created", "late", "mod-x_event") }, want: map[string]string{"late": "mod-x_event"},
|
||||||
|
status: [3]int{0, 0, 1}, noted: 1},
|
||||||
{name: "§9 an object-store entry is composed with its object store", answer: []any{noBinding("media", "object-store", "OBJ_", true)},
|
{name: "§9 an object-store entry is composed with its object store", answer: []any{noBinding("media", "object-store", "OBJ_", true)},
|
||||||
want: map[string]string{"media": "mod-x_media"}, status: [3]int{1, 0, 1}, composed: 1, noted: 1},
|
want: map[string]string{"media": "mod-x_media"}, status: [3]int{1, 0, 1}, composed: 1, noted: 1},
|
||||||
{name: "§9 a stream and a ledger are left unbound and logged", answer: []any{noBinding("s", "stream", "", true), noBinding("l", "ledger", "", true)},
|
{name: "§9 a stream and a ledger are left unbound and logged", answer: []any{noBinding("s", "stream", "", true), noBinding("l", "ledger", "", true)},
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ type BindingsStatus struct {
|
|||||||
Listed int `json:"listed"`
|
Listed int `json:"listed"`
|
||||||
Written int `json:"written"`
|
Written int `json:"written"`
|
||||||
Rewritten int `json:"rewritten"`
|
Rewritten int `json:"rewritten"`
|
||||||
// Composed is how many entries of the last answer had their binding composed from the answer's own fields, and Unbound
|
// Composed is how many of the bindings the last answer wrote or rewrote were composed from its own fields, and Unbound
|
||||||
// the entries it left unbound, `<module>/<local name> (<storage type>)`: both only for an answer no entry of which
|
// the entries it left unbound, `<module>/<local name> (<storage type>)`: both only for an answer no entry of which
|
||||||
// carries `binding` (§9).
|
// carries `binding` (§9).
|
||||||
Composed int `json:"composed"`
|
Composed int `json:"composed"`
|
||||||
@@ -329,7 +329,7 @@ func (v *BindingsView) apply(p *Part, raw json.RawMessage) error {
|
|||||||
}
|
}
|
||||||
entries, composed, unbound := v.compose(answer.Entries)
|
entries, composed, unbound := v.compose(answer.Entries)
|
||||||
p.bindMu.Lock()
|
p.bindMu.Lock()
|
||||||
written, rewritten, err := v.take(p, entries, composed)
|
written, rewritten, fromFields, err := v.take(p, entries, composed)
|
||||||
p.bindMu.Unlock()
|
p.bindMu.Unlock()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -340,7 +340,7 @@ func (v *BindingsView) apply(p *Part, raw json.RawMessage) error {
|
|||||||
v.st.Answered = v.now()
|
v.st.Answered = v.now()
|
||||||
v.st.Listed = len(answer.Entries)
|
v.st.Listed = len(answer.Entries)
|
||||||
v.st.Written, v.st.Rewritten = written, rewritten
|
v.st.Written, v.st.Rewritten = written, rewritten
|
||||||
v.st.Composed, v.st.Unbound = len(composed), unbound
|
v.st.Composed, v.st.Unbound = fromFields, unbound
|
||||||
status := v.statusLocked()
|
status := v.statusLocked()
|
||||||
v.mu.Unlock()
|
v.mu.Unlock()
|
||||||
if wasRaised {
|
if wasRaised {
|
||||||
@@ -401,7 +401,7 @@ func composeBinding(e meshbroker.Held) (*meshbroker.Binding, bool) {
|
|||||||
// take writes the bindings of the entries an event did not name since the ask was sent, keeps every binding the answer does
|
// take writes the bindings of the entries an event did not name since the ask was sent, keeps every binding the answer does
|
||||||
// not list and raises its unlisted condition, and answers how many bindings it wrote and rewrote; composed names the
|
// not list and raises its unlisted condition, and answers how many bindings it wrote and rewrote; composed names the
|
||||||
// entries whose binding compose gave them. The caller holds the part's bindMu.
|
// entries whose binding compose gave them. The caller holds the part's bindMu.
|
||||||
func (v *BindingsView) take(p *Part, entries []meshbroker.Held, composed map[string]bool) (written, rewritten int, err error) {
|
func (v *BindingsView) take(p *Part, entries []meshbroker.Held, composed map[string]bool) (written, rewritten, fromFields int, err error) {
|
||||||
v.mu.Lock()
|
v.mu.Lock()
|
||||||
touched := copyOf(v.touched)
|
touched := copyOf(v.touched)
|
||||||
v.mu.Unlock()
|
v.mu.Unlock()
|
||||||
@@ -425,7 +425,7 @@ func (v *BindingsView) take(p *Part, entries []meshbroker.Held, composed map[str
|
|||||||
}
|
}
|
||||||
b, berr := p.bound(module)
|
b, berr := p.bound(module)
|
||||||
if berr != nil {
|
if berr != nil {
|
||||||
return written, rewritten, berr
|
return written, rewritten, fromFields, berr
|
||||||
}
|
}
|
||||||
changed := false
|
changed := false
|
||||||
for _, e := range byModule[module] {
|
for _, e := range byModule[module] {
|
||||||
@@ -447,6 +447,9 @@ func (v *BindingsView) take(p *Part, entries []meshbroker.Held, composed map[str
|
|||||||
}
|
}
|
||||||
b.Bindings[e.LocalName] = bind
|
b.Bindings[e.LocalName] = bind
|
||||||
changed = true
|
changed = true
|
||||||
|
if composed[localKey(module, e.LocalName)] {
|
||||||
|
fromFields++
|
||||||
|
}
|
||||||
if had {
|
if had {
|
||||||
rewritten++
|
rewritten++
|
||||||
v.logf("the binding of %s %s was rewritten, the cause %s", module, e.LocalName, cause)
|
v.logf("the binding of %s %s was rewritten, the cause %s", module, e.LocalName, cause)
|
||||||
@@ -458,11 +461,11 @@ func (v *BindingsView) take(p *Part, entries []meshbroker.Held, composed map[str
|
|||||||
if changed {
|
if changed {
|
||||||
raw, _ := json.Marshal(b)
|
raw, _ := json.Marshal(b)
|
||||||
if _, perr := p.Store.Put(StateMemberships, BoundKey(module), raw); perr != nil {
|
if _, perr := p.Store.Put(StateMemberships, BoundKey(module), raw); perr != nil {
|
||||||
return written, rewritten, fmt.Errorf("its own %s %s cannot be written: %w", StateMemberships, BoundKey(module), perr)
|
return written, rewritten, fromFields, fmt.Errorf("its own %s %s cannot be written: %w", StateMemberships, BoundKey(module), perr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return written, rewritten, v.unlisted(p, listed, touched)
|
return written, rewritten, fromFields, v.unlisted(p, listed, touched)
|
||||||
}
|
}
|
||||||
|
|
||||||
// unlisted keeps every binding the answer does not list and raises its condition, one per binding; a binding it lists again
|
// unlisted keeps every binding the answer does not list and raises its condition, one per binding; a binding it lists again
|
||||||
|
|||||||
@@ -239,8 +239,8 @@ func (r *Receiver[M]) arm(id string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Take takes one chunk of a part from the transfer's opener: chunks of a part arrive in sequence from 0, the last
|
// Take takes one chunk of a part from the transfer's opener: chunks of a part arrive in sequence from 0, the last
|
||||||
// marked, and a chunk 0 again starts the part afresh (its earlier chunks are dropped); the whole part must hash to its digest, else its chunks are dropped and the part is lacked again. Belongs,
|
// marked, and a chunk 0 again starts the part afresh (its earlier chunks are dropped); the whole part must hash to its
|
||||||
// when given, refuses a transfer the caller's own shape says is not this call's (another seat's, say). When the last
|
// digest, else its chunks are dropped and the part is lacked again. Belongs, when given, refuses a transfer the caller's own shape says is not this call's (another seat's, say). When the last
|
||||||
// lacked part arrives the transfer ends: the caller's check, then its store.
|
// lacked part arrives the transfer ends: the caller's check, then its store.
|
||||||
func (r *Receiver[M]) Take(id, opener, digest string, sequence int, last bool, data []byte, belongs func(Transfer[M]) error) (Received, error) {
|
func (r *Receiver[M]) Take(id, opener, digest string, sequence int, last bool, data []byte, belongs func(Transfer[M]) error) (Received, error) {
|
||||||
t, found, err := r.Transfers.Get(id)
|
t, found, err := r.Transfers.Get(id)
|
||||||
|
|||||||
Reference in New Issue
Block a user