Skip to content

Commit

Permalink
[Backend] Follow some revive linter
Browse files Browse the repository at this point in the history
  • Loading branch information
Alfex4936 committed Apr 23, 2024
1 parent 430087a commit 399fc86
Show file tree
Hide file tree
Showing 17 changed files with 152 additions and 78 deletions.
2 changes: 1 addition & 1 deletion backend/handlers/chat_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ func HandleChatRoomHandler(c *websocket.Conn, markerID, reqID string) {

defer func() {
// On disconnect, remove the client from the room
services.WsRoomManager.RemoveWsFromRoom(markerID, clientId, c)
services.WsRoomManager.RemoveWsFromRoom(markerID, clientId)
// services.RemoveConnectionFromRedis(markerID, reqID)

// Broadcast leave message
Expand Down
67 changes: 52 additions & 15 deletions backend/handlers/marker_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import (
)

var (
// cache to store encoded marker data
// MarkersLocalCache cache to store encoded marker data
MarkersLocalCache []byte // 400 kb is fine here
CacheMutex sync.RWMutex
)
Expand Down Expand Up @@ -76,11 +76,6 @@ func RegisterMarkerRoutes(api fiber.Router) {
}

func createMarkerWithPhotosHandler(c *fiber.Ctx) error {
// go services.ResetCache(services.ALL_MARKERS_KEY)
CacheMutex.Lock()
MarkersLocalCache = nil
CacheMutex.Unlock()

// Parse the multipart form
form, err := c.MultipartForm()
if err != nil {
Expand All @@ -94,21 +89,52 @@ func createMarkerWithPhotosHandler(c *fiber.Ctx) error {
}

// Location Must Be Inside South Korea
if !util.IsInSouthKoreaPrecisely(latitude, longitude) {
return c.Status(fiber.StatusForbidden).JSON(fiber.Map{"error": "Operations are only allowed within South Korea."})
}
// if !util.IsInSouthKoreaPrecisely(latitude, longitude) {
// return c.Status(fiber.StatusForbidden).JSON(fiber.Map{"error": "Operations are only allowed within South Korea."})
// }

errorChan := make(chan error)
defer close(errorChan)

go func() {
if inSKorea := util.IsInSouthKoreaPrecisely(latitude, longitude); !inSKorea {
errorChan <- fmt.Errorf("operation is only allowed within South Korea")
} else {
errorChan <- nil
}
}()

// Checking if there's a marker close to the latitude and longitude
if nearby, _ := services.IsMarkerNearby(latitude, longitude, 10); nearby {
return c.Status(fiber.StatusConflict).JSON(fiber.Map{"error": "There is a marker already nearby."})
}
go func() {
if nearby, _ := services.IsMarkerNearby(latitude, longitude, 10); nearby {
errorChan <- fmt.Errorf("there is a marker already nearby")
} else {
errorChan <- nil
}
}()

// Set default description if it's empty or not provided
description := GetDescriptionFromForm(form)
if containsBadWord, _ := util.CheckForBadWords(description); containsBadWord {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Comment contains inappropriate content."})

// Concurrent check for bad words
go func() {
if containsBadWord, _ := util.CheckForBadWords(description); containsBadWord {
errorChan <- fmt.Errorf("comment contains inappropriate content")
} else {
errorChan <- nil
}
}()

for i := 0; i < 3; i++ {
if err := <-errorChan; err != nil {
return c.Status(mapErrorToStatus(err.Error())).JSON(fiber.Map{"error": err.Error()})
}
}

// no errors
CacheMutex.Lock()
MarkersLocalCache = nil
CacheMutex.Unlock()

userId := c.Locals("userID").(int)

marker, err := services.CreateMarkerWithPhotos(&dto.MarkerRequest{
Expand Down Expand Up @@ -605,3 +631,14 @@ func GetMarkerIDFromForm(form *multipart.Form) string {
}
return ""
}

func mapErrorToStatus(errorMessage string) int {
switch errorMessage {
case "There is a marker already nearby.":
return fiber.StatusConflict
case "Comment contains inappropriate content.":
return fiber.StatusBadRequest
default:
return fiber.StatusInternalServerError
}
}
7 changes: 4 additions & 3 deletions backend/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,7 @@ func setUpMiddlewares(app *fiber.App) {
Level: compress.LevelBestSpeed,
}))

// ContentSecurityPolicy: "default-src 'self'; script-src 'self' 'unsafe-inline'; object-src 'none'"
app.Use(helmet.New(helmet.Config{XSSProtection: "1; mode=block"}))
app.Use(limiter.New(limiter.Config{
Next: func(c *fiber.Ctx) bool {
Expand Down Expand Up @@ -368,8 +369,8 @@ func setUpGlobals() {

// Initialize global variables
setTokenExpirationTime()
services.AWS_REGION = os.Getenv("AWS_REGION")
services.S3_BUCKET_NAME = os.Getenv("AWS_BUCKET_NAME")
services.AwsRegion = os.Getenv("AWS_REGION")
services.S3BucketName = os.Getenv("AWS_BUCKET_NAME")
util.LOGIN_TOKEN_COOKIE = os.Getenv("TOKEN_COOKIE")
}

Expand All @@ -384,7 +385,7 @@ func setTokenExpirationTime() {
}

// Assign the converted duration to the global variable
services.TOKEN_DURATION = time.Duration(durationInt) * time.Hour
services.TokenDuration = time.Duration(durationInt) * time.Hour
}

// countAPIs counts the number of APIs in a Fiber app
Expand Down
29 changes: 29 additions & 0 deletions backend/revive.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
ignoreGeneratedHeader = false
severity = "warning"
confidence = 0.8
errorCode = 0
warningCode = 0

[rule.blank-imports]
[rule.context-as-argument]
[rule.context-keys-type]
[rule.dot-imports]
[rule.error-return]
[rule.error-strings]
[rule.error-naming]
[rule.exported]
[rule.increment-decrement]
[rule.var-naming]
[rule.var-declaration]
[rule.package-comments]
[rule.range]
[rule.receiver-naming]
[rule.time-naming]
[rule.unexported-return]
[rule.indent-error-flow]
[rule.errorf]
[rule.empty-block]
[rule.superfluous-else]
[rule.unused-parameter]
[rule.unreachable-code]
[rule.redefines-builtin-id]
6 changes: 3 additions & 3 deletions backend/services/chat_conn_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ func (manager *RoomConnectionManager) SaveConnection(markerID, clientId string,
newConn := &ChulbongConn{
Socket: conn,
UserID: clientId,
Send: make(chan []byte, 256), // Buffered channel
InActiveChan: make(chan struct{}, 10),
Send: make(chan []byte, 10), // Buffered channel
InActiveChan: make(chan struct{}),
}
newConn.UpdateLastSeen()

Expand Down Expand Up @@ -233,7 +233,7 @@ func RemoveConnectionFromRedis(markerID, xRequestID string) {
}

// RemoveConnection removes a WebSocket connection associated with a id
func (manager *RoomConnectionManager) RemoveWsFromRoom(markerID, clientId string, conn *websocket.Conn) {
func (manager *RoomConnectionManager) RemoveWsFromRoom(markerID, clientId string) {
// manager.mu.Lock() // Lock at the start of the method
// defer manager.mu.Unlock() // Unlock when the method returns

Expand Down
1 change: 1 addition & 0 deletions backend/services/chat_process_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"github.com/goccy/go-json"
)

// ProcessMessageFromSubscription processes a message from a Redis subscription
func ProcessMessageFromSubscription(msg []byte) {
var broadcastMsg dto.BroadcastMessage
err := json.Unmarshal(msg, &broadcastMsg)
Expand Down
4 changes: 2 additions & 2 deletions backend/services/chat_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ var (
retryCtx, _ = context.WithCancel(context.Background())
)

var WsRoomManager *RoomConnectionManager = NewRoomConnectionManager()
var WsRoomManager = NewRoomConnectionManager()

type ChulbongConn struct {
Socket *websocket.Conn
Expand Down Expand Up @@ -185,7 +185,7 @@ func (manager *RoomConnectionManager) BroadcastMessage(message []byte, userId, r
return
}

manager.connections.Range(func(key string, conns []*ChulbongConn) bool {
manager.connections.Range(func(_ string, conns []*ChulbongConn) bool {
// Iterate over the connections and send the message
for _, conn := range conns {
select {
Expand Down
14 changes: 7 additions & 7 deletions backend/services/marker_facilities_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,14 @@ const (
)

var (
KAKAO_AK = os.Getenv("KAKAO_AK")
KakaoAK = os.Getenv("KAKAO_AK")

HTTPClient = &http.Client{
Timeout: 10 * time.Second, // Set a timeout to avoid hanging requests indefinitely
}

IS_WATER_URL = os.Getenv("IS_WATER_API")
IS_WATER_KEY = os.Getenv("IS_WATER_API_KEY")
IsWaterURL = os.Getenv("IS_WATER_API")
IsWaterKEY = os.Getenv("IS_WATER_API_KEY")
)

// GetFacilitiesByMarkerID retrieves facilities for a given marker ID.
Expand Down Expand Up @@ -111,7 +111,7 @@ func FetchAddressFromAPI(latitude, longitude float64) (string, error) {
return "-1", fmt.Errorf("creating request: %w", err)
}

req.Header.Add("Authorization", "KakaoAK "+KAKAO_AK)
req.Header.Add("Authorization", "KakaoAK "+KakaoAK)
resp, err := HTTPClient.Do(req)
if err != nil {
return "-1", fmt.Errorf("executing request: %w", err)
Expand Down Expand Up @@ -151,7 +151,7 @@ func FetchXYFromAPI(address string) (float64, float64, error) {
return 0.0, 0.0, fmt.Errorf("creating request: %w", err)
}

req.Header.Add("Authorization", "KakaoAK "+KAKAO_AK)
req.Header.Add("Authorization", "KakaoAK "+KakaoAK)
resp, err := HTTPClient.Do(req)
if err != nil {
return 0.0, 0.0, fmt.Errorf("executing request: %w", err)
Expand Down Expand Up @@ -199,7 +199,7 @@ func FetchRegionFromAPI(latitude, longitude float64) (string, error) {
return "-1", fmt.Errorf("creating request: %w", err)
}

req.Header.Add("Authorization", "KakaoAK "+KAKAO_AK)
req.Header.Add("Authorization", "KakaoAK "+KakaoAK)
resp, err := HTTPClient.Do(req)
if err != nil {
return "-1", fmt.Errorf("executing request: %w", err)
Expand Down Expand Up @@ -275,7 +275,7 @@ func FetchWeatherFromAddress(latitude, longitude float64) (*kakao.WeatherRequest

// FetchRegionWaterInfo checks if latitude/longitude is in the water possibly.
func FetchRegionWaterInfo(latitude, longitude float64) (bool, error) {
reqURL := fmt.Sprintf("%s?latitude=%f&longitude=%f&rapidapi-key=%s", IS_WATER_URL, latitude, longitude, IS_WATER_KEY)
reqURL := fmt.Sprintf("%s?latitude=%f&longitude=%f&rapidapi-key=%s", IsWaterURL, latitude, longitude, IsWaterKEY)
req, err := http.NewRequest(http.MethodGet, reqURL, nil)
if err != nil {
return false, fmt.Errorf("creating request: %w", err)
Expand Down
2 changes: 1 addition & 1 deletion backend/services/marker_location_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ func FindRankedMarkersInCurrentArea(lat, long float64, distance, limit int) ([]d
}

ctx := context.Background()
floatMin := float64(MIN_CLICK_RANK)
floatMin := float64(MinClickRank)

result, _ := RedisStore.Do(ctx, RedisStore.B().Zmscore().Key("marker_clicks").Member(markerIDs...).Build()).AsFloatSlice()
rankedMarkers := make([]dto.MarkerWithDistance, 0, len(result))
Expand Down
50 changes: 27 additions & 23 deletions backend/services/marker_rank_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,40 +20,44 @@ import (
)

// 클릭 이벤트를 저장할 임시 저장소
var clickEventBuffer = csmap.Create(
csmap.WithShardCount[int, int](64),
csmap.WithCustomHasher[int, int](func(key int) uint64 {
// Convert int to a byte slice
bs := make([]byte, 8)
binary.LittleEndian.PutUint64(bs, uint64(key))
return xxh3.Hash(bs)
}),
var (
ClickEventBuffer = csmap.Create(
csmap.WithShardCount[int, int](64),
csmap.WithCustomHasher[int, int](func(key int) uint64 {
// Convert int to a byte slice
bs := make([]byte, 8)
binary.LittleEndian.PutUint64(bs, uint64(key))
return xxh3.Hash(bs)
}),
)

SketchedLocations = csmap.Create(
csmap.WithShardCount[string, *hyperloglog.Sketch](64),
csmap.WithCustomHasher[string, *hyperloglog.Sketch](func(key string) uint64 {
return xxh3.HashString(key)
}),
)
)

var SketchedLocations = csmap.Create(
csmap.WithShardCount[string, *hyperloglog.Sketch](64),
csmap.WithCustomHasher[string, *hyperloglog.Sketch](func(key string) uint64 {
return xxh3.HashString(key)
}),
const (
RankUpdateTime = 3 * time.Minute
MinClickRank = 5
)

const RANK_UPDATE_TIME = 3 * time.Minute
const MIN_CLICK_RANK = 5

// 클릭 이벤트를 버퍼에 추가하는 함수
func BufferClickEvent(markerID int) {
// 현재 클릭 수 조회
// 마커 ID가 존재하지 않으면 클릭 수를 1로 설정
clickEventBuffer.SetIfAbsent(markerID, 1)
ClickEventBuffer.SetIfAbsent(markerID, 1)

actual, ok := clickEventBuffer.Load(markerID)
actual, ok := ClickEventBuffer.Load(markerID)
if !ok {
return
}

// 마커 ID가 존재하면 클릭 수를 1 증가
newClicks := actual + 1
clickEventBuffer.Store(markerID, newClicks)
ClickEventBuffer.Store(markerID, newClicks)
}

func SaveUniqueVisitor(markerID string, uniqueUser string) {
Expand Down Expand Up @@ -99,13 +103,13 @@ func GetAllUniqueVisitorCounts() map[string]int {
// 정해진 시간 간격마다 클릭 이벤트 배치 처리를 실행하는 함수
func ProcessClickEventsBatch() {
// 일정 시간 간격으로 배치 처리 실행
ticker := time.NewTicker(RANK_UPDATE_TIME)
ticker := time.NewTicker(RankUpdateTime)
defer ticker.Stop() // 함수가 반환될 때 ticker를 정지

for range ticker.C {
IncrementMarkerClicks(clickEventBuffer)
IncrementMarkerClicks(ClickEventBuffer)
// 처리 후 버퍼 초기화
clickEventBuffer.Clear()
ClickEventBuffer.Clear()
}
}

Expand Down Expand Up @@ -136,7 +140,7 @@ func GetTopMarkers(limit int) []dto.MarkerSimpleWithAddr {
ctx := context.Background()

// Convert minClickRank to string and prepare for the ZRangeByScore command
minScore := strconv.Itoa(MIN_CLICK_RANK + 1) // "+1" to adjust for exclusive minimum
minScore := strconv.Itoa(MinClickRank + 1) // "+1" to adjust for exclusive minimum

// Use ZREVRANGEBYSCORE to get marker IDs in descending order based on score
markerScores, err := RedisStore.Do(ctx, RedisStore.B().Zrevrangebyscore().
Expand Down
6 changes: 3 additions & 3 deletions backend/services/notification_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ func PostNotification(userId, notificationType, title, message string, metadata
}

// GetNotifications retrieves notifications for a specific user (unviewed)
func GetNotifications(userId string) ([]NotificationRedis, error) {
func GetNotifications(userID string) ([]NotificationRedis, error) {
var notifications []Notification
const query = `(SELECT * FROM Notifications
WHERE UserId = ? AND Viewed = FALSE
Expand All @@ -71,7 +71,7 @@ func GetNotifications(userId string) ([]NotificationRedis, error) {
(SELECT * FROM Notifications
WHERE NotificationType IN ('NewMarker', 'System', 'Other') AND Viewed = FALSE
ORDER BY CreatedAt DESC)`
err := database.DB.Select(&notifications, query, userId)
err := database.DB.Select(&notifications, query, userID)
if err != nil {
return nil, err
}
Expand All @@ -89,7 +89,7 @@ func GetNotifications(userId string) ([]NotificationRedis, error) {
results[idx] = mapToNotificationRedis(notif)
}
} else {
viewed, err := IsNotificationViewed(notif.NotificationId, userId)
viewed, err := IsNotificationViewed(notif.NotificationId, userID)
if err != nil {
errors <- err
return
Expand Down
Loading

0 comments on commit 399fc86

Please sign in to comment.