feat: Integrate factory with SubsystemHandler for idempotency support\n\n- Add commandFactory field to SubsystemHandler\n- Update NewSubsystemHandler to accept factory\n- Modify TriggerSubsystem to use CreateWithIdempotency\n- Update main.go to pass factory to handler\n\nNow all subsystem commands use idempotency keys, preventing duplicates from rapid clicks.
This commit is contained in:
@@ -6,6 +6,7 @@ import (
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/Fimeg/RedFlag/aggregator-server/internal/command"
|
||||
"github.com/Fimeg/RedFlag/aggregator-server/internal/database/queries"
|
||||
"github.com/Fimeg/RedFlag/aggregator-server/internal/models"
|
||||
"github.com/Fimeg/RedFlag/aggregator-server/internal/services"
|
||||
@@ -17,14 +18,16 @@ import (
|
||||
type SubsystemHandler struct {
|
||||
subsystemQueries *queries.SubsystemQueries
|
||||
commandQueries *queries.CommandQueries
|
||||
commandFactory *command.Factory
|
||||
signingService *services.SigningService
|
||||
securityLogger *logging.SecurityLogger
|
||||
}
|
||||
|
||||
func NewSubsystemHandler(sq *queries.SubsystemQueries, cq *queries.CommandQueries, signingService *services.SigningService, securityLogger *logging.SecurityLogger) *SubsystemHandler {
|
||||
func NewSubsystemHandler(sq *queries.SubsystemQueries, cq *queries.CommandQueries, cf *command.Factory, signingService *services.SigningService, securityLogger *logging.SecurityLogger) *SubsystemHandler {
|
||||
return &SubsystemHandler{
|
||||
subsystemQueries: sq,
|
||||
commandQueries: cq,
|
||||
commandFactory: cf,
|
||||
signingService: signingService,
|
||||
securityLogger: securityLogger,
|
||||
}
|
||||
@@ -249,14 +252,9 @@ func (h *SubsystemHandler) TriggerSubsystem(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
// Create command for the subsystem
|
||||
// Create command for the subsystem using factory with idempotency
|
||||
commandType := "scan_" + subsystem
|
||||
command := &models.AgentCommand{
|
||||
AgentID: agentID,
|
||||
CommandType: commandType,
|
||||
Status: "pending",
|
||||
Source: "manual", // Manual trigger from UI (must be 'manual' or 'system' per DB constraint)
|
||||
}
|
||||
idempotencyKey := fmt.Sprintf("%s_%s_%d", agentID.String(), subsystem, time.Now().Unix())
|
||||
|
||||
// Log command creation attempt
|
||||
log.Printf("[INFO] [server] [command] creating_scan_command agent_id=%s subsystem=%s command_type=%s timestamp=%s",
|
||||
@@ -264,6 +262,23 @@ func (h *SubsystemHandler) TriggerSubsystem(c *gin.Context) {
|
||||
log.Printf("[HISTORY] [server] [scan_%s] command_creation_started agent_id=%s timestamp=%s",
|
||||
subsystem, agentID, time.Now().Format(time.RFC3339))
|
||||
|
||||
command, err := h.commandFactory.CreateWithIdempotency(
|
||||
agentID,
|
||||
commandType,
|
||||
map[string]interface{}{"subsystem": subsystem},
|
||||
idempotencyKey,
|
||||
)
|
||||
if err != nil {
|
||||
log.Printf("[ERROR] [server] [scan_%s] command_creation_failed agent_id=%s error=%v", subsystem, agentID, err)
|
||||
log.Printf("[HISTORY] [server] [scan_%s] command_creation_failed error=\"%v\" timestamp=%s",
|
||||
subsystem, err, time.Now().Format(time.RFC3339))
|
||||
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": fmt.Sprintf("Failed to create %s scan command: %v", subsystem, err),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
err = h.signAndCreateCommand(command)
|
||||
if err != nil {
|
||||
log.Printf("[ERROR] [server] [scan_%s] command_creation_failed agent_id=%s error=%v", subsystem, agentID, err)
|
||||
|
||||
Reference in New Issue
Block a user