* INFRA-2829 | Implemented transaction in create incident flow * INFRA-2829 | created util func for rollback * INFRA-2829 | removed redundant cod to create slack channel
771 lines
23 KiB
Go
771 lines
23 KiB
Go
package incident
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"github.com/slack-go/slack/socketmode"
|
|
"github.com/spf13/viper"
|
|
"houston/logger"
|
|
"houston/model/log"
|
|
"houston/model/severity"
|
|
"houston/model/team"
|
|
utils "houston/service/utils"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
"go.uber.org/zap"
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
type Repository struct {
|
|
gormClient *gorm.DB
|
|
severityRepository *severity.Repository
|
|
logRepository *log.Repository
|
|
teamRepository *team.Repository
|
|
socketModeClient *socketmode.Client
|
|
}
|
|
|
|
var valueBeforeUpdate IncidentEntity
|
|
var valueAfterUpdate IncidentEntity
|
|
var valueBeforeCreate IncidentEntity
|
|
var valueAfterCreate IncidentEntity
|
|
var differences []utils.Difference
|
|
|
|
func NewIncidentRepository(
|
|
gormClient *gorm.DB,
|
|
severityService *severity.Repository,
|
|
logRepository *log.Repository,
|
|
teamRepository *team.Repository,
|
|
socketModeClient *socketmode.Client,
|
|
) *Repository {
|
|
return &Repository{
|
|
gormClient: gormClient,
|
|
severityRepository: severityService,
|
|
logRepository: logRepository,
|
|
teamRepository: teamRepository,
|
|
socketModeClient: socketModeClient,
|
|
}
|
|
}
|
|
|
|
func (r *Repository) CreateIncidentEntity(request *CreateIncidentDTO, tx *gorm.DB) (*IncidentEntity, error) {
|
|
severityId, err := strconv.Atoi(request.Severity)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("fetch channel conversationInfo failed. err: %v", err)
|
|
}
|
|
severity, err := r.severityRepository.FindSeverityById(uint(severityId))
|
|
if err != nil {
|
|
return nil, fmt.Errorf("fetch FindSeverityById failed. err: %v", err)
|
|
}
|
|
|
|
teamId, _ := strconv.Atoi(request.TeamId)
|
|
incidentStatusEntity, _ := r.GetIncidentStatusByStatusName(string(request.Status))
|
|
|
|
incidentEntity := &IncidentEntity{
|
|
Title: request.Title,
|
|
Description: request.Description,
|
|
Status: incidentStatusEntity.ID,
|
|
SeverityId: uint(severityId),
|
|
DetectionTime: request.DetectionTime,
|
|
StartTime: request.StartTime,
|
|
TeamId: uint(teamId),
|
|
EnableReminder: request.EnableReminder,
|
|
SeverityTat: time.Now().AddDate(0, 0, severity.Sla),
|
|
CreatedBy: request.CreatedBy,
|
|
UpdatedBy: request.UpdatedBy,
|
|
MetaData: request.MetaData,
|
|
}
|
|
|
|
tx.Create(incidentEntity)
|
|
|
|
return incidentEntity, nil
|
|
}
|
|
|
|
func (i *IncidentEntity) AfterCreate(tx *gorm.DB) (err error) {
|
|
println(fmt.Sprintf("AfterUpdate executed at: %v", time.Now()))
|
|
valueBeforeCreate = IncidentEntity{}
|
|
valueAfterCreate = IncidentEntity{}
|
|
if err := tx.First(&valueAfterCreate, i.ID).Error; err != nil {
|
|
return err
|
|
}
|
|
println(fmt.Sprintf("incident entity after created is: %s", valueAfterCreate))
|
|
differences = utils.DeepCompare(valueBeforeCreate, valueAfterCreate)
|
|
return nil
|
|
}
|
|
|
|
func (i *IncidentEntity) BeforeUpdate(tx *gorm.DB) (err error) {
|
|
println(fmt.Sprintf("BeforeUpdate executed at: %v", time.Now()))
|
|
valueBeforeUpdate = IncidentEntity{}
|
|
if err := tx.First(&valueBeforeUpdate, i.ID).Error; err != nil {
|
|
return err
|
|
}
|
|
println(fmt.Sprintf("incident entity before update is: %s", valueBeforeUpdate))
|
|
return nil
|
|
}
|
|
|
|
func (i *IncidentEntity) AfterUpdate(tx *gorm.DB) (err error) {
|
|
println(fmt.Sprintf("AfterUpdate executed at: %v", time.Now()))
|
|
valueAfterUpdate = IncidentEntity{}
|
|
if err := tx.First(&valueAfterUpdate, i.ID).Error; err != nil {
|
|
return err
|
|
}
|
|
println(fmt.Sprintf("incident entity after updated is: %s", valueAfterUpdate))
|
|
differences = append(differences, utils.DeepCompare(valueBeforeUpdate, valueAfterUpdate)...)
|
|
return nil
|
|
}
|
|
|
|
func (r *Repository) processDiffIds() []byte {
|
|
var jsonDiff []byte
|
|
|
|
for index := range differences {
|
|
switch differences[index].Attribute {
|
|
case "Status":
|
|
if differences[index].From != "" {
|
|
statusIdString, _ := strconv.Atoi(differences[index].From)
|
|
statusEntity, _ := r.GetIncidentStatusNameByStatus(uint(statusIdString))
|
|
if statusEntity != nil {
|
|
differences[index].From = statusEntity.Name
|
|
}
|
|
}
|
|
|
|
statusIdString, _ := strconv.Atoi(differences[index].To)
|
|
statusEntity, _ := r.GetIncidentStatusNameByStatus(uint(statusIdString))
|
|
differences[index].To = statusEntity.Name
|
|
|
|
case "SeverityId":
|
|
if differences[index].From != "" {
|
|
severityIdString, _ := strconv.Atoi(differences[index].From)
|
|
severityEntity, _ := r.severityRepository.FindSeverityById(uint(severityIdString))
|
|
if severityEntity != nil {
|
|
differences[index].From = severityEntity.Name
|
|
}
|
|
}
|
|
|
|
severityIdString, _ := strconv.Atoi(differences[index].To)
|
|
severityEntity, _ := r.severityRepository.FindSeverityById(uint(severityIdString))
|
|
differences[index].To = severityEntity.Name
|
|
|
|
case "TeamId":
|
|
if differences[index].From != "" {
|
|
teamIdString, _ := strconv.Atoi(differences[index].From)
|
|
teamEntity, _ := r.teamRepository.FindTeamById(uint(teamIdString))
|
|
if teamEntity != nil {
|
|
differences[index].From = teamEntity.Name
|
|
}
|
|
}
|
|
teamIdString, _ := strconv.Atoi(differences[index].To)
|
|
teamEntity, _ := r.teamRepository.FindTeamById(uint(teamIdString))
|
|
if teamEntity != nil {
|
|
differences[index].To = teamEntity.Name
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
jsonDiff, _ = json.Marshal(differences)
|
|
|
|
return jsonDiff
|
|
}
|
|
|
|
func (r *Repository) processUserInfo() ([]byte, error) {
|
|
user, err := r.socketModeClient.GetUsersInfo(valueAfterUpdate.UpdatedBy)
|
|
|
|
if err != nil {
|
|
errorMessage := fmt.Sprintf("failed to get user info from slack for userID: %s", valueAfterUpdate.UpdatedBy)
|
|
logger.Error(errorMessage)
|
|
return nil, fmt.Errorf("%s. Error: %v", errorMessage, err)
|
|
}
|
|
|
|
if len(*user) != 0 {
|
|
userData := (*user)[0]
|
|
userInfo := log.UserInfo{
|
|
Id: userData.ID,
|
|
Email: userData.Profile.Email,
|
|
Name: userData.Profile.RealName,
|
|
}
|
|
return json.Marshal(userInfo)
|
|
}
|
|
|
|
return nil, fmt.Errorf("%s is not a valid user", valueAfterUpdate.UpdatedBy)
|
|
}
|
|
|
|
func (r *Repository) captureLogs(justification string) {
|
|
if differences != nil && len(differences) > 0 {
|
|
jsonUser, _ := r.processUserInfo()
|
|
|
|
jsonDiff := r.processDiffIds()
|
|
|
|
logEntity := log.LogEntity{
|
|
CreatedAt: time.Now(),
|
|
RelationName: "incident",
|
|
RecordId: valueAfterUpdate.ID,
|
|
UserInfo: jsonUser,
|
|
Changes: jsonDiff,
|
|
}
|
|
if justification != "" {
|
|
logEntity.Justification = justification
|
|
}
|
|
_, err := r.logRepository.CreateLog(&logEntity)
|
|
if err != nil {
|
|
logger.Error(fmt.Sprintf("%d failed to create log. Error: %v", logEntity.RecordId, err))
|
|
}
|
|
|
|
differences = []utils.Difference{}
|
|
}
|
|
}
|
|
|
|
func (r *Repository) UpdateIncident(incidentEntity *IncidentEntity) error {
|
|
result := r.gormClient.Updates(incidentEntity)
|
|
if result.Error != nil {
|
|
return result.Error
|
|
}
|
|
|
|
r.captureLogs("")
|
|
|
|
return nil
|
|
}
|
|
|
|
func (r *Repository) UpdateIncidentWithJustification(incidentEntity *IncidentEntity, justification string) error {
|
|
result := r.gormClient.Updates(incidentEntity)
|
|
if result.Error != nil {
|
|
return result.Error
|
|
}
|
|
r.captureLogs(justification)
|
|
return nil
|
|
}
|
|
|
|
func (r *Repository) GetIncidentStatusByStatusName(status string) (*IncidentStatusEntity, error) {
|
|
var incidentStatus IncidentStatusEntity
|
|
|
|
result := r.gormClient.Find(&incidentStatus, "LOWER(name) = LOWER(?)", status)
|
|
if result.Error != nil {
|
|
return nil, result.Error
|
|
}
|
|
if result.RowsAffected == 0 {
|
|
return nil, nil
|
|
}
|
|
|
|
return &incidentStatus, nil
|
|
}
|
|
|
|
func (r *Repository) GetIncidentStatusNameByStatus(status uint) (*IncidentStatusEntity, error) {
|
|
var incidentStatus IncidentStatusEntity
|
|
|
|
result := r.gormClient.Find(&incidentStatus, "id = ?", status)
|
|
if result.Error != nil {
|
|
return nil, result.Error
|
|
}
|
|
if result.RowsAffected == 0 {
|
|
return nil, nil
|
|
}
|
|
|
|
return &incidentStatus, nil
|
|
}
|
|
|
|
func (r *Repository) GetOpenIncidents(limit int) (*[]IncidentSeverityTeamDTO, error) {
|
|
var incidentSeverityTeamDTO []IncidentSeverityTeamDTO
|
|
|
|
result := r.gormClient.Raw(`
|
|
select i.title, ins.name as status, i.slack_channel, s.name as severity_name, t.name as team_name
|
|
from incident i
|
|
inner join severity s on s.id = i.severity_id
|
|
inner join team t on t.id = i.team_id
|
|
inner join incident_status ins on ins.id = i.status
|
|
where ins.name <> ? and i.deleted_at is null
|
|
limit ?
|
|
`, Resolved, limit).Scan(&incidentSeverityTeamDTO)
|
|
|
|
if result.Error != nil {
|
|
return nil, result.Error
|
|
}
|
|
if result.RowsAffected == 0 {
|
|
return nil, nil
|
|
}
|
|
|
|
return &incidentSeverityTeamDTO, nil
|
|
}
|
|
|
|
func (r *Repository) FindIncidentByChannelId(channelId string) (*IncidentEntity, error) {
|
|
var incidentEntity IncidentEntity
|
|
|
|
result := r.gormClient.Find(&incidentEntity, "slack_channel = ?", channelId)
|
|
if result.Error != nil {
|
|
return nil, result.Error
|
|
}
|
|
|
|
if result.RowsAffected == 0 {
|
|
return nil, nil
|
|
}
|
|
|
|
return &incidentEntity, nil
|
|
}
|
|
|
|
func (r *Repository) FindIncidentById(Id uint) (*IncidentEntity, error) {
|
|
var incidentEntity IncidentEntity
|
|
|
|
result := r.gormClient.Find(&incidentEntity, "id = ?", Id)
|
|
if result.Error != nil {
|
|
return nil, result.Error
|
|
}
|
|
|
|
if result.RowsAffected == 0 {
|
|
return nil, fmt.Errorf("could not find incident with ID: %d", Id)
|
|
}
|
|
|
|
return &incidentEntity, nil
|
|
}
|
|
|
|
func (r *Repository) GetAllOpenIncidents() (*[]IncidentEntity, int, error) {
|
|
statusEntities, err := r.FetchAllNonTerminalIncidentStatuses()
|
|
if err != nil {
|
|
logger.Error(fmt.Sprintf("%s failed to fetch all non terminal incident statuses. Error: %+v", "[incident_repository]", err))
|
|
}
|
|
var nonTerminalStatuses []uint
|
|
for _, status := range *statusEntities {
|
|
nonTerminalStatuses = append(nonTerminalStatuses, status.ID)
|
|
}
|
|
|
|
return r.GetAllIncidents(nil, nil, nonTerminalStatuses)
|
|
}
|
|
|
|
func (r *Repository) GetAllIncidents(teamsIds, severityIds, statusIds []uint) (*[]IncidentEntity, int, error) {
|
|
var query = r.gormClient.Model([]IncidentEntity{})
|
|
var incidentEntity []IncidentEntity
|
|
if len(teamsIds) != 0 {
|
|
query = query.Where("team_id IN ?", teamsIds)
|
|
}
|
|
if len(severityIds) != 0 {
|
|
query = query.Where("severity_id IN ?", severityIds)
|
|
}
|
|
if len(statusIds) != 0 {
|
|
query = query.Where("status IN ?", statusIds)
|
|
}
|
|
|
|
var totalElements int64
|
|
result := query.Count(&totalElements)
|
|
if result.Error != nil {
|
|
return nil, 0, result.Error
|
|
}
|
|
|
|
if result.RowsAffected == 0 {
|
|
return nil, int(totalElements), nil
|
|
}
|
|
|
|
result = query.Order("created_at desc").Find(&incidentEntity)
|
|
|
|
if result.Error != nil {
|
|
return nil, 0, result.Error
|
|
}
|
|
if result.RowsAffected == 0 {
|
|
return nil, int(totalElements), nil
|
|
}
|
|
|
|
return &incidentEntity, int(totalElements), nil
|
|
}
|
|
|
|
func (r *Repository) FetchAllIncidentsPaginated(
|
|
TeamsId []uint,
|
|
SeverityIds []uint,
|
|
StatusIds []uint,
|
|
pageNumber int64,
|
|
pageSize int64,
|
|
incidentName string,
|
|
from string,
|
|
to string,
|
|
) ([]IncidentEntity, int, error) {
|
|
var query = r.gormClient.Model([]IncidentEntity{})
|
|
var incidentEntity []IncidentEntity
|
|
if len(TeamsId) != 0 {
|
|
query = query.Where("team_id IN ?", TeamsId)
|
|
}
|
|
if len(SeverityIds) != 0 {
|
|
query = query.Where("severity_id IN ?", SeverityIds)
|
|
}
|
|
if len(StatusIds) != 0 {
|
|
query = query.Where("status IN ?", StatusIds)
|
|
}
|
|
if len(strings.TrimSpace(incidentName)) != 0 {
|
|
query = query.Where("incident_name LIKE ?", "%"+incidentName+"%")
|
|
}
|
|
if len(from) != 0 {
|
|
query = query.Where("created_at >= ?", from)
|
|
}
|
|
if len(to) != 0 {
|
|
query = query.Where("created_at <= ?", to)
|
|
}
|
|
|
|
var totalElements int64
|
|
result := query.Count(&totalElements)
|
|
if result.Error != nil {
|
|
return nil, 0, result.Error
|
|
}
|
|
|
|
result = query.Order("created_at desc").Offset(int(pageNumber * pageSize)).Limit(int(pageSize)).Find(&incidentEntity)
|
|
|
|
if result.Error != nil {
|
|
return nil, 0, result.Error
|
|
}
|
|
if result.RowsAffected == 0 {
|
|
return nil, int(totalElements), nil
|
|
}
|
|
|
|
return incidentEntity, int(totalElements), nil
|
|
}
|
|
|
|
func (r *Repository) FindIncidentSeverityTeamJoin(slackChannelId string) (*IncidentSeverityTeamDTO, error) {
|
|
var incidentSeverityTeamJoinEntity IncidentSeverityTeamDTO
|
|
|
|
result := r.gormClient.Table("incident").
|
|
Where("incident.slack_channel = ? and incident.deleted_at IS NULL", slackChannelId).
|
|
Joins("JOIN severity ON severity.id = incident.severity_id").
|
|
Joins("JOIN team ON team.id = incident.team_id").
|
|
Joins("JOIN incident_status on incident.status = incident_status.id").
|
|
Select("incident.title, incident_status.name as status, incident.slack_channel, severity.name as severity_name ,team.name as team_name").
|
|
Scan(&incidentSeverityTeamJoinEntity)
|
|
|
|
if result.Error != nil {
|
|
return nil, result.Error
|
|
}
|
|
if result.RowsAffected == 0 {
|
|
return nil, nil
|
|
}
|
|
|
|
return &incidentSeverityTeamJoinEntity, nil
|
|
}
|
|
|
|
func (r *Repository) UpsertIncidentRole(addIncidentRoleRequest *AddIncidentRoleRequest) error {
|
|
incidentRolesEntity := &IncidentRoleEntity{
|
|
IncidentId: addIncidentRoleRequest.IncidentId,
|
|
Role: addIncidentRoleRequest.Role,
|
|
AssignedTo: addIncidentRoleRequest.UserId,
|
|
AssignedBy: addIncidentRoleRequest.CreatedById,
|
|
}
|
|
var incidentRole IncidentRoleEntity
|
|
|
|
result := r.gormClient.Find(&incidentRole, "incident_id = ? AND role = ?", addIncidentRoleRequest.IncidentId, addIncidentRoleRequest.Role)
|
|
if result.Error != nil {
|
|
return result.Error
|
|
}
|
|
if result.RowsAffected == 1 {
|
|
incidentRolesEntity.ID = incidentRole.ID
|
|
incidentRolesEntity.CreatedAt = incidentRole.CreatedAt
|
|
incidentRolesEntity.UpdatedAt = time.Now()
|
|
addResult := r.gormClient.Save(incidentRolesEntity)
|
|
if addResult != nil {
|
|
return addResult.Error
|
|
}
|
|
return nil
|
|
|
|
} else if result.RowsAffected == 0 {
|
|
addResult := r.gormClient.Create(incidentRolesEntity)
|
|
if addResult != nil {
|
|
return addResult.Error
|
|
}
|
|
return nil
|
|
}
|
|
return gorm.ErrInvalidData
|
|
}
|
|
|
|
func (r *Repository) FindIncidentStatusById(incidentStatusId uint) (*IncidentStatusEntity, error) {
|
|
var incidentStatusEntity IncidentStatusEntity
|
|
|
|
result := r.gormClient.Find(&incidentStatusEntity, "id = ?", incidentStatusId)
|
|
if result.Error != nil {
|
|
return nil, result.Error
|
|
}
|
|
if result.RowsAffected == 0 {
|
|
return nil, nil
|
|
}
|
|
|
|
return &incidentStatusEntity, nil
|
|
}
|
|
|
|
func (r *Repository) FindIncidentStatusByName(name string) (*IncidentStatusEntity, error) {
|
|
var incidentStatusEntity IncidentStatusEntity
|
|
|
|
result := r.gormClient.Find(&incidentStatusEntity, "LOWER(name) = LOWER(?)", name)
|
|
if result.Error != nil {
|
|
return nil, result.Error
|
|
}
|
|
if result.RowsAffected == 0 {
|
|
return nil, nil
|
|
}
|
|
|
|
return &incidentStatusEntity, nil
|
|
}
|
|
|
|
func (r *Repository) FetchAllIncidentStatuses() (*[]IncidentStatusEntity, error) {
|
|
var incidentStatusEntity []IncidentStatusEntity
|
|
result := r.gormClient.Find(&incidentStatusEntity)
|
|
if result.Error != nil {
|
|
return nil, result.Error
|
|
}
|
|
|
|
if result.RowsAffected == 0 {
|
|
return nil, nil
|
|
}
|
|
|
|
return &incidentStatusEntity, nil
|
|
}
|
|
|
|
func (r *Repository) CreateIncidentChannelEntry(request *CreateIncidentChannelEntry) error {
|
|
messageEntity := &IncidentChannelEntity{
|
|
SlackChannel: request.SlackChannel,
|
|
MessageTimeStamp: request.MessageTimeStamp,
|
|
IncidentId: request.IncidentId,
|
|
}
|
|
|
|
result := r.gormClient.Create(&messageEntity)
|
|
if result.Error != nil {
|
|
return result.Error
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (r *Repository) CreateIncidentTag(incidentId, tagId uint) (*IncidentTagEntity, error) {
|
|
incidentTag := IncidentTagEntity{
|
|
IncidentId: incidentId,
|
|
TagId: tagId,
|
|
}
|
|
|
|
result := r.gormClient.Create(&incidentTag)
|
|
if result.Error != nil {
|
|
return nil, result.Error
|
|
}
|
|
return &incidentTag, nil
|
|
}
|
|
|
|
func (r *Repository) CreateIncidentTagsInBatchesForAnIncident(incidentId uint, tagIds []uint) (*[]IncidentTagEntity, error) {
|
|
var incidentTags []IncidentTagEntity
|
|
for _, tagId := range tagIds {
|
|
incidentTag := IncidentTagEntity{
|
|
IncidentId: incidentId,
|
|
TagId: tagId,
|
|
}
|
|
incidentTags = append(incidentTags, incidentTag)
|
|
}
|
|
|
|
result := r.gormClient.CreateInBatches(&incidentTags, len(incidentTags))
|
|
if result.Error != nil {
|
|
return nil, result.Error
|
|
}
|
|
return &incidentTags, nil
|
|
}
|
|
|
|
func (r *Repository) GetIncidentChannels(incidentId uint) (*[]IncidentChannelEntity, error) {
|
|
var incidentChannels []IncidentChannelEntity
|
|
|
|
result := r.gormClient.Find(&incidentChannels, "incident_id = ?", incidentId)
|
|
if result.Error != nil {
|
|
return nil, result.Error
|
|
}
|
|
|
|
if result.RowsAffected == 0 {
|
|
return nil, nil
|
|
}
|
|
|
|
return &incidentChannels, nil
|
|
}
|
|
|
|
func (r *Repository) GetIncidentTagsByIncidentId(incidentId uint) (*[]IncidentTagEntity, error) {
|
|
var incidentTags []IncidentTagEntity
|
|
|
|
result := r.gormClient.Find(&incidentTags, "incident_id = ?", incidentId)
|
|
if result.Error != nil {
|
|
return nil, result.Error
|
|
}
|
|
if result.RowsAffected == 0 {
|
|
return nil, nil
|
|
}
|
|
|
|
return &incidentTags, nil
|
|
}
|
|
|
|
func (r *Repository) GetIncidentTagByTagId(incidentId uint, tagId uint) (*IncidentTagEntity, error) {
|
|
var incidentTag IncidentTagEntity
|
|
|
|
result := r.gormClient.Find(&incidentTag, "incident_id = ? and tag_id = ?", incidentId, tagId)
|
|
if result.Error != nil {
|
|
return nil, result.Error
|
|
} else if result.RowsAffected == 0 {
|
|
return nil, nil
|
|
}
|
|
|
|
return &incidentTag, nil
|
|
}
|
|
|
|
func (r *Repository) GetIncidentTagsByTagIds(incidentId uint, tagIds []uint) (*IncidentTagEntity, error) {
|
|
var incidentTag IncidentTagEntity
|
|
|
|
result := r.gormClient.Find(&incidentTag, "incident_id = ? and tag_id in ?", incidentId, tagIds)
|
|
if result.Error != nil {
|
|
return nil, result.Error
|
|
} else if result.RowsAffected == 0 {
|
|
return nil, nil
|
|
}
|
|
|
|
return &incidentTag, nil
|
|
}
|
|
|
|
func (r *Repository) SaveIncidentTag(entity IncidentTagEntity) (*IncidentTagEntity, error) {
|
|
tx := r.gormClient.Save(&entity)
|
|
if tx.Error != nil {
|
|
return nil, tx.Error
|
|
}
|
|
return &entity, nil
|
|
}
|
|
|
|
func (r *Repository) FindIncidentsByNotResolvedStatusAndGreaterSeverityTatThanCurrentDateAndNotSev0(db *gorm.DB, resolvedIndex int) ([]IncidentEntity, error) {
|
|
var incidentEntity []IncidentEntity
|
|
|
|
currentTime := time.Now()
|
|
|
|
result := r.gormClient.Table("incident").
|
|
Where("incident_status.name <> ? and incident_status.name <> ? and incident.severity_tat <= ? and severity.id <> ?", Resolved, Duplicated, currentTime, 1).
|
|
Joins("JOIN severity ON severity.id = incident.severity_id").
|
|
Joins("JOIN incident_status on incident.status = incident_status.id").
|
|
Select("incident.*").
|
|
Scan(&incidentEntity)
|
|
|
|
if result.Error != nil {
|
|
return nil, result.Error
|
|
}
|
|
if result.RowsAffected == 0 {
|
|
return nil, nil
|
|
}
|
|
|
|
return incidentEntity, nil
|
|
}
|
|
|
|
func (r *Repository) GetIncidentsByTeamIdAndNotResolvedAndOfSev0OrSev1OrSev2(team_id uint) (*[]IncidentEntity, error) {
|
|
var incidentEntity []IncidentEntity
|
|
|
|
result := r.gormClient.Order("severity_id").Order("created_at desc").Find(&incidentEntity, "team_id = ? AND status NOT IN ? AND severity_id IN ?", team_id, []uint{4, 5}, []uint{1, 2, 3})
|
|
if result.Error != nil {
|
|
return nil, result.Error
|
|
}
|
|
|
|
return &incidentEntity, nil
|
|
}
|
|
|
|
func (r *Repository) GetCountOfIncidentsByTeamIdAndNotResolved(team_id uint) (int, error) {
|
|
var incidentEntity []IncidentEntity
|
|
|
|
result := r.gormClient.Find(&incidentEntity, "team_id = ? AND status NOT IN ? AND severity_id IN (1,2,3)", team_id, []uint{4, 5})
|
|
if result.Error != nil {
|
|
return 0, result.Error
|
|
}
|
|
|
|
return int(result.RowsAffected), nil
|
|
}
|
|
|
|
func (r *Repository) GetIncidentRoleByIncidentIdAndRole(incident_id uint, role string) (*IncidentRoleEntity, error) {
|
|
var incidentRoleEntity IncidentRoleEntity
|
|
|
|
result := r.gormClient.Find(&incidentRoleEntity, "incident_id = ? and role = ? and deleted_at IS NULL", incident_id, role)
|
|
if result.Error != nil {
|
|
return nil, result.Error
|
|
}
|
|
|
|
return &incidentRoleEntity, nil
|
|
}
|
|
|
|
func (r *Repository) GetOpenIncidentsByCreatorIdForGivenTeam(created_by string, teamId uint) (*[]IncidentEntity, error) {
|
|
var incidentEntities []IncidentEntity
|
|
|
|
incidentStatuses, err := r.FetchAllNonTerminalIncidentStatuses()
|
|
|
|
if err != nil {
|
|
logger.Error("Error in fetching non terminal incident statuses", zap.Error(err))
|
|
return nil, err
|
|
}
|
|
|
|
if incidentStatuses == nil {
|
|
err := errors.New("Could not find any non terminal incident statuses")
|
|
logger.Error("Error in fetching non terminal incident statuses", zap.Error(err))
|
|
return nil, err
|
|
}
|
|
|
|
var statusIds []uint
|
|
|
|
for _, status := range *incidentStatuses {
|
|
statusIds = append(statusIds, status.ID)
|
|
}
|
|
|
|
result := r.gormClient.Find(&incidentEntities, "created_by = ? AND team_id = ? AND status IN ?", created_by, teamId, statusIds)
|
|
|
|
if result.Error != nil {
|
|
logger.Error(fmt.Sprintf("Error in fetching open incidents created by %s and for team %d", created_by, teamId), zap.Error(err))
|
|
return nil, result.Error
|
|
}
|
|
|
|
return &incidentEntities, nil
|
|
}
|
|
|
|
func (r *Repository) FindOpenIncidentsByTeamOrderedByCreationTimeAndSeverity(team string) (*[]IncidentEntity, error) {
|
|
var incidentEntity []IncidentEntity
|
|
query := fmt.Sprintf("SELECT * FROM incident WHERE team_id = %v AND status NOT IN (4, 5) AND deleted_at IS NULL ORDER BY severity_id, id", team)
|
|
result :=
|
|
r.gormClient.Raw(query).Scan(&incidentEntity)
|
|
if result.Error != nil {
|
|
return nil, result.Error
|
|
}
|
|
return &incidentEntity, nil
|
|
}
|
|
|
|
func (r *Repository) FetchAllNonTerminalIncidentStatuses() (*[]IncidentStatusEntity, error) {
|
|
var incidentStatusEntity []IncidentStatusEntity
|
|
result := r.gormClient.Find(&incidentStatusEntity, "is_terminal_status", false)
|
|
if result.Error != nil {
|
|
return nil, result.Error
|
|
}
|
|
|
|
if result.RowsAffected == 0 {
|
|
return nil, nil
|
|
}
|
|
|
|
return &incidentStatusEntity, nil
|
|
}
|
|
|
|
func (r *Repository) FetchAllOpenIncidentsWithSeverityTATGreaterThan(slaStart, slaEnd string, severityId ...int) (*[]IncidentEntity, error) {
|
|
var incidents []IncidentEntity
|
|
query := fmt.Sprintf("SELECT * FROM incident WHERE severity_tat >= '%v' AND severity_tat < '%v' AND severity_id IN (%v) AND status IN (SELECT id FROM incident_status WHERE is_terminal_status = false) ORDER BY team_id;", slaStart, slaEnd, strings.Trim(strings.Join(strings.Fields(fmt.Sprint(severityId)), ","), "[]"))
|
|
logger.Info("Query: ", zap.String("query", query))
|
|
result := r.gormClient.Raw(query).Scan(&incidents)
|
|
if result.Error != nil {
|
|
return nil, result.Error
|
|
}
|
|
return &incidents, nil
|
|
}
|
|
|
|
func (r *Repository) GetUnArchivedAndTerminatedIncidentChannels() ([]IncidentChannelEntity, error) {
|
|
var incidentChannels []IncidentChannelEntity
|
|
startTime := viper.GetInt64("cron.job.archival_time_in_hour")
|
|
interval := viper.GetInt64("cron.job.archival_interval_in_hour")
|
|
endTime := startTime + interval
|
|
intervalEnd := fmt.Sprintf("NOW() - interval '%d hours'", endTime)
|
|
intervalStart := fmt.Sprintf("NOW() - interval '%d hours'", startTime)
|
|
|
|
query := r.gormClient.Table("incident_channel").
|
|
Joins("JOIN incident ON incident_channel.slack_channel = incident.slack_channel").
|
|
Where("incident.status IN (?,?)", ResolvedId, DuplicateId).
|
|
Where("incident.severity_id IN (?,?)", Sev2Id, Sev3Id).
|
|
Where(fmt.Sprintf("incident.end_time BETWEEN (%s) AND (%s)", intervalEnd, intervalStart)).
|
|
Where("incident_channel.is_archived IS NOT TRUE")
|
|
|
|
if err := query.Find(&incidentChannels).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
return incidentChannels, nil
|
|
}
|
|
|
|
func (r *Repository) UpdateIncidentChannelEntity(incidentChannelEntity *IncidentChannelEntity) error {
|
|
result := r.gormClient.Select("*").Updates(incidentChannelEntity)
|
|
if result.Error != nil {
|
|
return result.Error
|
|
}
|
|
return nil
|
|
}
|