Files
houston-be/internal/processor/action/member_join_action.go

183 lines
6.5 KiB
Go

package action
import (
"fmt"
"github.com/slack-go/slack/slackevents"
"github.com/slack-go/slack/socketmode"
"go.uber.org/zap"
"houston/appcontext"
"houston/common"
"houston/common/metrics"
"houston/common/util"
"houston/internal/processor/action/view"
"houston/logger"
"houston/model/incident"
incidentStatusModel "houston/model/incidentStatus"
severityModel "houston/model/severity"
"houston/model/team"
"houston/repository/severity"
incidentStatusService "houston/service/incidentStatus"
"houston/service/incidentUser"
incidentUserRequest "houston/service/request/incidentUser"
userService "houston/service/user"
"sync"
)
type MemberJoinAction struct {
client *socketmode.Client
incidentService *incident.Repository
teamService *team.Repository
severityService *severity.Repository
incidentStatusService incidentStatusService.IncidentStatusService
userService userService.UserService
incidentUserService incidentUser.IncidentUserService
}
func NewMemberJoinAction(socketModeClient *socketmode.Client, incidentService *incident.Repository, teamService *team.Repository, severityService *severity.Repository) *MemberJoinAction {
return &MemberJoinAction{
client: socketModeClient,
incidentService: incidentService,
teamService: teamService,
severityService: severityService,
incidentStatusService: appcontext.GetIncidentStatusService(),
userService: appcontext.GetUserService(),
incidentUserService: appcontext.GetIncidentUserService(),
}
}
func (mp *MemberJoinAction) PerformAction(memberJoinedChannelEvent *slackevents.MemberJoinedChannelEvent) {
logger.Info(fmt.Sprintf("processing member joined channel event: %v", memberJoinedChannelEvent))
incidentEntity, err := mp.incidentService.FindIncidentByChannelId(memberJoinedChannelEvent.Channel)
if err != nil {
logger.Error("error in searching incident", zap.String("channel", memberJoinedChannelEvent.Channel),
zap.String("user_id", memberJoinedChannelEvent.User), zap.Error(err))
return
} else if err == nil && incidentEntity == nil {
logger.Info("incident not found", zap.String("channel", memberJoinedChannelEvent.Channel),
zap.String("user_id", memberJoinedChannelEvent.User), zap.Error(err))
return
}
mp.postIncidentSummaryEphemeral(incidentEntity, memberJoinedChannelEvent)
go func() {
err := mp.addIncidentUserMapping(incidentEntity.ID, memberJoinedChannelEvent.User)
if err != nil {
logger.Error(fmt.Sprintf("failed to add incident-user mapping"), zap.Error(err))
metrics.PublishHoustonFlowFailureMetrics(util.ADD_INCIDENT_USER_MAPPING, err.Error())
}
}()
}
func (mp *MemberJoinAction) postIncidentSummaryEphemeral(
incidentEntity *incident.IncidentEntity, memberJoinedChannelEvent *slackevents.MemberJoinedChannelEvent,
) {
var (
responderTeam, reporterTeam *team.TeamEntity
severityEntity *severityModel.SeverityEntity
incidentStatus *incidentStatusModel.IncidentStatusDTO
errors common.ThreadSafeErrors
wg sync.WaitGroup
)
wg.Add(4)
go util.ExecuteConcurrentAction(&wg, func() {
team, err := mp.teamService.FindTeamById(incidentEntity.TeamId)
if err != nil {
logger.Error("error in fetching team", zap.String("channel", memberJoinedChannelEvent.Channel),
zap.Uint("incident_id", incidentEntity.ID), zap.Error(err))
errors.AddErrors(err)
} else if team == nil {
logger.Info("team not found", zap.String("channel", memberJoinedChannelEvent.Channel),
zap.Uint("incident_id", incidentEntity.ID))
errors.AddErrors(fmt.Errorf("team not found"))
} else {
responderTeam = team
}
})
go util.ExecuteConcurrentAction(&wg, func() {
severity, err := mp.severityService.FindSeverityById(incidentEntity.SeverityId)
if err != nil {
logger.Error("error in fetching severity", zap.String("channel", memberJoinedChannelEvent.Channel),
zap.Uint("incident_id", incidentEntity.ID), zap.Error(err))
errors.AddErrors(err)
} else if severity == nil {
logger.Info("severity not found", zap.String("channel", memberJoinedChannelEvent.Channel),
zap.Uint("incident_id", incidentEntity.ID))
errors.AddErrors(fmt.Errorf("severity not found"))
} else {
severityEntity = severity
}
})
go util.ExecuteConcurrentAction(&wg, func() {
status, err := mp.incidentStatusService.GetIncidentStatusByStatusId(incidentEntity.Status)
if err != nil {
logger.Error("error in fetching incident status", zap.String("channel", memberJoinedChannelEvent.Channel),
zap.Uint("incident_id", incidentEntity.ID), zap.Error(err))
errors.AddErrors(err)
} else if status == nil {
logger.Info("incident status not found", zap.String("channel", memberJoinedChannelEvent.Channel),
zap.Uint("incident_id", incidentEntity.ID))
errors.AddErrors(fmt.Errorf("incident status not found"))
} else {
incidentStatus = status
}
})
go util.ExecuteConcurrentAction(&wg, func() {
if incidentEntity.ReportingTeamId != nil {
team, err := mp.teamService.FindTeamById(*incidentEntity.ReportingTeamId)
if err != nil {
logger.Error("error in fetching reporting team", zap.String("channel", memberJoinedChannelEvent.Channel),
zap.Uint("incident_id", incidentEntity.ID), zap.Error(err))
errors.AddErrors(err)
} else if team == nil {
logger.Info("reporting team not found", zap.String("channel", memberJoinedChannelEvent.Channel),
zap.Uint("incident_id", incidentEntity.ID))
errors.AddErrors(fmt.Errorf("reporting team not found"))
} else {
reporterTeam = team
}
}
})
wg.Wait()
if len(errors.GetErrors()) > 0 {
return
}
blocks := view.IncidentSummarySectionV3(
incidentEntity, reporterTeam, responderTeam, severityEntity, incidentStatus,
)
msgOption := view.IncidentEphemeralMessage(incidentEntity, blocks)
_, err := mp.client.PostEphemeral(memberJoinedChannelEvent.Channel, memberJoinedChannelEvent.User, msgOption)
if err != nil {
logger.Error("post response failed", zap.Error(err))
}
}
func (mp *MemberJoinAction) addIncidentUserMapping(incidentId uint, slackUserId string) error {
user, err := mp.userService.GetHoustonUserBySlackUserId(slackUserId)
if err != nil {
logger.Error(fmt.Sprintf("failed to get user with id %s : %v", slackUserId, err))
return err
} else if user == nil {
errMsg := fmt.Sprintf("user with id %s not found", slackUserId)
logger.Error(errMsg)
return fmt.Errorf(errMsg)
}
return mp.incidentUserService.AddIncidentUser(
incidentUserRequest.AddIncidentUserRequest{
IncidentID: incidentId,
UserID: user.ID,
},
)
}