Skip to content

Commit

Permalink
♻️ migrate to rabbit mq
Browse files Browse the repository at this point in the history
  • Loading branch information
AlphaNecron committed Aug 31, 2023
1 parent 72b94b4 commit d20697b
Show file tree
Hide file tree
Showing 68 changed files with 1,222 additions and 2,628 deletions.
4 changes: 2 additions & 2 deletions .air.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ tmp_dir = "/tmp"
follow_symlink = false
full_bin = ""
include_dir = []
include_ext = ["go", "tpl", "tmpl", "html", "config.yml"]
include_ext = ["go", "tpl", "tmpl", "html", "blizzard.yml", ".air.toml"]
kill_delay = "0s"
log = "blizzard.build-errors.log"
send_interrupt = false
send_interrupt = true
stop_on_error = true

[color]
Expand Down
53 changes: 37 additions & 16 deletions blizzard.example.yml
Original file line number Diff line number Diff line change
@@ -1,21 +1,42 @@
host: 0.0.0.0
port: 2999
privateKey: private_key_used_to_hash_password
debug: false
enableCors: true
rateLimit: 1000
host: 0.0.0.0 # host blizzard should run on
privateKey: d057ab405abcee847b3c0ee6e8324cfbdb693803 # private key used to encrypt sessions
port: 2999 # port blizzard should run on
debug: true # whether to enable debug mode, deprecated, will be removed in the future
enableCors: true # where to enable cors
rateLimit: 100 # limit to x requests per second

judges:
north-pole: 0.0.0.0:172
ethereal: 192.168.31.202:2345 # http address of judge

oauth:
github:
clientId: your_github_client_id
clientSecret: your_github_client_secret
clientId: ba4983ed38e2e43dfbeb
clientSecret: 63b04c44475d709f939529b193551acd119a001c
discord:
clientId: your_discord_client_id
clientSecret: your_discord_client_secret
clientId: 1089944774880018493
clientSecret: rKLXDoSAiiZxBtAXhFa_vovmwMsBUYfU

storage:
problems: /path/to/problems
posts: /path/to/posts
submissions: /path/to/submissions
readmes: /path/to/readmes

redis:
host: 192.168.31.240
port: 6379
db: 0

rabbitmq:
username: guest
password: guest
host: localhost
port: 5672

database:
secure: false
address: db_addr
username: db_username
password: db_pwd
name: db_name
secure: false # whether to use tls for connection to db
host: localhost
port: 5432
username: postgres
password: postgres
name: arctic
Empty file removed blizzard.prof
Empty file.
82 changes: 39 additions & 43 deletions blizzard/cache/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,59 +5,55 @@ import (
"blizzard/blizzard/logger"
"context"
"fmt"
"github.com/allegro/bigcache/v3"
"github.com/eko/gocache/lib/v4/cache"
"github.com/eko/gocache/lib/v4/marshaler"
cachestore "github.com/eko/gocache/lib/v4/store"
bcstore "github.com/eko/gocache/store/bigcache/v4"
"strings"
"github.com/redis/rueidis"
"time"
)

type Store struct {
ctx context.Context
*marshaler.Marshaler
}

var store *Store
func init() {
}

func Init() {
ctx := context.Background()
bc, _ := bigcache.NewBigCache(bigcache.DefaultConfig(5 * time.Minute))
bcStore := bcstore.NewBigcache(bc)
cacheManager := cache.New[interface{}](bcStore)
store = &Store{Marshaler: marshaler.New(cacheManager), ctx: ctx}
func create(db int, name string) (c rueidis.Client) {
c, e := rueidis.NewClient(rueidis.ClientOption{
InitAddress: []string{fmt.Sprintf("%s:%d", config.Config.Redis.Host, config.Config.Redis.Port)},
SelectDB: db,
DisableCache: true,
})
logger.Panic(e, "failed to initialize redis client for %s cache", name)
return
}

func Get[T any](category, key string, loader func() (T, error)) *T {
if config.Config.Debug {
v, e := loader()
if e != nil {
return nil
}
return &v
}
if strings.TrimSpace(key) == "" {
return nil
}
val, e := store.Get(store.ctx, key, new(T))
func Get[T any](key string, loader func() (T, error), duration time.Duration) *T {
//if config.Config.Debug {
// v, e := loader()
// if e != nil {
// return nil
// }
// return &v
//}
//val, e := store.Get(store.ctx, key, new(T))
//fmt.Println(e)
//if e != nil {
// v, e := loader()
// if e != nil {
// return nil
// }
// e = store.Set(store.ctx, key, v, cachestore.WithExpiration(duration))
// return &v
//}
//if v, ok := val.(*T); ok {
// logger.Logger.Debug().Str("key", key).Interface("data", v).Msg("cache hit")
// return v
//} else {
// Invalidate(key)
//}
//return nil
v, e := loader()
if e != nil {
v, e := loader()
if e != nil {
return nil
}
e = store.Set(store.ctx, key, v, cachestore.WithExpiration(time.Hour*24))
return &v
}
if v, ok := val.(*T); ok {
logger.Logger.Debug().Str("key", category+"_"+key).Interface("data", v).Msg("cache hit")
return v
} else {
fmt.Println("fail")
return nil
}
return nil
}

func Invalidate(category, key string) bool {
return store.Delete(store.ctx, category+"_"+key) == nil
return &v
}
135 changes: 135 additions & 0 deletions blizzard/cache/result.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
package cache

import (
"blizzard/blizzard/db/models/contest"
"blizzard/blizzard/utils"
"context"
"encoding/json"
"errors"
"fmt"
"github.com/redis/rueidis"
"strconv"
"strings"
"sync"
)

type ResultCache struct {
rueidis.Client
l sync.RWMutex
tl sync.RWMutex
}

var Result *ResultCache

const defaultResultKey = "blizzard::case_results[%d]"

const defaultTagKey = "blizzard::pending_submission[%d]"

const defaultTtl = 15

// 30 minutes
const defaultInitialTtl = 30 * 60

func init() {
Result = &ResultCache{Client: create(1, "results")}
}

func (c *ResultCache) GetTag(id uint32) (uint64, error) {
c.tl.RLock()
defer c.tl.RUnlock()
return c.Do(context.Background(), c.B().Get().Key(c.createTagKey(id)).Build()).AsUint64()
}

func (c *ResultCache) SetTag(id uint32, tag uint64) error {
c.tl.Lock()
defer c.tl.Unlock()
key := c.createTagKey(id)
res := c.DoMulti(
context.Background(),
c.B().Set().Key(key).Value(strconv.FormatUint(tag, 10)).Build(),
c.B().Expire().Key(key).Seconds(defaultInitialTtl).Build())
if e := res[0].Error(); e != nil {
return e
}
return res[1].Error()
}

func (c *ResultCache) DeleteTag(id uint32) error {
c.tl.Lock()
defer c.tl.Unlock()
return c.Do(context.Background(), c.B().Del().Key(c.createTagKey(id)).Build()).Error()
}

func (c *ResultCache) createKey(id uint32) string {
return fmt.Sprintf(defaultResultKey, id)
}

func (c *ResultCache) createTagKey(id uint32) string {
return fmt.Sprintf(defaultTagKey, id)
}

func (c *ResultCache) Create(id uint32, count uint16) error {
if c.IsPending(id) {
return errors.New("submission is being judged")
}
key := c.createKey(id)
res := c.DoMulti(
context.Background(),
c.B().Del().Key(key).Build(),
c.B().Rpush().Key(key).Element(utils.ArrayFill("", int(count))...).Build(),
c.B().Expire().Key(key).Seconds(defaultInitialTtl).Build(),
)
if e := res[1].Error(); e != nil {
return e
}
return res[2].Error()
}

func (c *ResultCache) IsPending(id uint32) bool {
c.l.RLock()
defer c.l.RUnlock()
exists, e := c.Do(context.Background(), c.B().Exists().Key(c.createKey(id)).Build()).AsBool()
return exists && e == nil
}

func (c *ResultCache) Store(id uint32, caseId uint16, r contest.CaseResult, ttl int) error {
c.l.Lock()
defer c.l.Unlock()
buf, e := json.Marshal(r)
if e != nil {
return e
}
key := c.createKey(id)
if ttl == 0 {
ttl = defaultTtl
}
res := c.DoMulti(
context.Background(),
c.B().Lset().Key(key).Index(int64(caseId)).Element(string(buf)).Build(),
c.B().Expire().Key(key).Seconds(int64(ttl)).Build(),
)
if e = res[0].Error(); e != nil {
return e
}
return res[1].Error()
}

func (c *ResultCache) Get(id uint32) (string, error) {
c.l.RLock()
defer c.l.RUnlock()
res := c.Do(context.Background(), c.B().Lrange().Key(c.createKey(id)).Start(0).Stop(-1).Build())
if e := res.Error(); e != nil {
return "[]", e
}
arr, e := res.AsStrSlice()
if e != nil {
return "[]", e
}
return fmt.Sprintf("[%s]", strings.Join(arr, ",")), nil
}

func (c *ResultCache) Clean(id uint32) {
c.l.Lock()
defer c.l.Unlock()
c.Do(context.Background(), c.B().Del().Key(c.createKey(id)).Build())
}
1 change: 1 addition & 0 deletions blizzard/cache/submissions.go
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package cache
4 changes: 4 additions & 0 deletions blizzard/cache/users.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package cache

func GetUsers() {
}
30 changes: 7 additions & 23 deletions blizzard/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,30 +3,14 @@ package config
import (
"blizzard/blizzard/logger"
"blizzard/blizzard/models"
"github.com/spf13/viper"
"gopkg.in/yaml.v3"
"os"
)

var Config *models.BlizzardConfig
var Config models.BlizzardConfig

func readConfig() *models.BlizzardConfig {
// TODO: Command line arguments, env config and config file
var conf models.BlizzardConfig
v := viper.New()
v.SetConfigName("blizzard")
v.SetConfigType("yaml")
v.AddConfigPath(".")
if e := v.ReadInConfig(); e != nil {
logger.Logger.Err(e).Msg("config_reader")
}
v.SetEnvPrefix("BLIZZARD")
v.AutomaticEnv()
err := v.Unmarshal(&conf)
if err != nil {
logger.Logger.Err(err).Msg("config_unmarshaler")
}
return &conf
}

func Load() {
Config = readConfig()
func init() {
b, e := os.ReadFile("blizzard.yml")
logger.Panic(e, "could not read config file")
logger.Panic(yaml.Unmarshal(b, &Config), "failed to parse config file")
}
33 changes: 33 additions & 0 deletions blizzard/core/runtimes.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package core

type Runtime struct {
Name string
Extension string
}

var LanguageMatrix = map[string]*Runtime{
"gnuc++11": {
Name: "GNU C++ 11",
Extension: "cpp",
},
"gnuc++14": {
Name: "GNU C++ 14",
Extension: "cpp",
},
"gnuc++17": {
Name: "GNU C++ 17",
Extension: "cpp",
},
"gnuc++20": {
Name: "GNU C++ 20",
Extension: "cpp",
},
"python3": {
Name: "Python 3",
Extension: "py",
},
"go": {
Name: "Go",
Extension: "go",
},
}
13 changes: 13 additions & 0 deletions blizzard/cron/cron.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package cron

import (
"blizzard/blizzard/cron/jobs"
"github.com/go-co-op/gocron"
"time"
)

func init() {
s := gocron.NewScheduler(time.UTC)
s.Every("10s").Do(jobs.UpdateJudgeStatus)
s.StartAsync()
}
Loading

0 comments on commit d20697b

Please sign in to comment.