Answer a send's state only to its caller (issue 1261)
This commit is contained in:
@@ -1312,19 +1312,30 @@ func tellWaits(store SendStore, tell TellOperator, id string, now time.Time) err
|
||||
|
||||
// ---- reading the status -----------------------------------------------------------------------------------------
|
||||
|
||||
// ReadSendStatus is where a send asked with mail_send stands, by its ask id: waiting for the operator, sent,
|
||||
// declined, ended without a choice (expired, refused, cancelled), or not proven. Read from the router's own
|
||||
// record; when the router's word is a close one that was not decided yet, this is also where a send is first
|
||||
// decided (and so sent), exactly once (Decide).
|
||||
func ReadSendStatus(store SendStore, bus AskBus, publish QueuePublish, id string, now time.Time) (map[string]any, error) {
|
||||
// ReadSendStatus is where a send asked with mail_send stands, answered only to the caller that asked for it
|
||||
// (novox/hq ADR 0440 §7, issue 1261): an id no send is kept under, or a send whose own caller differs from the
|
||||
// one asking, answers status "unknown" and nothing else of it — never an error, and never the account,
|
||||
// recipients or subject of a send that is not the caller's own. The sweep, which settles a send regardless of
|
||||
// who asked for it, calls readSendStatus directly instead, never through this caller check.
|
||||
func ReadSendStatus(store SendStore, bus AskBus, publish QueuePublish, id, caller string, now time.Time) (map[string]any, error) {
|
||||
trimmed := strings.TrimSpace(id)
|
||||
req, rev, ok, err := getSend(store, trimmed)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("the send %q cannot be read now (%v); ask again", trimmed, err)
|
||||
}
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("no send %q is kept: the id is the one mail_send gave", trimmed)
|
||||
if !ok || req.Caller != caller {
|
||||
return map[string]any{"status": "unknown"}, nil
|
||||
}
|
||||
return readSendStatus(store, bus, publish, req, rev, now)
|
||||
}
|
||||
|
||||
// readSendStatus is ReadSendStatus's own reading of one send already fetched (req, rev): waiting for the
|
||||
// operator, sent, declined, ended without a choice (expired, refused, cancelled), or not proven. Read from the
|
||||
// router's own record; when the router's word is a close one that was not decided yet, this is also where a
|
||||
// send is first decided (and so sent), exactly once (Decide). It never checks who is asking: ReadSendStatus
|
||||
// does that before calling it, and the sweep (which settles a send no matter who asked for it) calls it
|
||||
// directly.
|
||||
func readSendStatus(store SendStore, bus AskBus, publish QueuePublish, req SendRequest, rev uint64, now time.Time) (map[string]any, error) {
|
||||
out := map[string]any{"ask": req.ID, "account": req.Account, "to": req.To, "subject": req.Subject,
|
||||
"asked": req.At.Format(time.RFC3339)}
|
||||
if req.Decided != nil {
|
||||
@@ -1342,7 +1353,7 @@ func ReadSendStatus(store SendStore, bus AskBus, publish QueuePublish, id string
|
||||
if now.Sub(req.At) > SendAskLasts {
|
||||
d, _, err := settleSend(store, req, rev, SendDecision{At: now, Outcome: "ended: never heard"})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("the send %q could not be settled as ended (%v); ask again", trimmed, err)
|
||||
return nil, fmt.Errorf("the send %q could not be settled as ended (%v); ask again", req.ID, err)
|
||||
}
|
||||
reportDecision(out, d, now)
|
||||
return out, nil
|
||||
@@ -1448,11 +1459,13 @@ func (b *Bundle) Sweep(now time.Time) {
|
||||
}
|
||||
} else {
|
||||
for _, id := range undecided {
|
||||
req, _, ok, err := getSend(store, id)
|
||||
req, rev, ok, err := getSend(store, id)
|
||||
if err != nil || !ok || req.Decided != nil {
|
||||
continue
|
||||
}
|
||||
if _, err := ReadSendStatus(store, b.askBus(), b.queuePublish(), id, now); err != nil {
|
||||
// 1261/AC6: the sweep settles a send regardless of who asked for it — readSendStatus directly,
|
||||
// never ReadSendStatus's caller check.
|
||||
if _, err := readSendStatus(store, b.askBus(), b.queuePublish(), req, rev, now); err != nil {
|
||||
if b.Logf != nil {
|
||||
b.Logf("[mesh-mail] sweeping the send %s: %v", id, err)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user