546 lines
15 KiB
Go
546 lines
15 KiB
Go
|
// cache.go
|
||
|
package cache
|
||
|
|
||
|
import (
|
||
|
"context"
|
||
|
"encoding/json"
|
||
|
"log"
|
||
|
"strconv"
|
||
|
"time"
|
||
|
|
||
|
"github.com/redis/go-redis/v9"
|
||
|
)
|
||
|
|
||
|
// reference, do not delete that
|
||
|
/*type CacheServer struct {
|
||
|
Submits int64 `json:"submits"`
|
||
|
Blocks int64 `json:"blocks"`
|
||
|
|
||
|
Accepts float64 `json:"accepts"`
|
||
|
Rejects int64 `json:"rejects"`
|
||
|
Shares int64 `json:"shares"`
|
||
|
|
||
|
Rewards float64 `json:"reward"`
|
||
|
Fees float64 `json:"fee"`
|
||
|
|
||
|
RefDiff float64 `json:"refdiff"`
|
||
|
|
||
|
//LastSubmit int64 `json:"lastsubmit"`
|
||
|
}
|
||
|
|
||
|
type CacheUser struct {
|
||
|
Submits int64 `json:"submits"`
|
||
|
Blocks int64 `json:"blocks"`
|
||
|
|
||
|
Accepts float64 `json:"accepts"`
|
||
|
Rejects int64 `json:"rejects"`
|
||
|
Shares int64 `json:"shares"`
|
||
|
|
||
|
Rewards float64 `json:"reward"`
|
||
|
Fees float64 `json:"fee"`
|
||
|
|
||
|
User string `json:"user"`
|
||
|
}
|
||
|
|
||
|
type CacheMhs struct {
|
||
|
User string `json:"user"`
|
||
|
Miner string `json:"miner"`
|
||
|
Index string `json:"index"`
|
||
|
|
||
|
Accepts []CacheMhsItem `json:"accepts"`
|
||
|
Rejects []CacheMhsItem `json:"rejects"`
|
||
|
|
||
|
StartDayTime string `json:"startday"`
|
||
|
}
|
||
|
|
||
|
type CacheMiner struct {
|
||
|
Submits int64 `json:"submits"`
|
||
|
Blocks int64 `json:"blocks"`
|
||
|
|
||
|
Accepts float64 `json:"accepts"`
|
||
|
Rejects int64 `json:"rejects"`
|
||
|
Shares int64 `json:"shares"`
|
||
|
|
||
|
LastDiff float64 `json:"diff"`
|
||
|
|
||
|
Rewards float64 `json:"reward"`
|
||
|
Fees float64 `json:"fee"`
|
||
|
|
||
|
Retry int `json:"retry"`
|
||
|
|
||
|
LastSubmit int64 `json:"lastsubmit"`
|
||
|
|
||
|
User string `json:"user"`
|
||
|
Miner string `json:"miner"`
|
||
|
Index string `json:"index"`
|
||
|
|
||
|
ErrStaleds int64 `json:"staleds"`
|
||
|
ErrLowDiffs int64 `json:"lowdiffs"`
|
||
|
ErrDuplicates int64 `json:"duplicates"`
|
||
|
ErrFormats int64 `json:"formats"`
|
||
|
ErrOthers int64 `json:"others"`
|
||
|
}*/
|
||
|
|
||
|
// need used
|
||
|
type CacheMhsItem struct {
|
||
|
Tt string `json:"Tt"`
|
||
|
Diff float64 `json:"diff"`
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
type CacheMinerItem struct {
|
||
|
User string `json:"user"`
|
||
|
Miner string `json:"miner"`
|
||
|
Index string `json:"index"`
|
||
|
}*/
|
||
|
|
||
|
func LoadIntCache(client *redis.Client, key_int string) int64 {
|
||
|
val, err := client.Get(context.Background(), key_int).Result()
|
||
|
if err != nil {
|
||
|
log.Printf("[LoadIntCache]Error retrieving data from Redis: %s, %v\n", key_int, err)
|
||
|
return 0
|
||
|
}
|
||
|
val_int, err := strconv.ParseInt(val, 10, 64)
|
||
|
if err != nil {
|
||
|
log.Printf("[LoadIntCache]Error parsing integer from string: %v\n", err)
|
||
|
return 0
|
||
|
}
|
||
|
return val_int
|
||
|
}
|
||
|
|
||
|
func StoreIntCache(client *redis.Client, key string, intNumber int64) bool {
|
||
|
numberStr := strconv.FormatInt(intNumber, 10)
|
||
|
expiration := 7 * 24 * time.Hour
|
||
|
err := client.Set(context.Background(), key, numberStr, expiration).Err()
|
||
|
if err != nil {
|
||
|
log.Printf("[StoreIntCache]Error storing data in Redis: %s, %v\n", key, err)
|
||
|
return false
|
||
|
}
|
||
|
return true
|
||
|
}
|
||
|
|
||
|
func LoadFloatCache(client *redis.Client, key_float string) float64 {
|
||
|
val, err := client.Get(context.Background(), key_float).Result()
|
||
|
if err != nil {
|
||
|
log.Printf("[LoadFloatCache]Error retrieving data from Redis: %s, %v\n", key_float, err)
|
||
|
return 0
|
||
|
}
|
||
|
val_f, err := strconv.ParseFloat(val, 64)
|
||
|
if err != nil {
|
||
|
log.Printf("[LoadFloatCache]Error parsing float from string: %v\n", err)
|
||
|
return 0
|
||
|
}
|
||
|
return val_f
|
||
|
}
|
||
|
|
||
|
func StoreFloatCache(client *redis.Client, key string, floatNumber float64) bool {
|
||
|
numberStr := strconv.FormatFloat(floatNumber, 'f', -1, 64)
|
||
|
expiration := 7 * 24 * time.Hour
|
||
|
err := client.Set(context.Background(), key, numberStr, expiration).Err()
|
||
|
if err != nil {
|
||
|
log.Printf("[StoreFloatCache]Error storing data in Redis: %s, %v\n", key, err)
|
||
|
return false
|
||
|
}
|
||
|
return true
|
||
|
}
|
||
|
|
||
|
func LoadStringCache(client *redis.Client, keyStr string) string {
|
||
|
val, err := client.Get(context.Background(), keyStr).Result()
|
||
|
if err != nil {
|
||
|
log.Printf("[LoadStringCache]Error retrieving data from Redis: %s, %v\n", keyStr, err)
|
||
|
return ""
|
||
|
}
|
||
|
return val
|
||
|
}
|
||
|
|
||
|
func StoreStringCache(client *redis.Client, key string, strValue string) bool {
|
||
|
expiration := 7 * 24 * time.Hour
|
||
|
err := client.Set(context.Background(), key, strValue, expiration).Err()
|
||
|
if err != nil {
|
||
|
log.Printf("[StoreStringCache]Error storing data in Redis: %s, %v\n", key, err)
|
||
|
return false
|
||
|
}
|
||
|
return true
|
||
|
}
|
||
|
|
||
|
func LoadTimeCache(client *redis.Client, keyTime string) (time.Time, bool) {
|
||
|
val, err := client.Get(context.Background(), keyTime).Result()
|
||
|
if err != nil {
|
||
|
log.Printf("[LoadTimeCache]Error retrieving data from Redis: %s, %v\n", keyTime, err)
|
||
|
return time.Time{}, false
|
||
|
}
|
||
|
|
||
|
t, err := time.Parse(time.RFC3339, val)
|
||
|
if err != nil {
|
||
|
log.Printf("[LoadTimeCache]Error parsing time from string: %v\n", err)
|
||
|
return time.Time{}, false
|
||
|
}
|
||
|
|
||
|
return t, true
|
||
|
}
|
||
|
|
||
|
func StoreTimeCache(client *redis.Client, key string, timeValue time.Time) bool {
|
||
|
numberStr := timeValue.Format(time.RFC3339)
|
||
|
expiration := 7 * 24 * time.Hour
|
||
|
err := client.Set(context.Background(), key, numberStr, expiration).Err()
|
||
|
if err != nil {
|
||
|
log.Printf("[StoreTimeCache]Error storing data in Redis: %s, %v\n", key, err)
|
||
|
return false
|
||
|
}
|
||
|
return true
|
||
|
}
|
||
|
|
||
|
func LoadPoolCache(client *redis.Client, coin string, pool_key string) interface{} {
|
||
|
k := "pool_" + coin + "_" + pool_key
|
||
|
switch pool_key {
|
||
|
case "submits", "blocks", "rejects":
|
||
|
return LoadIntCache(client, k)
|
||
|
case "accepts", "rewards", "fee", "refdiff":
|
||
|
return LoadFloatCache(client, k)
|
||
|
default:
|
||
|
log.Printf("[LoadPoolCache]Unknown pool_key: %s\n", pool_key)
|
||
|
return nil
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func StorePoolCache(client *redis.Client, coin string, pool_key string, val interface{}) bool {
|
||
|
k := "pool_" + coin + "_" + pool_key
|
||
|
|
||
|
switch pool_key {
|
||
|
case "submits", "blocks", "rejects":
|
||
|
if pool_key == "rejects" {
|
||
|
if intVal, ok := val.(float64); ok {
|
||
|
return StoreIntCache(client, k, int64(intVal))
|
||
|
}
|
||
|
} else {
|
||
|
if intVal, ok := val.(int64); ok {
|
||
|
return StoreIntCache(client, k, intVal)
|
||
|
}
|
||
|
}
|
||
|
log.Printf("[StorePoolCache]Invalid type for key %s: expected int64, got %T\n", pool_key, val)
|
||
|
return false
|
||
|
case "accepts", "rewards", "fee", "refdiff":
|
||
|
if floatVal, ok := val.(float64); ok {
|
||
|
return StoreFloatCache(client, k, floatVal)
|
||
|
}
|
||
|
log.Printf("[StorePoolCache]Invalid type for key %s: expected float64, got %T\n", pool_key, val)
|
||
|
return false
|
||
|
default:
|
||
|
log.Printf("[StorePoolCache]Unknown pool_key: %s\n", pool_key)
|
||
|
return false
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
func LoadUserCache(client *redis.Client, coin string, user string, pool_key string) interface{} {
|
||
|
k := "pool_" + coin + "_" + user + "_" + pool_key
|
||
|
switch pool_key {
|
||
|
case "submits", "blocks", "rejects":
|
||
|
return LoadIntCache(client, k)
|
||
|
case "accepts", "rewards", "fee":
|
||
|
return LoadFloatCache(client, k)
|
||
|
default:
|
||
|
log.Printf("Unknown pool_key: %s\n", pool_key)
|
||
|
return nil
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func StoreUserCache(client *redis.Client, coin string, user string, pool_key string, val interface{}) bool {
|
||
|
k := "pool_" + coin + "_" + user + "_" + pool_key
|
||
|
|
||
|
switch pool_key {
|
||
|
case "submits", "blocks", "rejects":
|
||
|
if intVal, ok := val.(int64); ok {
|
||
|
return StoreIntCache(client, k, intVal)
|
||
|
}
|
||
|
log.Printf("Invalid type for key %s: expected int64, got %T\n", pool_key, val)
|
||
|
return false
|
||
|
case "accepts", "rewards", "fee":
|
||
|
if floatVal, ok := val.(float64); ok {
|
||
|
return StoreFloatCache(client, k, floatVal)
|
||
|
}
|
||
|
log.Printf("Invalid type for key %s: expected float64, got %T\n", pool_key, val)
|
||
|
return false
|
||
|
default:
|
||
|
log.Printf("Unknown pool_key: %s\n", pool_key)
|
||
|
return false
|
||
|
}
|
||
|
}*/
|
||
|
|
||
|
func LoadMinerCache(client *redis.Client, coin string, user string, miner string, index string, pool_key string) interface{} {
|
||
|
k := "pool_" + coin + "_" + user + "_" + miner + "_" + index + "_" + pool_key
|
||
|
switch pool_key {
|
||
|
case "submits", "blocks", "rejects", "retry", "staleds", "lowdiffs", "duplicates", "formats", "others":
|
||
|
return LoadIntCache(client, k)
|
||
|
case "accepts", "rewards", "fee", "diff":
|
||
|
return LoadFloatCache(client, k)
|
||
|
case "lastsubmit", "startsubmit":
|
||
|
tT, ok := LoadTimeCache(client, k)
|
||
|
if ok {
|
||
|
return tT
|
||
|
}
|
||
|
return nil
|
||
|
default:
|
||
|
log.Printf("[LoadMinerCache]Unknown pool_key: %s\n", pool_key)
|
||
|
return nil
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func StoreMinerCache(client *redis.Client, coin string, user string, miner string, index string, pool_key string, val interface{}) bool {
|
||
|
k := "pool_" + coin + "_" + user + "_" + miner + "_" + index + "_" + pool_key
|
||
|
|
||
|
switch pool_key {
|
||
|
case "submits", "blocks", "rejects", "retry", "staleds", "lowdiffs", "duplicates", "formats", "others":
|
||
|
if intVal, ok := val.(int64); ok {
|
||
|
return StoreIntCache(client, k, intVal)
|
||
|
}
|
||
|
log.Printf("[StoreMinerCache]Invalid type for %s: expected int64, got %T\n", pool_key, val)
|
||
|
return false
|
||
|
|
||
|
case "accepts", "rewards", "fee", "diff":
|
||
|
if floatVal, ok := val.(float64); ok {
|
||
|
return StoreFloatCache(client, k, floatVal)
|
||
|
}
|
||
|
log.Printf("[StoreMinerCache]Invalid type for %s: expected float64, got %T\n", pool_key, val)
|
||
|
return false
|
||
|
|
||
|
case "lastsubmit", "startsubmit":
|
||
|
if timeVal, ok := val.(time.Time); ok {
|
||
|
return StoreTimeCache(client, k, timeVal)
|
||
|
}
|
||
|
log.Printf("[StoreMinerCache]Invalid type for %s: expected time.Time, got %T\n", pool_key, val)
|
||
|
return false
|
||
|
|
||
|
default:
|
||
|
log.Printf("[StoreMinerCache]Unknown pool_key: %s\n", pool_key)
|
||
|
return false
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func StoreCacheMhsItem(client *redis.Client, key string, item CacheMhsItem) bool {
|
||
|
data, err := json.Marshal(item)
|
||
|
if err != nil {
|
||
|
log.Printf("[StoreCacheMhsItem]Error marshalling CacheMhsItem to JSON: %v\n", err)
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
err = client.RPush(context.Background(), key, data).Err()
|
||
|
if err != nil {
|
||
|
log.Printf("[StoreCacheMhsItem]Error pushing data to Redis list: %v\n", err)
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
expiration := 7 * 24 * time.Hour
|
||
|
err = client.Expire(context.Background(), key, expiration).Err()
|
||
|
if err != nil {
|
||
|
log.Printf("[StoreCacheMhsItem] Error setting expiration for Redis key: %v\n", err)
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
return true
|
||
|
}
|
||
|
|
||
|
func PopCacheMhsItem(client *redis.Client, key string) (*CacheMhsItem, bool) {
|
||
|
data, err := client.LPop(context.Background(), key).Result()
|
||
|
if err != nil {
|
||
|
log.Printf("[PopCacheMhsItem]Error retrieving data from Redis list: %v\n", err)
|
||
|
return nil, false
|
||
|
}
|
||
|
|
||
|
var item CacheMhsItem
|
||
|
if err = json.Unmarshal([]byte(data), &item); err != nil {
|
||
|
log.Printf("[PopCacheMhsItem]Error unmarshalling JSON to CacheMhsItem: %v\n", err)
|
||
|
return nil, false
|
||
|
}
|
||
|
|
||
|
return &item, true
|
||
|
}
|
||
|
|
||
|
func RemoveMhsCache(client *redis.Client, coin string, user string, miner string, index string, key string) bool {
|
||
|
k := "mhs_" + coin + "_" + user + "_" + miner + "_" + index + "_" + key
|
||
|
switch key {
|
||
|
case "accepts", "rejects":
|
||
|
PopCacheMhsItem(client, k)
|
||
|
return true
|
||
|
}
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
func LoadMhsCache(client *redis.Client, coin string, user string, miner string, index string, key string) interface{} {
|
||
|
k := "mhs_" + coin + "_" + user + "_" + miner + "_" + index + "_" + key
|
||
|
switch key {
|
||
|
case "starttime":
|
||
|
tT, ok := LoadTimeCache(client, k)
|
||
|
if ok {
|
||
|
return tT
|
||
|
}
|
||
|
return nil
|
||
|
case "accepts", "rejects":
|
||
|
/*listLength, err := client.LLen(context.Background(), k).Result()
|
||
|
if err != nil {
|
||
|
log.Printf("Error getting list length: %v\n", err)
|
||
|
return nil
|
||
|
}*/
|
||
|
values, err := client.LRange(context.Background(), k, 0, -1).Result()
|
||
|
if err != nil {
|
||
|
log.Printf("[LoadMhsCache]Error getting list values: %v\n", err)
|
||
|
}
|
||
|
var items []CacheMhsItem
|
||
|
for _, value := range values {
|
||
|
var item CacheMhsItem
|
||
|
if err = json.Unmarshal([]byte(value), &item); err != nil {
|
||
|
continue
|
||
|
}
|
||
|
items = append(items, item)
|
||
|
}
|
||
|
return &items
|
||
|
default:
|
||
|
return nil
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func StoreMhsCache(client *redis.Client, coin string, user string, miner string, index string, key string, val interface{}) bool {
|
||
|
k := "mhs_" + coin + "_" + user + "_" + miner + "_" + index + "_" + key
|
||
|
switch key {
|
||
|
case "starttime":
|
||
|
if t, ok := val.(time.Time); ok {
|
||
|
return StoreTimeCache(client, k, t)
|
||
|
}
|
||
|
log.Printf("[StoreMhsCache]Invalid type for starttime: expected time.Time, got %T\n", val)
|
||
|
return false
|
||
|
case "accepts", "rejects":
|
||
|
if item, ok := val.(CacheMhsItem); ok {
|
||
|
return StoreCacheMhsItem(client, k, item)
|
||
|
}
|
||
|
log.Printf("[StoreMhsCache]Invalid type for CacheMhsItem: expected CacheMhsItem, got %T\n", val)
|
||
|
return false
|
||
|
default:
|
||
|
log.Printf("[StoreMhsCache]Unknown key: %s\n", key)
|
||
|
return false
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
func StoreStringToSet(client *redis.Client, setKey string, value string) bool {
|
||
|
err := client.SAdd(context.Background(), setKey, value).Err()
|
||
|
if err != nil {
|
||
|
log.Printf("Error adding value to Redis set: %v\n", err)
|
||
|
return false
|
||
|
}
|
||
|
return true
|
||
|
}
|
||
|
|
||
|
func LoadStringsFromSet(client *redis.Client, setKey string) ([]string, bool) {
|
||
|
members, err := client.SMembers(context.Background(), setKey).Result()
|
||
|
if err != nil {
|
||
|
log.Printf("Error retrieving data from Redis set: %v\n", err)
|
||
|
return nil, false
|
||
|
}
|
||
|
return members, true
|
||
|
}
|
||
|
|
||
|
func RemoveStringFromSet(client *redis.Client, setKey string, value string) bool {
|
||
|
err := client.SRem(context.Background(), setKey, value).Err()
|
||
|
if err != nil {
|
||
|
log.Printf("Error removing value from Redis set: %v\n", err)
|
||
|
return false
|
||
|
}
|
||
|
return true
|
||
|
}
|
||
|
|
||
|
func LoadUsersCache(client *redis.Client, coin string) []string {
|
||
|
k := "pool_" + coin + "_users"
|
||
|
users, ok := LoadStringsFromSet(client, k)
|
||
|
if !ok {
|
||
|
log.Printf("Error loading users slice from Redis for coin: %s\n", coin)
|
||
|
return []string{}
|
||
|
}
|
||
|
return users
|
||
|
}
|
||
|
|
||
|
func StoreUsersCache(client *redis.Client, coin string, user string) bool {
|
||
|
k := "pool_" + coin + "_users"
|
||
|
ok := StoreStringToSet(client, k, user)
|
||
|
if !ok {
|
||
|
log.Printf("Error storing users slice to Redis for coin: %s\n", coin)
|
||
|
return false
|
||
|
}
|
||
|
return true
|
||
|
}
|
||
|
*/
|
||
|
/*
|
||
|
func StoreCacheMinerItem(client *redis.Client, setKey string, item CacheMinerItem) bool {
|
||
|
data, err := json.Marshal(item)
|
||
|
if err != nil {
|
||
|
log.Printf("Error marshalling CacheMinerItem to JSON: %v\n", err)
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
err = client.SAdd(context.Background(), setKey, data).Err()
|
||
|
if err != nil {
|
||
|
log.Printf("Error adding data to Redis set: %v\n", err)
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
return true
|
||
|
}
|
||
|
|
||
|
func LoadCacheMinerItems(client *redis.Client, setKey string) ([]CacheMinerItem, bool) {
|
||
|
data, err := client.SMembers(context.Background(), setKey).Result()
|
||
|
if err != nil {
|
||
|
log.Printf("Error retrieving data from Redis set: %v\n", err)
|
||
|
return nil, false
|
||
|
}
|
||
|
|
||
|
var items []CacheMinerItem
|
||
|
for _, itemData := range data {
|
||
|
var item CacheMinerItem
|
||
|
err := json.Unmarshal([]byte(itemData), &item)
|
||
|
if err != nil {
|
||
|
log.Printf("Error unmarshalling JSON to CacheMinerItem: %v\n", err)
|
||
|
return nil, false
|
||
|
}
|
||
|
items = append(items, item)
|
||
|
}
|
||
|
|
||
|
return items, true
|
||
|
}
|
||
|
|
||
|
func RemoveCacheMinerItem(client *redis.Client, setKey string, item CacheMinerItem) bool {
|
||
|
|
||
|
data, err := json.Marshal(item)
|
||
|
if err != nil {
|
||
|
log.Printf("Error marshalling CacheMinerItem to JSON: %v\n", err)
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
err = client.SRem(context.Background(), setKey, data).Err()
|
||
|
if err != nil {
|
||
|
log.Printf("Error removing data from Redis set: %v\n", err)
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
return true
|
||
|
}
|
||
|
|
||
|
func LoadMinersCache(client *redis.Client, coin string) []CacheMinerItem {
|
||
|
k := "pool_" + coin + "_miners"
|
||
|
miners, ok := LoadCacheMinerItems(client, k)
|
||
|
if !ok {
|
||
|
log.Printf("Error loading miners set from Redis for coin: %s\n", coin)
|
||
|
return []CacheMinerItem{}
|
||
|
}
|
||
|
return miners
|
||
|
}
|
||
|
|
||
|
func StoreMinersCache(client *redis.Client, coin string, miner CacheMinerItem) bool {
|
||
|
k := "pool_" + coin + "_miners"
|
||
|
ok := StoreCacheMinerItem(client, k, miner)
|
||
|
if !ok {
|
||
|
log.Printf("Error storing miners slice to Redis for coin: %s\n", coin)
|
||
|
return false
|
||
|
}
|
||
|
return true
|
||
|
}
|
||
|
*/
|