Skip to content

Instantly share code, notes, and snippets.

@zzerjae
Created October 31, 2020 08:14
Show Gist options
  • Save zzerjae/35645da527f2651621d296edac66cde9 to your computer and use it in GitHub Desktop.
Save zzerjae/35645da527f2651621d296edac66cde9 to your computer and use it in GitHub Desktop.
package worker
type NewArticleEvent struct {
RegionId int64
PublishRange int
WriterId int64
ArticleId int64
Title string
}
type Matched struct {
UserId int64
Keyword string
}
type Worker struct {
RegionSvc RegionService
NotificationSvc NotificationService
UserSvc UserService
DB DB
}
type RegionService interface {
GetRegionIdsByRange(regionId int64, publishRange int) ([]int64, error)
}
type NotificationService interface {
Send(userId int64, keyword string, articleId int64, Title string)
}
type UserService interface {
BatchGetBlockingUsers(userIds []int64, userId int64) (map[int64]bool, error)
}
type DB interface {
FindMatchedUsers(title string, regionIdsByRange [][]int64) ([][]Matched, error)
}
// 내가 작성해야할 서비스
func (w *Worker) Work(e NewArticleEvent) {
// 게시글의 인접지역을 조회하여, 노출 범위별로 지역을 나눈다.
targetRegions, err := w.listRegionIdsByPublishRange(e.RegionId, e.PublishRange)
if err != nil {
return
}
// Title에 매칭되는 키워드를 구독하고 있는 유저를 각 지역별로 찾는다.
MatchedByRange, err := w.DB.FindMatchedUsers(e.Title, targetRegions)
if err != nil {
return
}
// 대상 유저들이 작성자를 차단하는지 찾는다.
isUserBockWriterMap, err := w.batchGetBlockingUsers(MatchedByRange, e.WriterId)
if err != nil {
return
}
// 알림을 전송한다.
for _, matched := range MatchedByRange {
for _, m := range matched {
if isUserBockWriterMap[m.UserId] {
continue
}
w.NotificationSvc.Send(m.UserId, m.Keyword, e.ArticleId, e.Title)
}
}
}
// 지역의 인접범위를 조회하여, 노출 범위별로 나눈다.
func (w *Worker) listRegionIdsByPublishRange(regionId int64, publishRange int) ([][]int64, error) {
resultRegions := make([][]int64, publishRange+1)
resultRegions[0] = []int64{regionId}
for i := 1; i <= publishRange; i++ {
regionIds, err := w.RegionSvc.GetRegionIdsByRange(regionId, i)
if err != nil {
return nil, err
}
for _, id := range regionIds {
already := false
alreadyExist:
for j := 0; j < i; j++ {
for _, alreadExistId := range resultRegions[j] {
if id == alreadExistId {
already = true
break alreadyExist
}
}
}
if !already {
resultRegions[i] = append(resultRegions[i], id)
}
}
}
return resultRegions, nil
}
// 지역별로 존재하는 대상 유저들이 작성자를 차단하는지 확인한다.
func (w *Worker) batchGetBlockingUsers(matchedByRange [][]Matched, writerId int64) (map[int64]bool, error) {
var userIds []int64
for _, matched := range matchedByRange {
for _, m := range matched {
userIds = append(userIds, m.UserId)
}
}
userBlockMap, err := w.UserSvc.BatchGetBlockingUsers(userIds, writerId)
if err != nil {
return nil, err
}
return userBlockMap, nil
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment