The assigner's two consumers of its durable on the shared stream still compete; they join the module's one hub. Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
69 lines
2.2 KiB
Go
69 lines
2.2 KiB
Go
package assign
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"time"
|
|
|
|
occ "git.novox.be/novox/mesh-contracts/operator-and-conversation/go/clients/operatorchannelclient"
|
|
oc "git.novox.be/novox/mesh-contracts/operator-and-conversation/go/seats/operatorchannel"
|
|
"git.novox.be/novox/mesh-sdk/go/delivery"
|
|
)
|
|
|
|
// assignerAsk is the asking-th ask a, as the asks state holds it: the router's ask as JSON (delivery.AssignerAsk.Ask).
|
|
func assignerAsk(asking int, a oc.Ask) delivery.AssignerAsk {
|
|
raw, err := json.Marshal(a)
|
|
if err != nil { // an oc.Ask holds only strings, bools and a slice of them: it cannot fail
|
|
panic(fmt.Sprintf("assign: the ask %q does not marshal: %v", a.ID, err))
|
|
}
|
|
return delivery.AssignerAsk{Asking: asking, Ask: raw}
|
|
}
|
|
|
|
// AskOf is the router's ask an asks-state value carries.
|
|
func AskOf(a delivery.AssignerAsk) (oc.Ask, error) {
|
|
var ask oc.Ask
|
|
if err := json.Unmarshal(a.Ask, &ask); err != nil {
|
|
return oc.Ask{}, fmt.Errorf("assign: the value carries no router's ask: %w", err)
|
|
}
|
|
return ask, nil
|
|
}
|
|
|
|
// EncodeAsk is delivery.EncodeAssignerAsk at key, after the checks every keeper of an ask owes (occ.Carried, ADR 0627 §4):
|
|
// the ask's id is delivery.AskingID(key, asking), and it offers at least one option.
|
|
func EncodeAsk(key string, a delivery.AssignerAsk) ([]byte, error) {
|
|
if _, err := checkedAsk(key, a); err != nil {
|
|
return nil, err
|
|
}
|
|
return delivery.EncodeAssignerAsk(key, a)
|
|
}
|
|
|
|
func checkedAsk(key string, a delivery.AssignerAsk) (oc.Ask, error) {
|
|
ask, err := occ.Carried(a.Ask, delivery.AskingID(key, a.Asking))
|
|
if err != nil {
|
|
return oc.Ask{}, fmt.Errorf("assign: %w", err)
|
|
}
|
|
return ask, nil
|
|
}
|
|
|
|
// DecodeAsk reads the ask at key (delivery.DecodeAssignerAsk) with the router's ask it carries.
|
|
func DecodeAsk(key string, data []byte) (delivery.AssignerAsk, oc.Ask, error) {
|
|
a, err := delivery.DecodeAssignerAsk(key, data)
|
|
if err != nil {
|
|
return delivery.AssignerAsk{}, oc.Ask{}, err
|
|
}
|
|
ask, err := checkedAsk(key, a)
|
|
if err != nil {
|
|
return delivery.AssignerAsk{}, oc.Ask{}, err
|
|
}
|
|
return a, ask, nil
|
|
}
|
|
|
|
// ExpiresAt is when the ask ends unanswered; the zero time for an ask that names none.
|
|
func ExpiresAt(a oc.Ask) time.Time {
|
|
t, err := occ.Time(a.Expires)
|
|
if err != nil {
|
|
return time.Time{}
|
|
}
|
|
return t
|
|
}
|