Files
core/internal/history/failure_projection.go

68 lines
1.5 KiB
Go

package history
import (
"context"
"database/sql"
"time"
"reanimator/internal/idgen"
)
type FailureProjectionInput struct {
Source string
ExternalID string
PartID string
MachineID *string
FailureType string
FailureTime time.Time
Details *string
}
func (s *Service) UpsertFailureProjectionWithTx(ctx context.Context, tx *sql.Tx, in FailureProjectionInput) error {
if tx == nil {
return ErrConflict
}
var existingID string
err := tx.QueryRowContext(ctx, `
SELECT id
FROM failure_events
WHERE source = ?
AND part_id = ?
AND ((machine_id IS NULL AND ? IS NULL) OR machine_id = ?)
AND failure_type = ?
AND failure_time = ?
AND COALESCE(details, '') = COALESCE(?, '')
LIMIT 1`,
in.Source,
in.PartID,
in.MachineID,
in.MachineID,
in.FailureType,
in.FailureTime.UTC(),
in.Details,
).Scan(&existingID)
if err == nil {
return nil
}
if err != sql.ErrNoRows {
return err
}
id, err := s.generateID(ctx, tx, idgen.FailureEvent)
if err != nil {
return err
}
_, err = tx.ExecContext(ctx, `
INSERT INTO failure_events (id, source, external_id, part_id, machine_id, failure_type, failure_time, details)
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
ON DUPLICATE KEY UPDATE
part_id = VALUES(part_id),
machine_id = VALUES(machine_id),
failure_type = VALUES(failure_type),
failure_time = VALUES(failure_time),
details = VALUES(details)`,
id, in.Source, in.ExternalID, in.PartID, in.MachineID, in.FailureType, in.FailureTime.UTC(), in.Details,
)
return err
}