Improve Redis efficiency and speed with pipelining
This commit is contained in:
75
src/redis.go
75
src/redis.go
@@ -27,78 +27,31 @@ func (r *Redis) Connect() error {
|
|||||||
return r.Client.Ping(ctx).Err()
|
return r.Client.Ping(ctx).Err()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Redis) Exists(key string) (bool, error) {
|
func (r *Redis) Get(key string) ([]byte, time.Duration, error) {
|
||||||
if r.Client == nil {
|
if r.Client == nil {
|
||||||
return false, nil
|
return nil, 0, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
||||||
|
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
res := r.Client.Exists(ctx, key)
|
p := r.Client.Pipeline()
|
||||||
|
|
||||||
if err := res.Err(); err != nil {
|
value := p.Get(ctx, key)
|
||||||
return false, err
|
ttl := p.TTL(ctx, key)
|
||||||
|
|
||||||
|
if _, err := p.Exec(ctx); err != nil {
|
||||||
|
if err == redis.Nil {
|
||||||
|
return nil, 0, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
val, err := res.Result()
|
data, err := value.Bytes()
|
||||||
|
|
||||||
return val == 1, err
|
return data, ttl.Val(), err
|
||||||
}
|
|
||||||
|
|
||||||
func (r *Redis) TTL(key string) (time.Duration, error) {
|
|
||||||
if r.Client == nil {
|
|
||||||
return 0, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
|
||||||
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
res := r.Client.TTL(ctx, key)
|
|
||||||
|
|
||||||
if err := res.Err(); err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.Result()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *Redis) GetString(key string) (string, error) {
|
|
||||||
if r.Client == nil {
|
|
||||||
return "", nil
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
|
||||||
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
res := r.Client.Get(ctx, key)
|
|
||||||
|
|
||||||
if err := res.Err(); err != nil {
|
|
||||||
return "", nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.Result()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *Redis) GetBytes(key string) ([]byte, error) {
|
|
||||||
if r.Client == nil {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
|
||||||
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
res := r.Client.Get(ctx, key)
|
|
||||||
|
|
||||||
if err := res.Err(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.Bytes()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Redis) Set(key string, value interface{}, ttl time.Duration) error {
|
func (r *Redis) Set(key string, value interface{}, ttl time.Duration) error {
|
||||||
|
|||||||
@@ -38,9 +38,9 @@ func JavaStatusHandler(ctx *fiber.Ctx) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.Set("X-Cache-Hit", strconv.FormatBool(expiresAt != nil))
|
ctx.Set("X-Cache-Hit", strconv.FormatBool(expiresAt != 0))
|
||||||
|
|
||||||
if expiresAt != nil {
|
if expiresAt != 0 {
|
||||||
ctx.Set("X-Cache-Time-Remaining", strconv.Itoa(int(expiresAt.Seconds())))
|
ctx.Set("X-Cache-Time-Remaining", strconv.Itoa(int(expiresAt.Seconds())))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,9 +64,9 @@ func BedrockStatusHandler(ctx *fiber.Ctx) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.Set("X-Cache-Hit", strconv.FormatBool(expiresAt != nil))
|
ctx.Set("X-Cache-Hit", strconv.FormatBool(expiresAt != 0))
|
||||||
|
|
||||||
if expiresAt != nil {
|
if expiresAt != 0 {
|
||||||
ctx.Set("X-Cache-Time-Remaining", strconv.Itoa(int(expiresAt.Seconds())))
|
ctx.Set("X-Cache-Time-Remaining", strconv.Itoa(int(expiresAt.Seconds())))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,9 +86,9 @@ func IconHandler(ctx *fiber.Ctx) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.Set("X-Cache-Hit", strconv.FormatBool(expiresAt != nil))
|
ctx.Set("X-Cache-Hit", strconv.FormatBool(expiresAt != 0))
|
||||||
|
|
||||||
if expiresAt != nil {
|
if expiresAt != 0 {
|
||||||
ctx.Set("X-Cache-Time-Remaining", strconv.Itoa(int(expiresAt.Seconds())))
|
ctx.Set("X-Cache-Time-Remaining", strconv.Itoa(int(expiresAt.Seconds())))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -87,117 +87,89 @@ type Mod struct {
|
|||||||
Version string `json:"version"`
|
Version string `json:"version"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetJavaStatus(host string, port uint16) (*JavaStatusResponse, *time.Duration, error) {
|
func GetJavaStatus(host string, port uint16) (*JavaStatusResponse, time.Duration, error) {
|
||||||
cacheKey := fmt.Sprintf("java:%s-%d", host, port)
|
cacheKey := fmt.Sprintf("java:%s-%d", host, port)
|
||||||
|
|
||||||
exists, err := r.Exists(cacheKey)
|
cache, ttl, err := r.Get(cacheKey)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if exists {
|
if cache != nil {
|
||||||
data, err := r.GetBytes(cacheKey)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var response JavaStatusResponse
|
var response JavaStatusResponse
|
||||||
|
|
||||||
if err = json.Unmarshal(data, &response); err != nil {
|
err = json.Unmarshal(cache, &response)
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
ttl, err := r.TTL(cacheKey)
|
return &response, ttl, err
|
||||||
|
|
||||||
return &response, &ttl, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
response, err := FetchJavaStatus(host, port)
|
response, err := FetchJavaStatus(host, port)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
data, err := json.Marshal(response)
|
data, err := json.Marshal(response)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := r.Set(cacheKey, data, config.Cache.JavaStatusDuration); err != nil {
|
if err := r.Set(cacheKey, data, config.Cache.JavaStatusDuration); err != nil {
|
||||||
return nil, nil, err
|
return nil, 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return response, nil, nil
|
return response, 0, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetBedrockStatus(host string, port uint16) (*BedrockStatusResponse, *time.Duration, error) {
|
func GetBedrockStatus(host string, port uint16) (*BedrockStatusResponse, time.Duration, error) {
|
||||||
cacheKey := fmt.Sprintf("bedrock:%s-%d", host, port)
|
cacheKey := fmt.Sprintf("bedrock:%s-%d", host, port)
|
||||||
|
|
||||||
exists, err := r.Exists(cacheKey)
|
cache, ttl, err := r.Get(cacheKey)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if exists {
|
if cache != nil {
|
||||||
data, err := r.GetBytes(cacheKey)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var response BedrockStatusResponse
|
var response BedrockStatusResponse
|
||||||
|
|
||||||
if err = json.Unmarshal(data, &response); err != nil {
|
err = json.Unmarshal(cache, &response)
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
ttl, err := r.TTL(cacheKey)
|
return &response, ttl, err
|
||||||
|
|
||||||
return &response, &ttl, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
response, err := FetchBedrockStatus(host, port)
|
response, err := FetchBedrockStatus(host, port)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
data, err := json.Marshal(response)
|
data, err := json.Marshal(response)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := r.Set(cacheKey, data, config.Cache.BedrockStatusDuration); err != nil {
|
if err := r.Set(cacheKey, data, config.Cache.BedrockStatusDuration); err != nil {
|
||||||
return nil, nil, err
|
return nil, 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return response, nil, nil
|
return response, 0, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetServerIcon(host string, port uint16) ([]byte, *time.Duration, error) {
|
func GetServerIcon(host string, port uint16) ([]byte, time.Duration, error) {
|
||||||
cacheKey := fmt.Sprintf("icon:%s-%d", host, port)
|
cacheKey := fmt.Sprintf("icon:%s-%d", host, port)
|
||||||
|
|
||||||
exists, err := r.Exists(cacheKey)
|
cache, ttl, err := r.Get(cacheKey)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if exists {
|
if cache != nil {
|
||||||
data, err := r.GetBytes(cacheKey)
|
return cache, ttl, err
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
ttl, err := r.TTL(cacheKey)
|
|
||||||
|
|
||||||
return data, &ttl, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
icon := defaultIcon
|
icon := defaultIcon
|
||||||
@@ -208,17 +180,17 @@ func GetServerIcon(host string, port uint16) ([]byte, *time.Duration, error) {
|
|||||||
data, err := base64.StdEncoding.DecodeString(strings.TrimPrefix(*status.Favicon, "data:image/png;base64,"))
|
data, err := base64.StdEncoding.DecodeString(strings.TrimPrefix(*status.Favicon, "data:image/png;base64,"))
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
icon = data
|
icon = data
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := r.Set(cacheKey, icon, config.Cache.IconDuration); err != nil {
|
if err := r.Set(cacheKey, icon, config.Cache.IconDuration); err != nil {
|
||||||
return nil, nil, err
|
return nil, 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return icon, nil, nil
|
return icon, 0, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func FetchJavaStatus(host string, port uint16) (*JavaStatusResponse, error) {
|
func FetchJavaStatus(host string, port uint16) (*JavaStatusResponse, error) {
|
||||||
|
|||||||
Reference in New Issue
Block a user