modelRT/diagram/redis_client.go

79 lines
2.0 KiB
Go

// Package diagram provide diagram data structure and operation
package diagram
import (
"context"
"fmt"
"strconv"
"github.com/redis/go-redis/v9"
)
// RedisClient define struct to accessing redis data that does not require the use of distributed locks
type RedisClient struct {
Client *redis.Client
}
// QueryLatestMeasurementValue returns the score whose member contains the
// greatest numeric timestamp. Measurement ZSets currently store timestamp in
// member and measurement value in score.
func (rc *RedisClient) QueryLatestMeasurementValue(ctx context.Context, key string) (float64, error) {
if rc.Client == nil {
return 0, fmt.Errorf("redis client is not initialized")
}
members, err := rc.Client.ZRangeWithScores(ctx, key, 0, -1).Result()
if err != nil {
return 0, err
}
return latestMeasurementValue(members, key)
}
func latestMeasurementValue(members []redis.Z, key string) (float64, error) {
if len(members) == 0 {
return 0, fmt.Errorf("real-time measurement value not found for key %q", key)
}
var latestTimestamp int64
var latestValue float64
found := false
for _, member := range members {
timestamp, err := strconv.ParseInt(fmt.Sprint(member.Member), 10, 64)
if err != nil {
continue
}
if !found || timestamp > latestTimestamp {
latestTimestamp = timestamp
latestValue = member.Score
found = true
}
}
if !found {
return 0, fmt.Errorf("real-time measurement timestamps are invalid for key %q", key)
}
return latestValue, nil
}
// NewRedisClient define func of new redis client instance
func NewRedisClient() *RedisClient {
return &RedisClient{
Client: GetRedisClientInstance(),
}
}
// QueryByZRange define func to query real time data from redis zset
func (rc *RedisClient) QueryByZRange(ctx context.Context, key string, size int64) ([]redis.Z, error) {
client := rc.Client
args := redis.ZRangeArgs{
Key: key,
Start: 0,
Stop: size,
ByScore: false,
ByLex: false,
Rev: false,
Offset: 0,
Count: 0,
}
return client.ZRangeArgsWithScores(ctx, args).Result()
}