Tell a refusal as one and an unanswered call as not known; ask a plan that fails again within the hour (issues 1316, 1314, review round 1)
This commit is contained in:
@@ -409,7 +409,9 @@ func (a *asker) reconcile(ctx context.Context) error {
|
||||
for _, r := range all {
|
||||
k := partKey(r.Condition, r.Part)
|
||||
if r.State == string(asks.OutcomeChosen) && now.Sub(r.Ended) < askAgainAfterAnswer {
|
||||
answered[k] = r
|
||||
if prior, has := answered[k]; !has || r.Ended.After(prior.Ended) {
|
||||
answered[k] = r
|
||||
}
|
||||
}
|
||||
if r.State == string(asks.OutcomeRefused) {
|
||||
if prior, has := refused[k]; !has || r.Opened.After(prior.Opened) {
|
||||
@@ -500,7 +502,9 @@ func (a *asker) reconcile(ctx context.Context) error {
|
||||
continue // refused lately, and nothing it was refused for has changed: asked again after the wait
|
||||
}
|
||||
}
|
||||
if r, done := answered[key]; done && sameAsked(r.Actions, p.actions) {
|
||||
// **A condition raised after the answered ask ended is a new one** (novox/hq ADR 0449 §2): a retried
|
||||
// plan that fails again is asked again, not held back for the hour its earlier answer holds.
|
||||
if r, done := answered[key]; done && sameAsked(r.Actions, p.actions) && !c.Raised.After(r.Ended) {
|
||||
if _, held := byCondition[key]; !held {
|
||||
continue
|
||||
}
|
||||
@@ -924,33 +928,53 @@ func (a *asker) Decided(ctx context.Context, body []byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// tellRefused tells the operator that the answer they gave to a plan's ask was refused (novox/hq ADR 0449 §3): the
|
||||
// controller's `plans` verb refuses a Retry, Start or Stop when the plan moved on between the ask and the answer,
|
||||
// and the refusal was only recorded, so the operator who pressed the answer heard nothing. One plain notice with the
|
||||
// ask's headline and the refusal's words, beside the hand act the caller still records. An answer to any other ask
|
||||
// is not told here. A notice that cannot be told is said in the log and changes nothing.
|
||||
func (a *asker) tellRefused(ctx context.Context, r asked, act conditions.Action, refusal error) {
|
||||
// tellRefused tells the operator what became of the answer they gave to a plan's ask, when it was not done (novox/hq
|
||||
// ADR 0449 §3): the controller's `plans` verb refuses a Retry, Start or Stop when the plan moved on between the ask and
|
||||
// the answer, and the refusal was only recorded, so the operator who pressed the answer heard nothing. **A refusal is
|
||||
// told as one, and nothing else is**: a verb that said no changed nothing, but a call that got no answer (a timeout, a
|
||||
// refused grant) may have run, and is told as not known. One plain notice with the ask's headline, beside the hand act
|
||||
// the caller still records. An answer to any other ask is not told here. A notice that cannot be told is said in the
|
||||
// log and changes nothing.
|
||||
func (a *asker) tellRefused(ctx context.Context, r asked, act conditions.Action, failure error) {
|
||||
if a.tell == nil || act.Verb != broker.ControllerSeat+".plans" {
|
||||
return
|
||||
}
|
||||
lines := []string{
|
||||
fmt.Sprintf("Your answer, %s, could not be done: %s.", act.Label, strings.TrimRight(refusalWords(refusal), ".")),
|
||||
"Nothing was changed.",
|
||||
var lines []string
|
||||
var refused verbRefused
|
||||
if errors.As(failure, &refused) {
|
||||
lines = []string{
|
||||
fmt.Sprintf("Your answer, %s, could not be done: %s.", act.Label, strings.TrimRight(refusalWords(refused.words, act), ".")),
|
||||
"Nothing was changed.",
|
||||
}
|
||||
} else {
|
||||
lines = []string{
|
||||
fmt.Sprintf("Your answer, %s, was given, and it is not known whether it was done.", act.Label),
|
||||
"Look at the delivery before you answer again.",
|
||||
}
|
||||
}
|
||||
if err := a.tell(ctx, r.Ask.Headline, lines); err != nil {
|
||||
a.logf("the operator could NOT be told that %s was refused (ask %s): %v", act.Label, r.ID, err)
|
||||
}
|
||||
}
|
||||
|
||||
// refusalWords is a refused verb's words as the operator reads them: without the verb's address in front, with the
|
||||
// plans named as "the plan" (plainRefusal), and, where they still carry an identifier the operator's channel
|
||||
// withholds, only that the controller refused it.
|
||||
func refusalWords(err error) string {
|
||||
text := err.Error()
|
||||
if i := strings.Index(text, " refused: "); i >= 0 {
|
||||
text = text[i+len(" refused: "):]
|
||||
// refusalWords is a verb's refusal as the operator reads it: the plans named as "the plan" (plainRefusal), and, where
|
||||
// the words still carry an identifier the operator's channel withholds, one sentence of the answer's own.
|
||||
func refusalWords(words string, act conditions.Action) string {
|
||||
return plainRefusalOr(words, refusalFallback(act))
|
||||
}
|
||||
|
||||
// refusalFallback is what an answer's refusal says when its own words cannot be said: one sentence for each answer
|
||||
// to a plan's ask, never another answer's.
|
||||
func refusalFallback(act conditions.Action) string {
|
||||
switch {
|
||||
case act.Arguments["retry"] != "":
|
||||
return "a retry would not run now; the details say why"
|
||||
case act.Arguments["go"] != "":
|
||||
return "the delivery could not be started now; the details say why"
|
||||
case act.Arguments["stop"] != "":
|
||||
return "the delivery could not be stopped now; the details say why"
|
||||
}
|
||||
return plainRefusal(text)
|
||||
return "the controller refused it; the details say why"
|
||||
}
|
||||
|
||||
// handActWarrant is the verb an act the operator chose on a warrant is recorded under: a person's decision,
|
||||
|
||||
Reference in New Issue
Block a user