50 lines
1.6 KiB
Go
50 lines
1.6 KiB
Go
package tenant
|
|
|
|
import (
|
|
"fmt"
|
|
"regexp"
|
|
)
|
|
|
|
// Route describes a SaaS-owned exact Topic binding. Dispatcher only
|
|
// consumes/publishes; it never declares, binds, or deletes these resources.
|
|
type Route struct {
|
|
Exchange string
|
|
BindingKey string
|
|
Queue string
|
|
}
|
|
|
|
var taskIDPattern = regexp.MustCompile(`^[A-Za-z0-9_-]{1,128}$`)
|
|
|
|
func ControlRoute(dispatcherID string) (Route, error) {
|
|
if err := ValidateDispatcherID(dispatcherID); err != nil {
|
|
return Route{}, err
|
|
}
|
|
return exactRoute("agent-call.dispatchers.v1", "d."+dispatcherID+".control.in", "agent-call.d."+dispatcherID+".control.v1")
|
|
}
|
|
|
|
func TaskRoute(dispatcherID, taskID string) (Route, error) {
|
|
if err := ValidateDispatcherID(dispatcherID); err != nil {
|
|
return Route{}, err
|
|
}
|
|
if !taskIDPattern.MatchString(taskID) {
|
|
return Route{}, fmt.Errorf("invalid task ID for exact MQ route")
|
|
}
|
|
return exactRoute("agent-call.dispatchers.v1", "d."+dispatcherID+".task."+taskID+".in", "agent-call.d."+dispatcherID+".task."+taskID+".v1")
|
|
}
|
|
|
|
func ResultRoute(dispatcherID string) (Route, error) {
|
|
if err := ValidateDispatcherID(dispatcherID); err != nil {
|
|
return Route{}, err
|
|
}
|
|
// The shared queue name is only a project-local Mock fixture. SaaS owns
|
|
// the actual receiving queue and exact bindings for each Dispatcher.
|
|
return exactRoute("agent-call.saas.v1", "d."+dispatcherID+".out", "agent-call.saas.events.v1")
|
|
}
|
|
|
|
func exactRoute(exchange, key, queue string) (Route, error) {
|
|
if len(key) > 255 || len(queue) > 255 {
|
|
return Route{}, fmt.Errorf("AMQP route exceeds 255 bytes")
|
|
}
|
|
return Route{Exchange: exchange, BindingKey: key, Queue: queue}, nil
|
|
}
|