fix(go): decouple mqtt message publishing from shutdown context
This commit is contained in:
@@ -176,6 +176,9 @@ func (c *MQTTClient) buildTLSConfig() (*tls.Config, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *MQTTClient) handleMessage(ctx context.Context, topic string, payload []byte) {
|
func (c *MQTTClient) handleMessage(ctx context.Context, topic string, payload []byte) {
|
||||||
|
messageCtx, cancelMessage := context.WithTimeout(context.WithoutCancel(ctx), frameOperationTimeout)
|
||||||
|
defer cancelMessage()
|
||||||
|
|
||||||
receivedAtMS := time.Now().UnixMilli()
|
receivedAtMS := time.Now().UnixMilli()
|
||||||
env, err := yutongmqtt.ParseMessage(c.cfg.EndpointName, topic, payload, receivedAtMS)
|
env, err := yutongmqtt.ParseMessage(c.cfg.EndpointName, topic, payload, receivedAtMS)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -193,7 +196,7 @@ func (c *MQTTClient) handleMessage(ctx context.Context, topic string, payload []
|
|||||||
}
|
}
|
||||||
env.EventID = env.StableEventID()
|
env.EventID = env.StableEventID()
|
||||||
} else {
|
} else {
|
||||||
resolved, resolveErr := c.cfg.Resolver.Resolve(ctx, env)
|
resolved, resolveErr := c.cfg.Resolver.Resolve(messageCtx, env)
|
||||||
if resolveErr != nil {
|
if resolveErr != nil {
|
||||||
c.cfg.Logger.Warn("mqtt identity resolve failed", "topic", topic, "event_id", env.StableEventID(), "error", resolveErr)
|
c.cfg.Logger.Warn("mqtt identity resolve failed", "topic", topic, "event_id", env.StableEventID(), "error", resolveErr)
|
||||||
if env.Parsed == nil {
|
if env.Parsed == nil {
|
||||||
@@ -205,14 +208,14 @@ func (c *MQTTClient) handleMessage(ctx context.Context, topic string, payload []
|
|||||||
env = resolved
|
env = resolved
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err := c.cfg.Sink.PublishRaw(ctx, env); err != nil {
|
if err := c.cfg.Sink.PublishRaw(messageCtx, env); err != nil {
|
||||||
c.cfg.Logger.Error("publish mqtt raw failed", "topic", topic, "event_id", env.StableEventID(), "error", err)
|
c.cfg.Logger.Error("publish mqtt raw failed", "topic", topic, "event_id", env.StableEventID(), "error", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if env.ParseStatus == envelope.ParseBadFrame {
|
if env.ParseStatus == envelope.ParseBadFrame {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if err := c.cfg.Sink.PublishUnified(ctx, env); err != nil {
|
if err := c.cfg.Sink.PublishUnified(messageCtx, env); err != nil {
|
||||||
c.cfg.Logger.Error("publish mqtt unified failed", "topic", topic, "event_id", env.StableEventID(), "error", err)
|
c.cfg.Logger.Error("publish mqtt unified failed", "topic", topic, "event_id", env.StableEventID(), "error", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -69,6 +69,45 @@ func TestMQTTClientHandleBadPayloadPublishesOnlyRaw(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestMQTTClientUsesUncancelledMessageContextForReceivedMessage(t *testing.T) {
|
||||||
|
parent, cancel := context.WithCancel(context.Background())
|
||||||
|
cancel()
|
||||||
|
|
||||||
|
resolver := &contextCheckingResolver{}
|
||||||
|
sink := &contextCheckingSink{}
|
||||||
|
client, err := NewMQTTClient(MQTTClientConfig{
|
||||||
|
EndpointName: "endpoint-a",
|
||||||
|
Broker: "tcp://127.0.0.1:1883",
|
||||||
|
ClientID: "test-client",
|
||||||
|
Topics: []string{"/ytforward/shln/+"},
|
||||||
|
Sink: sink,
|
||||||
|
Resolver: resolver,
|
||||||
|
Logger: slog.New(slog.NewTextHandler(testWriter{t: t}, nil)),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("NewMQTTClient() error = %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
client.handleMessage(parent, "/ytforward/shln/dev1", []byte(`{
|
||||||
|
"device":"LTEST000000000001",
|
||||||
|
"time":"20260413100000",
|
||||||
|
"data":{"METER_SPEED":52.3,"TOTAL_MILEAGE":123456.7}
|
||||||
|
}`))
|
||||||
|
|
||||||
|
if resolver.ctxErr != nil {
|
||||||
|
t.Fatalf("resolver saw cancelled context: %v", resolver.ctxErr)
|
||||||
|
}
|
||||||
|
if sink.rawCtxErr != nil {
|
||||||
|
t.Fatalf("raw publish saw cancelled context: %v", sink.rawCtxErr)
|
||||||
|
}
|
||||||
|
if sink.unifiedCtxErr != nil {
|
||||||
|
t.Fatalf("unified publish saw cancelled context: %v", sink.unifiedCtxErr)
|
||||||
|
}
|
||||||
|
if sink.rawCount != 1 || sink.unifiedCount != 1 {
|
||||||
|
t.Fatalf("raw=%d unified=%d", sink.rawCount, sink.unifiedCount)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestMQTTClientBuildOptionsLoadsTLSCertificates(t *testing.T) {
|
func TestMQTTClientBuildOptionsLoadsTLSCertificates(t *testing.T) {
|
||||||
dir := t.TempDir()
|
dir := t.TempDir()
|
||||||
caPath, certPath, keyPath := writeTestTLSMaterial(t, dir)
|
caPath, certPath, keyPath := writeTestTLSMaterial(t, dir)
|
||||||
|
|||||||
Reference in New Issue
Block a user