Move lesson source into the teaching structure, align the course path with the learner's Go and DevOps experience, and add the interactive lesson guides. Add advanced DevOps lifecycle study as a separate section. Bound MQTT message work and drain accepted jobs during shutdown; align the backend implementation with the revised course through Section 6.
39 lines
1.1 KiB
Go
39 lines
1.1 KiB
Go
package dispatch
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
"example.com/mqtt5-learning/internal/contracts"
|
|
"example.com/mqtt5-learning/internal/mqtt"
|
|
)
|
|
|
|
type Processor func(context.Context, mqtt.Message) error
|
|
|
|
// Receiver validates the route, selects a pool, and copies payload ownership.
|
|
type Receiver struct {
|
|
Telemetry *Pool
|
|
Important *Pool
|
|
Process Processor
|
|
}
|
|
|
|
func (r *Receiver) Submit(ctx context.Context, message mqtt.Message) (Outcome, error) {
|
|
if r.Process == nil {
|
|
return Stopping, fmt.Errorf("message processor is required")
|
|
}
|
|
topic, err := contracts.ParseTopic(message.Topic)
|
|
if err != nil {
|
|
return Stopping, err
|
|
}
|
|
pool := r.Telemetry
|
|
if topic.Kind == contracts.KindCommands || topic.Kind == contracts.KindResponses || topic.Kind == contracts.KindSales {
|
|
pool = r.Important
|
|
}
|
|
if pool == nil {
|
|
return Stopping, fmt.Errorf("no queue configured for topic kind %q", topic.Kind)
|
|
}
|
|
copyOfMessage := message
|
|
copyOfMessage.Payload = append([]byte(nil), message.Payload...)
|
|
return pool.Submit(ctx, func(jobCtx context.Context) error { return r.Process(jobCtx, copyOfMessage) })
|
|
}
|