Skip to content

Commit

Permalink
redis related things
Browse files Browse the repository at this point in the history
  • Loading branch information
skewb1k committed Nov 18, 2024
1 parent 74e9441 commit 91adaa2
Show file tree
Hide file tree
Showing 11 changed files with 172 additions and 18 deletions.
6 changes: 5 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
SERVER_PORT=
SERVER_HOST=
SERVER_UPDATES_INTERVAL=
SERVER_UPDATES_INTERVAL=
SERVER_LOG_LEVEL=
REDIS_PORT=
REDIS_HOST=
REDIS_PASSWORD=
49 changes: 36 additions & 13 deletions cmd/server/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,35 +22,50 @@ type configVar[T any] struct {

var (
port = configVar[int]{
envKey: "PORT",
flagKey: "port",
envKey: "SERVER_PORT",
flagKey: "server-port",
defaultValue: 8080,
}
host = configVar[string]{
envKey: "HOST",
flagKey: "host",
envKey: "SERVER_HOST",
flagKey: "server-host",
defaultValue: "0.0.0.0",
}
logLevel = configVar[string]{
envKey: "LOG_LEVEL",
flagKey: "log-level",
envKey: "SERVER_LOG_LEVEL",
flagKey: "server-log-level",
defaultValue: "INFO",
}
membersLimit = configVar[int]{
envKey: "MEMBERS_LIMIT",
flagKey: "members-limit",
envKey: "SERVER_MEMBERS_LIMIT",
flagKey: "server-members-limit",
defaultValue: 9,
}
playlistLimit = configVar[int]{
envKey: "PLAYLIST_LIMIT",
flagKey: "playlist-limit",
envKey: "SERVER_PLAYLIST_LIMIT",
flagKey: "server-playlist-limit",
defaultValue: 25,
}
updatesInterval = configVar[time.Duration]{
envKey: "UPDATES_INTERVAL",
flagKey: "updates-interval",
envKey: "SERVER_UPDATES_INTERVAL",
flagKey: "server-updates-interval",
defaultValue: 5 * time.Second,
}
redisPort = configVar[int]{
envKey: "REDIS_PORT",
flagKey: "redis-port",
defaultValue: 6379,
}
redisHost = configVar[string]{
envKey: "REDIS_HOST",
flagKey: "redis-host",
defaultValue: "localhost",
}
redisPassword = configVar[string]{
envKey: "REDIS_PASSWORD",
flagKey: "redis-password",
defaultValue: "",
}
)

func loadAppConfig() *app.AppConfig {
Expand All @@ -61,13 +76,15 @@ func loadAppConfig() *app.AppConfig {
pflag.Int(membersLimit.flagKey, membersLimit.defaultValue, "Maximum number of members in the room")
pflag.Int(playlistLimit.flagKey, playlistLimit.defaultValue, "Maximum number of videos in the playlist")
pflag.Duration(updatesInterval.flagKey, updatesInterval.defaultValue, "Interval between updates")
pflag.Int(redisPort.flagKey, redisPort.defaultValue, "Redis port")
pflag.String(redisHost.flagKey, redisHost.defaultValue, "Redis host")
pflag.String(redisPassword.flagKey, redisPassword.defaultValue, "Redis password")
pflag.Parse()

// 2. Bind flags to viper
viper.BindPFlags(pflag.CommandLine)

// 3. Set up environment variables prefix and binding
viper.SetEnvPrefix("SERVER")
viper.AutomaticEnv()

// 4. Set defaults (lowest priority)
Expand All @@ -77,6 +94,9 @@ func loadAppConfig() *app.AppConfig {
viper.SetDefault(membersLimit.envKey, membersLimit.defaultValue)
viper.SetDefault(playlistLimit.envKey, playlistLimit.defaultValue)
viper.SetDefault(updatesInterval.envKey, updatesInterval.defaultValue)
viper.SetDefault(redisPort.envKey, redisPort.defaultValue)
viper.SetDefault(redisHost.envKey, redisHost.defaultValue)
viper.SetDefault(redisPassword.envKey, redisPassword.defaultValue)

// 5. Create config struct
config := &app.AppConfig{
Expand All @@ -86,6 +106,9 @@ func loadAppConfig() *app.AppConfig {
MembersLimit: viper.GetInt(membersLimit.envKey),
PlaylistLimit: viper.GetInt(playlistLimit.envKey),
UpdatesInterval: viper.GetDuration(updatesInterval.envKey),
RedisPort: viper.GetInt(redisPort.envKey),
RedisHost: viper.GetString(redisHost.envKey),
RedisPassword: viper.GetString(redisPassword.envKey),
}

return config
Expand Down
16 changes: 16 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,18 @@
services:
redis:
image: redis:7.4.1-alpine3.20
container_name: sharetube-redis
entrypoint: redis-server --requirepass ${REDIS_PASSWORD}
ports:
- ${REDIS_PORT}:${REDIS_PORT}
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 1s
timeout: 1s
retries: 10
networks:
- sharetube

server:
container_name: sharetube-server
build:
Expand All @@ -8,6 +22,8 @@ services:
ports:
- ${SERVER_PORT}:${SERVER_PORT}
restart: unless-stopped
depends_on:
- redis
networks:
- sharetube

Expand Down
6 changes: 6 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,18 @@ require (
golang.org/x/exp v0.0.0-20230905200255-921286631fa9
)

require (
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
)

require (
github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/magiconair/properties v1.8.7 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
github.com/redis/go-redis/v9 v9.7.0
github.com/sagikazarmark/locafero v0.4.0 // indirect
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
github.com/sourcegraph/conc v0.3.0 // indirect
Expand Down
10 changes: 10 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs=
github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c=
github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA=
github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0=
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
Expand Down Expand Up @@ -29,6 +37,8 @@ github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/redis/go-redis/v9 v9.7.0 h1:HhLSs+B6O021gwzl+locl0zEDnyNkxMtf/Z3NNBMa9E=
github.com/redis/go-redis/v9 v9.7.0/go.mod h1:f6zhXITC7JUJIlPEiBOTXxJgPLdZcA93GewI7inzyWw=
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ=
Expand Down
34 changes: 32 additions & 2 deletions internal/app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ import (
"time"

"github.com/sharetube/server/internal/controller"
"github.com/sharetube/server/internal/repository/redis"
"github.com/sharetube/server/internal/service"
"github.com/sharetube/server/pkg/redisclient"
"golang.org/x/exp/slog"
)

Expand All @@ -22,9 +24,38 @@ type AppConfig struct {
PlaylistLimit int
UpdatesInterval time.Duration
LogLevel string
RedisPort int
RedisHost string
RedisPassword string `json:"-"`
}

// todo: add validation.
func (cfg *AppConfig) Validate() error {
if cfg.MembersLimit < 1 {
return fmt.Errorf("members limit must be greater than 0")
}
if cfg.PlaylistLimit < 1 {
return fmt.Errorf("playlist limit must be greater than 0")
}
if cfg.UpdatesInterval < 1 {
return fmt.Errorf("updates interval must be greater than 0")
}
return nil
}

func Run(ctx context.Context, cfg *AppConfig) error {
rc, err := redisclient.NewRedisClient(&redisclient.Config{
Port: cfg.RedisPort,
Host: cfg.RedisHost,
Password: cfg.RedisPassword,
})
if err != nil {
return fmt.Errorf("failed to create redis client: %w", err)
}
defer rc.Close()

createRoomSessionRepo := redis.NewCreateRoomSessionRepo(rc, 30*time.Second)
createRoomSessionRepo.Set(ctx, "some-value")
roomService := service.NewRoomService(cfg.UpdatesInterval, cfg.MembersLimit, cfg.PlaylistLimit)
controller := controller.NewController(roomService)
server := &http.Server{Addr: fmt.Sprintf("%s:%d", cfg.Host, cfg.Port), Handler: controller.Mux()}
Expand Down Expand Up @@ -55,8 +86,7 @@ func Run(ctx context.Context, cfg *AppConfig) error {
}()

slog.InfoContext(serverCtx, "starting server", "address", server.Addr)
err := server.ListenAndServe()
if err != nil && err != http.ErrServerClosed {
if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
return err
}

Expand Down
1 change: 1 addition & 0 deletions internal/controller/rest-handler.go
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package controller
10 changes: 8 additions & 2 deletions internal/controller/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,14 @@ func (c Controller) Mux() http.Handler {
r := chi.NewRouter()

r.Route("/api/v1", func(r chi.Router) {
r.HandleFunc("/ws/create-room", c.CreateRoom)
r.HandleFunc("/ws/join-room/{room-id}", c.JoinRoom)
r.Route("/room", func(r chi.Router) {
// r.Get("/{room-id}", c.GetRoom)
r.Route("/create", func(r chi.Router) {
r.Get("/validate", c.CreateRoom)
r.Get("/ws", c.CreateRoom)
})
r.Post("/join", c.JoinRoom)
})
})

return r
Expand Down
File renamed without changes.
30 changes: 30 additions & 0 deletions internal/repository/redis/create-room-session.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package redis

import (
"context"
"time"

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

type CreateRoomSessionRepo struct {
rc *redis.Client
expireTime time.Duration
}

const (
createRoomSessionPrefix = "create-room-session"
)

func NewCreateRoomSessionRepo(rc *redis.Client, expireTime time.Duration) *CreateRoomSessionRepo {
return &CreateRoomSessionRepo{
rc: rc,
expireTime: expireTime,
}
}

func (r CreateRoomSessionRepo) Set(ctx context.Context, value string) (string, error) {
key := uuid.NewString()
return key, r.rc.Set(ctx, createRoomSessionPrefix+key, value, r.expireTime).Err()
}
28 changes: 28 additions & 0 deletions pkg/redisclient/redis-client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package redisclient

import (
"context"
"fmt"
"time"

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

type Config struct {
Host string
Port int
Password string
}

func NewRedisClient(cfg *Config) (*redis.Client, error) {
r := redis.NewClient(&redis.Options{
Addr: fmt.Sprintf("%s:%d", cfg.Host, cfg.Port),
Password: cfg.Password,
})

if err := r.Set(context.Background(), "key", "value", time.Second).Err(); err != nil {
return nil, err
}

return r, nil
}

0 comments on commit 91adaa2

Please sign in to comment.