Skip to content

Commit

Permalink
makefile, compose updates, updateIsReady handler
Browse files Browse the repository at this point in the history
  • Loading branch information
skewb1k committed Dec 19, 2024
1 parent 1544d6a commit be6aacb
Show file tree
Hide file tree
Showing 22 changed files with 370 additions and 100 deletions.
9 changes: 4 additions & 5 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
SERVER_PORT=
SERVER_HOST=
SERVER_UPDATES_INTERVAL=
SERVER_LOG_LEVEL=
SERVER_PORT=
SERVER_SECRET=

REDIS_PORT=
REDIS_HOST=
REDIS_PASSWORD=
REDIS_PASSWORD=
45 changes: 45 additions & 0 deletions .golangci.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# https://golangci-lint.run/usage/configuration/
run:
# Lint only *.go files that were changed in the git commit range (default: HEAD~1..HEAD)
tests: false # Don't lint _test.go files
concurrency: 4 # Max number of parallel linters to run
timeout: 5m # Max run time for the linter

linters:
enable:
- govet # Go vet for catching static issues
- staticcheck # Replacement for deprecated megacheck suite
- revive # Extensible, configurable, and faster alternative to golint
- gofumpt # Enforces consistent formatting
- gocyclo # Enforces complexity rules (default < 15)
- goimports # Ensures properly ordered imports
- gosimple # Reports simplifiable code
- unused # Finds unused variables, constants, etc.
- prealloc # Highlights preallocations for performance
- misspell # Finds and fixes spelling mistakes
- exhaustruct # Enforces initializing all struct fields
- unparam # Identifies unused function parameters
- nolintlint # Flags incorrect `nolint` comments
disable:
- errcheck

linters-settings:
misspell:
locale: US # Enforce American English spelling
revive:
severity: warning # Set the default severity for all rules
exhaustruct:
exclude:
- '^github\.com/redis/go-redis/v9\.Options$'
- '^github\.com/gorilla/websocket\.Upgrader$'
- '^net/http\.Server$'
- '^log/slog\.HandlerOptions$'

issues:
max-same-issues: 3 # Limits the number of identical issues
max-issues-per-linter: 20 # Limits the number of issues per linter

output:
formats:
- format: colored-line-number
print-issued-lines: true # Print offending lines for issues
25 changes: 22 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,36 +1,55 @@
.DEFAULT_GOAL := lint

.PHONY: gen-env-example
gen-env-example:
sed 's/=.*/=/' .env > .env.example

.PHONY: down
down:
docker compose down

.PHONY: up
up:
docker compose up

.PHONY: upd
upd:
docker compose up -d

.PHONY: build
build:
docker compose build

.PHONY: run
run:
docker compose up --build

.PHONY: rund
rund:
docker compose up --build -d

.PHONY: logs
logs:
docker logs -f sharetube-server | sed 's/\\n/\n/g'

.PHONY: run-logs
run-logs: rund logs

.PHONY: lint
lint:
golangci-lint run

.PHONY: format
format:
gofumpt -l .

.PHONY: test
test:
go test -v ./internal/app

.PHONY: docker-clean
docker-clean:
docker compose down --remove-orphans
docker system prune -af
docker volume prune -f
docker network prune -f

.PHONY: gen-env-example up upd run rund build logs docker-clean run-logs
docker network prune -f
2 changes: 1 addition & 1 deletion cmd/server/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ var (
redisHost = configVar[string]{
envKey: "REDIS_HOST",
flagKey: "redis-host",
defaultValue: "sharetube-redis",
defaultValue: "localhost",
}
redisPassword = configVar[string]{
envKey: "REDIS_PASSWORD",
Expand Down
11 changes: 4 additions & 7 deletions docker-compose.yml → compose.yaml
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
services:
redis:
image: redis:7.4.1-alpine3.20
container_name: sharetube-redis
entrypoint: redis-server --requirepass ${REDIS_PASSWORD}
container_name: ${REDIS_HOST}
entrypoint: redis-server --requirepass ${REDIS_PASSWORD} --port ${REDIS_PORT}
ports:
- ${REDIS_PORT}:${REDIS_PORT}
healthcheck:
test: ["CMD", "redis-cli", "ping"]
test: ["CMD", "redis-cli","-p", "${REDIS_PORT}","ping"]
interval: 1s
timeout: 1s
retries: 10
Expand Down Expand Up @@ -45,7 +45,4 @@ services:
# - sharetube

networks:
sharetube:

volumes:
certs:
sharetube:
1 change: 1 addition & 0 deletions internal/controller/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ type iRoomService interface {
RemoveMember(context.Context, *room.RemoveMemberParams) (room.RemoveMemberResponse, error)
PromoteMember(context.Context, *room.PromoteMemberParams) (room.PromoteMemberResponse, error)
UpdateProfile(context.Context, *room.UpdateProfileParams) (room.UpdateProfileResponse, error)
UpdateIsReady(context.Context, *room.UpdateIsReadyParams) (room.UpdateIsReadyResponse, error)
}

type controller struct {
Expand Down
4 changes: 1 addition & 3 deletions internal/controller/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,4 @@ package controller

import "errors"

var (
ErrValidationError = errors.New("validation error")
)
var ErrValidationError = errors.New("validation error")
1 change: 1 addition & 0 deletions internal/controller/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ func (c controller) broadcast(conns []*websocket.Conn, output *Output) error {
for _, conn := range conns {
if err := conn.WriteJSON(output); err != nil {
slog.Warn("failed to broadcast", "error", err)
return err
}
}

Expand Down
52 changes: 51 additions & 1 deletion internal/controller/ws-router.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ func (c controller) getWSRouter() *wsrouter.WSRouter {
// profile
mux.Handle("UPDATE_PROFILE", c.handleUpdateProfile)
// mux.Handle("UPDATE_MUTED", c.handleUpdateMuted)
// mux.Handle("UPDATE_READY", c.handleUpdateReady)
mux.Handle("UPDATE_READY", c.handleUpdateIsReady)

return mux
}
Expand Down Expand Up @@ -76,6 +76,7 @@ func (c controller) handleUpdatePlayerState(ctx context.Context, conn *websocket
Type: "PLAYER_UPDATED",
Payload: updatePlayerStateResp.PlayerState,
}); err != nil {
c.logger.ErrorContext(ctx, "failed to broadcast", "error", err)
return
}
}
Expand Down Expand Up @@ -336,3 +337,52 @@ func (c controller) handleUpdateProfile(ctx context.Context, conn *websocket.Con
return
}
}

func (c controller) handleUpdateIsReady(ctx context.Context, conn *websocket.Conn, payload json.RawMessage) {
c.logger.InfoContext(ctx, "update is_ready")
roomId := c.getRoomIdFromCtx(ctx)
memberId := c.getMemberIdFromCtx(ctx)

var data struct {
IsReady bool `json:"is_ready"`
}
if err := c.unmarshalJSONorError(conn, payload, &data); err != nil {
return
}

updatePlayerVideoResp, err := c.roomService.UpdateIsReady(ctx, &room.UpdateIsReadyParams{
IsReady: data.IsReady,
SenderId: memberId,
RoomId: roomId,
SenderConn: conn,
})
if err != nil {
c.logger.DebugContext(ctx, "failed to update player video", "error", err)
if err := c.writeError(conn, err); err != nil {
c.logger.ErrorContext(ctx, "failed to write error", "error", err)
}

return
}

if err := c.broadcast(updatePlayerVideoResp.Conns, &Output{
Type: "MEMBER_UPDATED",
Payload: map[string]any{
"updated_member": updatePlayerVideoResp.UpdatedMember,
"members": updatePlayerVideoResp.Members,
},
}); err != nil {
c.logger.ErrorContext(ctx, "failed to broadcast", "error", err)
return
}

if updatePlayerVideoResp.PlayerState != nil {
if err := c.broadcast(updatePlayerVideoResp.Conns, &Output{
Type: "PLAYER_UPDATED",
Payload: updatePlayerVideoResp.PlayerState,
}); err != nil {
c.logger.ErrorContext(ctx, "failed to broadcast", "error", err)
return
}
}
}
1 change: 1 addition & 0 deletions internal/repository/connection/inmemory/repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ func NewRepo(logger *slog.Logger) *repo {
connList: make(map[*websocket.Conn]string),
idList: make(map[string]*websocket.Conn),
logger: logger,
mu: sync.RWMutex{},
}
}

Expand Down
1 change: 0 additions & 1 deletion internal/repository/room/member.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ type Member struct {
IsMuted bool `redis:"is_muted"`
IsAdmin bool `redis:"is_admin"`
IsReady bool `redis:"is_ready"`
RoomId string `redis:"room_id"`
}

type AddMemberToListParams struct {
Expand Down
59 changes: 41 additions & 18 deletions internal/repository/room/redis/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,18 @@ package redis
import (
"context"
"encoding/json"
"log/slog"
"reflect"

"github.com/redis/go-redis/v9"
)

func (r repo) addWithIncrement(ctx context.Context, c redis.Scripter, key string, value interface{}) error {
return c.EvalSha(ctx, r.maxScoreScript, []string{key}, value).Err()
func (r repo) addWithIncrement(ctx context.Context, c redis.Scripter, key string, value interface{}) {
c.EvalSha(ctx, r.maxScoreScript, []string{key}, value)
}

// Same as HSet, but returns error if key already exists (implemented with lua script)
func (r repo) hSetIfNotExists(ctx context.Context, c redis.Scripter, key string, value interface{}) error {
func (r repo) hSetIfNotExists(ctx context.Context, c redis.Scripter, key string, value interface{}) {
v := reflect.ValueOf(value)
t := v.Type()

Expand All @@ -36,10 +37,7 @@ func (r repo) hSetIfNotExists(ctx context.Context, c redis.Scripter, key string,
// Convert field value to string
fieldValue := v.Field(i).Interface()

b, err := json.Marshal(fieldValue)
if err != nil {
return err
}
b, _ := json.Marshal(fieldValue)

strValue = string(b)
}
Expand All @@ -48,27 +46,52 @@ func (r repo) hSetIfNotExists(ctx context.Context, c redis.Scripter, key string,

}

result, err := c.EvalSha(ctx, r.hSetIfNotExistsScript, []string{key}, args...).Result()
if err != nil {
return err
c.EvalSha(ctx, r.hSetIfNotExistsScript, []string{key}, args...)
}

func (r repo) HSetStruct(ctx context.Context, c redis.Pipeliner, key string, value interface{}) error {
v := reflect.ValueOf(value)
if v.Kind() == reflect.Ptr {
v = v.Elem()
}

if result == 0 {
return redis.Nil
fields := make(map[string]interface{})
t := v.Type()

for i := 0; i < v.NumField(); i++ {
field := v.Field(i)
tag := t.Field(i).Tag.Get("redis")
if tag == "" {
tag = t.Field(i).Name
}

// Handle nil pointer fields
if field.Kind() == reflect.Ptr && field.IsNil() {
continue
}

// Get the actual value for pointer fields
if field.Kind() == reflect.Ptr {
fields[tag] = field.Elem().Interface()
} else {
fields[tag] = field.Interface()
}
}

return nil
return c.HSet(ctx, key, fields).Err()
}

func (r repo) executePipe(ctx context.Context, pipe redis.Pipeliner) error {
cmds, err := pipe.Exec(ctx)
if err != nil {
return err
}
for _, cmd := range cmds {
if err := cmd.Err(); err != nil {
return err
slog.InfoContext(ctx, "redis tx err != nil", "error", err)
for _, cmd := range cmds {
if err := cmd.Err(); err != nil {
slog.ErrorContext(ctx, "redis tx error", "error", err)
}
}

return err
}

return nil
Expand Down
4 changes: 2 additions & 2 deletions internal/repository/room/redis/member.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,11 @@ func (r repo) SetMember(ctx context.Context, params *room.SetMemberParams) error
IsMuted: params.IsMuted,
IsAdmin: params.IsAdmin,
IsReady: params.IsReady,
RoomId: params.RoomId,
}

memberKey := r.getMemberKey(params.MemberId)
//? replace with hsetifnotexists
pipe.HSet(ctx, memberKey, member)
r.HSetStruct(ctx, pipe, memberKey, member)
pipe.Expire(ctx, memberKey, 10*time.Minute)

r.addMemberToList(ctx, pipe, params.RoomId, params.MemberId)
Expand Down
2 changes: 1 addition & 1 deletion internal/repository/room/redis/video.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ func (r repo) SetVideo(ctx context.Context, params *room.SetVideoParams) error {
}

func (r repo) getVideo(ctx context.Context, params *room.GetVideoParams) (room.Video, error) {
video := room.Video{}
var video room.Video
if err := r.rc.HGetAll(ctx, r.getVideoKey(params.RoomId, params.VideoId)).Scan(&video); err != nil {
return room.Video{}, err
}
Expand Down
2 changes: 1 addition & 1 deletion internal/repository/room/video.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ type SetVideoParams struct {
RoomId string
URL string
AddedById string
Version int
// Version int
}

type GetVideoParams struct {
Expand Down
Loading

0 comments on commit be6aacb

Please sign in to comment.