Refactor MQTT course and bound backend message processing
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.
This commit is contained in:
+24
-23
@@ -8,6 +8,7 @@ import (
|
||||
"time"
|
||||
|
||||
"example.com/mqtt5-learning/internal/config"
|
||||
"example.com/mqtt5-learning/internal/contracts"
|
||||
"github.com/eclipse/paho.golang/autopaho"
|
||||
"github.com/eclipse/paho.golang/paho"
|
||||
)
|
||||
@@ -18,7 +19,7 @@ type Message struct {
|
||||
Retain bool
|
||||
}
|
||||
|
||||
func Start(ctx context.Context, cfg config.Config, topics []string, inbox chan<- Message) (*autopaho.ConnectionManager, error) {
|
||||
func Start(ctx context.Context, cfg config.Config, topics []contracts.TopicFilter, inbox chan<- Message) (*autopaho.ConnectionManager, error) {
|
||||
broker, err := url.Parse(cfg.MQTT.URL)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -38,7 +39,7 @@ func Start(ctx context.Context, cfg config.Config, topics []string, inbox chan<-
|
||||
|
||||
subscriptions := make([]paho.SubscribeOptions, 0, len(topics))
|
||||
for _, topic := range topics {
|
||||
subscriptions = append(subscriptions, paho.SubscribeOptions{Topic: topic, QoS: 1, RetainAsPublished: true})
|
||||
subscriptions = append(subscriptions, paho.SubscribeOptions{Topic: topic.String(), QoS: 1, RetainAsPublished: true})
|
||||
}
|
||||
|
||||
ack, subErr := cm.Subscribe(subCtx, &paho.Subscribe{Subscriptions: subscriptions})
|
||||
@@ -64,24 +65,24 @@ func Start(ctx context.Context, cfg config.Config, topics []string, inbox chan<-
|
||||
default:
|
||||
}
|
||||
},
|
||||
OnConnectionDown: func() bool { log.Print("disconnected; reconnecting"); return true },
|
||||
OnConnectError: func(err error) { log.Printf("connect error: %v", err) },
|
||||
ClientID: cfg.MQTT.ClientID,
|
||||
OnClientError: func(err error) { log.Printf("client error: %v", err) },
|
||||
OnServerDisconnect: func(d *paho.Disconnect) { log.Printf("disconnect reason=0x%02x", d.ReasonCode) },
|
||||
OnPublishReceived: []func(paho.PublishReceived) (bool, error){
|
||||
func(received paho.PublishReceived) (bool, error) {
|
||||
packet := received.Packet
|
||||
message := Message{Topic: packet.Topic, Payload: append([]byte(nil), packet.Payload...), Retain: packet.Retain}
|
||||
select {
|
||||
case inbox <- message:
|
||||
default:
|
||||
// Deliberately lossy early demo: automatic MQTT ACK is still possible.
|
||||
log.Printf("lab inbox full; message dropped topic=%s", packet.Topic)
|
||||
}
|
||||
return true, nil
|
||||
},
|
||||
OnConnectionDown: func() bool { log.Print("disconnected; reconnecting"); return true },
|
||||
OnConnectError: func(err error) { log.Printf("connect error: %v", err) },
|
||||
ClientID: cfg.MQTT.ClientID,
|
||||
OnClientError: func(err error) { log.Printf("client error: %v", err) },
|
||||
OnServerDisconnect: func(d *paho.Disconnect) { log.Printf("disconnect reason=0x%02x", d.ReasonCode) },
|
||||
OnPublishReceived: []func(paho.PublishReceived) (bool, error){
|
||||
func(received paho.PublishReceived) (bool, error) {
|
||||
packet := received.Packet
|
||||
message := Message{Topic: packet.Topic, Payload: append([]byte(nil), packet.Payload...), Retain: packet.Retain}
|
||||
select {
|
||||
case inbox <- message:
|
||||
default:
|
||||
// Deliberately lossy early demo: automatic MQTT ACK is still possible.
|
||||
log.Printf("lab inbox full; message dropped topic=%s", packet.Topic)
|
||||
}
|
||||
return true, nil
|
||||
},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("start AutoPaho: %w", err)
|
||||
@@ -105,12 +106,12 @@ func Start(ctx context.Context, cfg config.Config, topics []string, inbox chan<-
|
||||
return manager, nil
|
||||
}
|
||||
|
||||
func Publish(ctx context.Context, manager *autopaho.ConnectionManager, topic string, payload []byte) error {
|
||||
func Publish(ctx context.Context, manager *autopaho.ConnectionManager, topic contracts.TopicName, payload []byte) error {
|
||||
operation, cancel := context.WithTimeout(ctx, 3*time.Second)
|
||||
defer cancel()
|
||||
|
||||
ack, err := manager.Publish(operation, &paho.Publish{
|
||||
Topic: topic,
|
||||
Topic: topic.String(),
|
||||
Payload: payload,
|
||||
QoS: 1,
|
||||
Retain: false,
|
||||
@@ -137,7 +138,7 @@ func Stop(manager *autopaho.ConnectionManager) {
|
||||
shutdown, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
|
||||
if err:=manager.Disconnect(shutdown); err != nil {
|
||||
if err := manager.Disconnect(shutdown); err != nil {
|
||||
log.Printf("shutdown did not finish within deadline: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user