package agent import ( "context" "encoding/json" "time" "git.5iot.com/iotlcm-public/iotlcm-admin-svr/internal/cmd/inithttp" "git.5iot.com/iotlcm-public/iotlcm-admin-svr/internal/consts" "git.5iot.com/iotlcm-public/iotlcm-admin-svr/internal/library/rabbitmq" "git.5iot.com/iotlcm-public/iotlcm-admin-svr/internal/model" "git.5iot.com/iotlcm-public/iotlcm-admin-svr/internal/service" localqueue "git.5iot.com/iotlcm-public/iotlcm-admin-svr/utility/queue" "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/os/gctx" ) type agentRoleSyncQueue struct{} func init() { inithttp.RegisterHttpInitFunc("agentRoleSyncQueue", func(ctx context.Context) error { if rabbitmq.Enabled(ctx) { if err := rabbitmq.DeclareQueue(ctx, consts.QueueAgentRoleSyncDeadLetter); err != nil { return err } return rabbitmq.ConsumeJSON[model.AgentRoleSyncMessage](ctx, consts.QueueAgentRoleSync, "iotlcm-agent-role-sync", handleAgentRoleSyncMessage) } if err := localqueue.NewConsumer(gctx.New(), &agentRoleSyncQueue{}, &localqueue.Config{Workers: 2}); err != nil { return err } return localqueue.NewProducer(gctx.New(), localqueue.QueueTypeMemory, consts.QueueAgentRoleSync, &localqueue.Config{}) }) } func publishAgentRoleSync(ctx context.Context, message *model.AgentRoleSyncMessage) error { if rabbitmq.Enabled(ctx) { return rabbitmq.Publish(ctx, consts.QueueAgentRoleSync, message) } return localqueue.Push(ctx, consts.QueueAgentRoleSync, message) } func handleAgentRoleSyncMessage(ctx context.Context, message model.AgentRoleSyncMessage) error { if err := service.AgentRole().SyncInheritedRole(ctx, &message); err != nil { g.Log().Errorf(ctx, "agent role sync failed, sourceRoleId:%d, retry:%d, err:%v", message.SourceRoleId, message.RetryCount, err) if message.RetryCount < 3 { message.RetryCount++ return rabbitmq.PublishDelayed(ctx, consts.QueueAgentRoleSyncRetry, consts.QueueAgentRoleSync, time.Duration(message.RetryCount)*time.Second, message) } deadLetter := model.AgentRoleSyncDeadLetterMessage{Message: message, Error: err.Error(), FailedAt: time.Now().Format(time.RFC3339)} if publishErr := rabbitmq.Publish(ctx, consts.QueueAgentRoleSyncDeadLetter, deadLetter); publishErr != nil { return publishErr } g.Log().Errorf(ctx, "agent role sync moved to dead-letter queue, sourceRoleId:%d, err:%v", message.SourceRoleId, err) return nil } g.Log().Infof(ctx, "agent role sync completed, sourceRoleId:%d", message.SourceRoleId) return nil } func (*agentRoleSyncQueue) GetTopic() string { return consts.QueueAgentRoleSync } func (*agentRoleSyncQueue) GetType() localqueue.QueueType { return localqueue.QueueTypeMemory } func (*agentRoleSyncQueue) Handle(ctx context.Context, payload localqueue.Payload) error { var message model.AgentRoleSyncMessage if err := json.Unmarshal(payload.Data, &message); err != nil { return err } var err error for attempt := 0; attempt <= 3; attempt++ { err = service.AgentRole().SyncInheritedRole(ctx, &message) if err == nil { g.Log().Infof(ctx, "agent role sync completed, sourceRoleId:%d", message.SourceRoleId) return nil } if attempt < 3 { time.Sleep(time.Duration(attempt+1) * time.Second) } } g.Log().Errorf(ctx, "agent role sync failed after retries, sourceRoleId:%d, err:%v", message.SourceRoleId, err) return err }