m2pool_core/internal/cache/cache.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
}
*/