use github.com/rueian/rueidis as Redis client and abstract RedisCache interface

pull/249/head
Michael Li 2 years ago
parent 77c768fa12
commit 92a492d90d
No known key found for this signature in database

@ -47,7 +47,7 @@ jobs:
name: Test
strategy:
matrix:
go-version: [ 1.19.x, 1.20.x ]
go-version: [ 1.20.x ]
platform: [ ubuntu-latest, macos-latest ]
runs-on: ${{ matrix.platform }}
steps:
@ -66,7 +66,7 @@ jobs:
name: TestOnWindows
strategy:
matrix:
go-version: [ 1.19.x, 1.20.x ]
go-version: [ 1.20.x ]
platform: [ windows-latest ]
runs-on: ${{ matrix.platform }}
steps:

@ -65,7 +65,7 @@ PaoPao主要由以下优秀的开源项目/工具构建
### 环境要求
* Go (1.19+)
* Go (1.20+)
* Node.js (14+)
* MySQL (5.7+)
* Redis

@ -181,7 +181,6 @@ Postgres: # PostgreSQL数据库
Sqlite3: # Sqlite3数据库
Path: custom/data/sqlite3/paopao-ce.db
Redis:
Host: redis:6379
Password:
DB:
InitAddress:
- redis:6379

@ -32,11 +32,22 @@ services:
# networks:
# - paopao-network
# redis:
# image: redis:7.0-alpine
# restart: always
# ports:
# - 6379:6379
# networks:
# - paopao-network
redis:
image: redis:7.0-alpine
image: redis/redis-stack:7.0.6-RC8
restart: always
ports:
- 6379:6379
- 8001:8001
environment:
REDISEARCH_ARGS: "MAXSEARCHRESULTS 5"
networks:
- paopao-network

@ -26,6 +26,5 @@ LocalOSS: # 本地文件OSS存储配置
Sqlite3: # Sqlite3数据库
Path: custom/data/sqlite3/paopao-ce.db
Redis:
Host: 127.0.0.1:6379
Password:
DB:
InitAddress:
- 127.0.0.1:6379

@ -1,6 +1,6 @@
module github.com/rocboss/paopao-ce
go 1.19
go 1.20
require (
github.com/Masterminds/semver/v3 v3.2.0
@ -24,9 +24,9 @@ require (
github.com/meilisearch/meilisearch-go v0.21.0
github.com/minio/minio-go/v7 v7.0.49
github.com/onsi/ginkgo/v2 v2.9.2
github.com/onsi/gomega v1.27.4
github.com/onsi/gomega v1.27.5
github.com/pyroscope-io/client v0.6.0
github.com/redis/go-redis/v9 v9.0.2
github.com/rueian/rueidis v0.0.97
github.com/sirupsen/logrus v1.9.0
github.com/smartwalle/alipay/v3 v3.2.0
github.com/sourcegraph/conc v0.3.0
@ -49,10 +49,8 @@ require (
require (
github.com/andybalholm/brotli v1.0.4 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
github.com/clbanning/mxj v1.8.4 // indirect
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/fsnotify/fsnotify v1.6.0 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect
@ -66,7 +64,7 @@ require (
github.com/golang/protobuf v1.5.3 // indirect
github.com/google/go-cmp v0.5.9 // indirect
github.com/google/go-querystring v1.1.0 // indirect
github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 // indirect
github.com/google/pprof v0.0.0-20230207041349-798e818bf904 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect

@ -185,8 +185,6 @@ github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnweb
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4=
github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
github.com/bshuster-repo/logrus-logstash-hook v0.4.1/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk=
github.com/bsm/ginkgo/v2 v2.5.0 h1:aOAnND1T40wEdAtkGSkvSICWeQ8L3UASX7YVCqQx+eQ=
github.com/bsm/gomega v1.20.0 h1:JhAwLmtRzXFTx2AkALSLa8ijZafntmhSoU63Ok18Uq8=
github.com/buger/jsonparser v0.0.0-20180808090653-f4dd9f5a6b44/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s=
github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0=
github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8=
@ -204,8 +202,6 @@ github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054/go.mod h1:sGbDF6
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/checkpoint-restore/go-criu/v4 v4.1.0/go.mod h1:xUQBLp4RLc5zJtWY++yjOoMoB5lihDt7fai+75m+rGw=
github.com/checkpoint-restore/go-criu/v5 v5.0.0/go.mod h1:cfwC0EG7HMUenopBsUf9d89JlCLQIfgVcNsNN0t6T2M=
github.com/checkpoint-restore/go-criu/v5 v5.3.0/go.mod h1:E/eQpaFtUKGOOSEBZgmKAcn+zUUwWxqcaKZlF54wK8E=
@ -375,8 +371,6 @@ github.com/denisenkom/go-mssqldb v0.10.0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27
github.com/denverdino/aliyungo v0.0.0-20190125010748-a747050bb1ba/go.mod h1:dV8lFg6daOBZbT6/BDGIz6Y3WFGn8juu6G+CQ6LHtl0=
github.com/dgrijalva/jwt-go v0.0.0-20170104182250-a601269ab70c/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
github.com/dhui/dktest v0.3.10 h1:0frpeeoM9pHouHjhLeZDuDTJ0PqjDTrycaHaMmkJAo8=
github.com/dhui/dktest v0.3.10/go.mod h1:h5Enh0nG3Qbo9WjNFRrwmKUaePEBhXMOygbz3Ww7Sz0=
@ -658,8 +652,8 @@ github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLe
github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ=
github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo=
github.com/google/pprof v0.0.0-20230207041349-798e818bf904 h1:4/hN5RUoecvl+RmJRE2YxKWtnnQls6rQjjW5oV7qg2U=
github.com/google/pprof v0.0.0-20230207041349-798e818bf904/go.mod h1:uglQLonpP8qtYCYyzA+8c/9qtqgA3qsXGYqCPKARAFg=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
@ -1007,8 +1001,8 @@ github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoT
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc=
github.com/onsi/gomega v1.15.0/go.mod h1:cIuvLEne0aoVhAgh/O6ac0Op8WWw9H6eYCriF+tEHG0=
github.com/onsi/gomega v1.27.4 h1:Z2AnStgsdSayCMDiCU42qIz+HLqEPcgiOCXjAU/w+8E=
github.com/onsi/gomega v1.27.4/go.mod h1:riYq/GJKh8hhoM01HN6Vmuy93AarCXCBGpvFDK3q3fQ=
github.com/onsi/gomega v1.27.5 h1:T/X6I0RNFw/kTqgfkZPcQ5KU6vCnWNBGdtrIx2dpGeQ=
github.com/onsi/gomega v1.27.5/go.mod h1:PIQNjfQwkP3aQAH7lf7j87O/5FiNr+ZR8+ipb+qQlhg=
github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
@ -1104,8 +1098,6 @@ github.com/pyroscope-io/client v0.6.0 h1:rcUFgcnfmuyVYDYT+4d0zfqc8YedOyruHSsUb9I
github.com/pyroscope-io/client v0.6.0/go.mod h1:4h21iOU4pUOq0prKyDlvYRL+SCKsBc5wKiEtV+rJGqU=
github.com/pyroscope-io/godeltaprof v0.1.0 h1:UBqtjt0yZi4jTxqZmLAs34XG6ycS3vUTlhEUSq4NHLE=
github.com/pyroscope-io/godeltaprof v0.1.0/go.mod h1:psMITXp90+8pFenXkKIpNhrfmI9saQnPbba27VIaiQE=
github.com/redis/go-redis/v9 v9.0.2 h1:BA426Zqe/7r56kCcvxYLWe1mkaz71LKF77GwgFzSxfE=
github.com/redis/go-redis/v9 v9.0.2/go.mod h1:/xDTe9EF1LM61hek62Poq2nzQSGj0xSrEtEHbBQevps=
github.com/remyoudompheng/bigfft v0.0.0-20190728182440-6a916e37a237/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
@ -1124,6 +1116,8 @@ github.com/rs/xid v1.4.0 h1:qd7wPTDkN6KQx2VmMBLrpHkiyQwgFXRnkOLacUiaSNY=
github.com/rs/xid v1.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU=
github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc=
github.com/rueian/rueidis v0.0.97 h1:b3jo3CatMd7Jak+Sbz8sPpasdUY/BziBsSjdzT5GQvc=
github.com/rueian/rueidis v0.0.97/go.mod h1:ivvsRYRtAUcf9OnheuKc5Gpa8IebrkLT1P45Lr2jlXE=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58/go.mod h1:6lfFZQK844Gfx8o5WFuvpxWRwnSoipWe/p622j1v06w=
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=

@ -112,6 +112,7 @@ func setupSetting(suite []string, noDefault bool) error {
SimpleCacheIndexSetting.CheckTickDuration *= time.Second
SimpleCacheIndexSetting.ExpireTickDuration *= time.Second
BigCacheIndexSetting.ExpireInSecond *= time.Second
redisSetting.ConnWriteTimeout *= time.Second
Mutex = &sync.Mutex{}
return nil
@ -124,7 +125,6 @@ func Initialize(suite []string, noDefault bool) {
}
setupLogger()
setupDBEngine()
}
func GetOssDomain() string {

@ -179,7 +179,10 @@ Postgres: # PostgreSQL数据库
Sqlite3: # Sqlite3数据库
Path: custom/data/sqlite3/paopao-ce.db
Redis:
Host: redis:6379
Password:
DB:
InitAddress:
- redis:6379
Username:
Password:
SelectDB:
ConnWriteTimeout: 60 # 连接写超时时间 多少秒 默认 60秒

@ -9,7 +9,6 @@ import (
"time"
"github.com/alimy/cfg"
"github.com/redis/go-redis/v9"
"github.com/sirupsen/logrus"
"gorm.io/driver/mysql"
"gorm.io/driver/postgres"
@ -20,9 +19,8 @@ import (
)
var (
db *gorm.DB
Redis *redis.Client
once sync.Once
db *gorm.DB
once sync.Once
)
func MustGormDB() *gorm.DB {
@ -84,11 +82,3 @@ func newDBEngine() (*gorm.DB, error) {
return db, err
}
func setupDBEngine() {
Redis = redis.NewClient(&redis.Options{
Addr: redisSetting.Host,
Password: redisSetting.Password,
DB: redisSetting.DB,
})
}

@ -0,0 +1,34 @@
// Copyright 2023 ROC. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
package conf
import (
"log"
"sync"
"github.com/rueian/rueidis"
)
var (
_redisClient rueidis.Client
_once sync.Once
)
func MustRedisClient() rueidis.Client {
_once.Do(func() {
client, err := rueidis.NewClient(rueidis.ClientOption{
InitAddress: redisSetting.InitAddress,
Username: redisSetting.Username,
Password: redisSetting.Password,
SelectDB: redisSetting.SelectDB,
ConnWriteTimeout: redisSetting.ConnWriteTimeout,
})
if err != nil {
log.Fatalf("create a redis client failed: %s", err)
}
_redisClient = client
})
return _redisClient
}

@ -210,9 +210,11 @@ type LocalOSSSettingS struct {
}
type RedisSettingS struct {
Host string
Password string
DB int
InitAddress []string
Username string
Password string
SelectDB int
ConnWriteTimeout time.Duration
}
type JWTSettingS struct {

@ -5,6 +5,8 @@
package core
import (
"context"
"github.com/rocboss/paopao-ce/internal/dao/jinzhu/dbr"
)
@ -56,3 +58,21 @@ type CacheIndexService interface {
SendAction(act IdxAct, post *dbr.Post)
}
// RedisCache memory cache by Redis
type RedisCache interface {
SetPushToSearchJob(ctx context.Context) error
DelPushToSearchJob(ctx context.Context) error
SetImgCaptcha(ctx context.Context, id string, value string) error
GetImgCaptcha(ctx context.Context, id string) (string, error)
DelImgCaptcha(ctx context.Context, id string) error
GetCountSmsCaptcha(ctx context.Context, phone string) (int64, error)
IncrCountSmsCaptcha(ctx context.Context, phone string) error
GetCountLoginErr(ctx context.Context, id int64) (int64, error)
DelCountLoginErr(ctx context.Context, id int64) error
IncrCountLoginErr(ctx context.Context, id int64) error
GetCountWhisper(ctx context.Context, uid int64) (int64, error)
IncrCountWhisper(ctx context.Context, uid int64) error
SetRechargeStatus(ctx context.Context, tradeNo string) error
DelRechargeStatus(ctx context.Context, tradeNo string) error
}

@ -13,6 +13,12 @@ import (
"github.com/sirupsen/logrus"
)
func NewRedisCache() core.RedisCache {
return &redisCache{
c: conf.MustRedisClient(),
}
}
func NewBigCacheIndexService(ips core.IndexPostsService, ams core.AuthorizationManageService) (core.CacheIndexService, core.VersionInfo) {
s := conf.BigCacheIndexSetting
c := bigcache.DefaultConfig(s.ExpireInSecond)

@ -0,0 +1,108 @@
package cache
import (
"context"
"fmt"
"time"
"unsafe"
"github.com/rocboss/paopao-ce/internal/core"
"github.com/rueian/rueidis"
)
var (
_ core.RedisCache = (*redisCache)(nil)
)
const (
_pushToSearchJobKey = "JOB_PUSH_TO_SEARCH"
_countLoginErrKey = "PaoPaoUserLoginErr:"
_imgCaptchaKey = "PaoPaoCaptcha:"
_smsCaptchaKey = "PaoPaoSmsCaptcha:"
_countWhisperKey = "WhisperTimes:"
_rechargeStatusKey = "PaoPaoRecharge:"
)
type redisCache struct {
c rueidis.Client
}
func (r *redisCache) SetPushToSearchJob(ctx context.Context) error {
return r.c.Do(ctx, r.c.B().Set().
Key(_pushToSearchJobKey).Value("1").
Nx().ExSeconds(3600).
Build()).Error()
}
func (r *redisCache) DelPushToSearchJob(ctx context.Context) error {
return r.c.Do(ctx, r.c.B().Del().Key(_pushToSearchJobKey).Build()).Error()
}
func (r *redisCache) SetImgCaptcha(ctx context.Context, id string, value string) error {
return r.c.Do(ctx, r.c.B().Set().
Key(_imgCaptchaKey+id).Value(value).
ExSeconds(300).
Build()).Error()
}
func (r *redisCache) GetImgCaptcha(ctx context.Context, id string) (string, error) {
res, err := r.c.Do(ctx, r.c.B().Get().Key(_imgCaptchaKey+id).Build()).AsBytes()
return unsafe.String(&res[0], len(res)), err
}
func (r *redisCache) DelImgCaptcha(ctx context.Context, id string) error {
return r.c.Do(ctx, r.c.B().Del().Key(_imgCaptchaKey+id).Build()).Error()
}
func (r *redisCache) GetCountSmsCaptcha(ctx context.Context, phone string) (int64, error) {
return r.c.Do(ctx, r.c.B().Get().Key(_smsCaptchaKey+phone).Build()).AsInt64()
}
func (r *redisCache) IncrCountSmsCaptcha(ctx context.Context, phone string) (err error) {
if err = r.c.Do(ctx, r.c.B().Incr().Key(_smsCaptchaKey+phone).Build()).Error(); err == nil {
currentTime := time.Now()
endTime := time.Date(currentTime.Year(), currentTime.Month(), currentTime.Day(), 23, 59, 59, 0, currentTime.Location())
err = r.c.Do(ctx, r.c.B().Expire().Key(_smsCaptchaKey+phone).Seconds(int64(endTime.Sub(currentTime)/time.Second)).Build()).Error()
}
return
}
func (r *redisCache) GetCountLoginErr(ctx context.Context, id int64) (int64, error) {
return r.c.Do(ctx, r.c.B().Get().Key(fmt.Sprintf("%s:%d", _countLoginErrKey, id)).Build()).AsInt64()
}
func (r *redisCache) DelCountLoginErr(ctx context.Context, id int64) error {
return r.c.Do(ctx, r.c.B().Del().Key(fmt.Sprintf("%s:%d", _countLoginErrKey, id)).Build()).Error()
}
func (r *redisCache) IncrCountLoginErr(ctx context.Context, id int64) error {
err := r.c.Do(ctx, r.c.B().Incr().Key(fmt.Sprintf("%s:%d", _countLoginErrKey, id)).Build()).Error()
if err == nil {
err = r.c.Do(ctx, r.c.B().Expire().Key(fmt.Sprintf("%s:%d", _countLoginErrKey, id)).Seconds(3600).Build()).Error()
}
return err
}
func (r *redisCache) GetCountWhisper(ctx context.Context, uid int64) (int64, error) {
return r.c.Do(ctx, r.c.B().Get().Key(fmt.Sprintf("%s:%d", _countWhisperKey, uid)).Build()).AsInt64()
}
func (r *redisCache) IncrCountWhisper(ctx context.Context, uid int64) (err error) {
key := fmt.Sprintf("%s:%d", _countWhisperKey, uid)
if err = r.c.Do(ctx, r.c.B().Incr().Key(key).Build()).Error(); err == nil {
currentTime := time.Now()
endTime := time.Date(currentTime.Year(), currentTime.Month(), currentTime.Day(), 23, 59, 59, 0, currentTime.Location())
err = r.c.Do(ctx, r.c.B().Expire().Key(key).Seconds(int64(endTime.Sub(currentTime)/time.Second)).Build()).Error()
}
return
}
func (r *redisCache) SetRechargeStatus(ctx context.Context, tradeNo string) error {
return r.c.Do(ctx, r.c.B().Set().
Key(_rechargeStatusKey+tradeNo).Value("1").
Nx().ExSeconds(5).Build()).Error()
}
func (r *redisCache) DelRechargeStatus(ctx context.Context, tradeNo string) error {
return r.c.Do(ctx, r.c.B().Del().Key(_rechargeStatusKey+tradeNo).Build()).Error()
}

@ -9,23 +9,24 @@ import (
"fmt"
"math"
"net/http"
"time"
"github.com/alimy/mir/v3"
"github.com/gin-gonic/gin"
"github.com/redis/go-redis/v9"
"github.com/rocboss/paopao-ce/internal/core"
"github.com/rocboss/paopao-ce/internal/dao"
"github.com/rocboss/paopao-ce/internal/dao/cache"
"github.com/rocboss/paopao-ce/pkg/app"
"github.com/rocboss/paopao-ce/pkg/types"
"github.com/rocboss/paopao-ce/pkg/xerror"
"github.com/sirupsen/logrus"
)
type BaseServant types.Empty
type DaoServant struct {
Redis *redis.Client
Ds core.DataService
Ts core.TweetSearchService
Redis core.RedisCache
}
type BaseBinding types.Empty
@ -140,8 +141,8 @@ func (s *DaoServant) GetTweetBy(id int64) (*core.PostFormated, error) {
}
func (s *DaoServant) PushPostsToSearch(c context.Context) {
if ok, _ := s.Redis.SetNX(c, "JOB_PUSH_TO_SEARCH", 1, time.Hour).Result(); ok {
defer s.Redis.Del(c, "JOB_PUSH_TO_SEARCH")
if err := s.Redis.SetPushToSearchJob(c); err == nil {
defer s.Redis.DelPushToSearchJob(c)
splitNum := 1000
totalRows, _ := s.Ds.GetPostCount(&core.ConditionsT{
@ -168,6 +169,8 @@ func (s *DaoServant) PushPostsToSearch(c context.Context) {
s.Ts.AddDocuments(docs, fmt.Sprintf("%d", posts[i].ID))
}
}
} else {
logrus.Errorf("redis: set JOB_PUSH_TO_SEARCH error: %s", err)
}
}
@ -207,3 +210,11 @@ func (s *DaoServant) GetTweetList(conditions *core.ConditionsT, offset, limit in
postFormated, err := s.Ds.MergePosts(posts)
return posts, postFormated, err
}
func NewDaoServant() *DaoServant {
return &DaoServant{
Redis: cache.NewRedisCache(),
Ds: dao.DataService(),
Ts: dao.TweetSearchService(),
}
}

@ -6,7 +6,6 @@ package web
import (
"fmt"
"time"
"github.com/alimy/mir/v3"
"github.com/gin-gonic/gin"
@ -80,7 +79,7 @@ func (b *alipayPubBinding) BindAlipayNotify(c *gin.Context) (*web.AlipayNotifyRe
func (s *alipayPubSrv) AlipayNotify(req *web.AlipayNotifyReq) mir.Error {
if req.TradeStatus == alipay.TradeStatusSuccess {
if ok, _ := s.Redis.SetNX(req.Ctx, "PaoPaoRecharge:"+req.TradeNo, 1, time.Second*5).Result(); ok {
if err := s.Redis.SetRechargeStatus(req.Ctx, req.TradeNo); err == nil {
recharge, err := s.Ds.GetRechargeByID(req.ID)
if err != nil {
logrus.Errorf("GetRechargeByID id:%d err: %s", req.ID, err)
@ -89,7 +88,7 @@ func (s *alipayPubSrv) AlipayNotify(req *web.AlipayNotifyReq) mir.Error {
if recharge.TradeStatus != "TRADE_SUCCESS" {
// 标记为已付款
err := s.Ds.HandleRechargeSuccess(recharge, req.TradeNo)
defer s.Redis.Del(req.Ctx, "PaoPaoRecharge:"+req.TradeNo)
defer s.Redis.DelRechargeStatus(req.Ctx, req.TradeNo)
if err != nil {
logrus.Errorf("HandleRechargeSuccess id:%d err: %s", req.ID, err)
return _errRechargeNotifyError

@ -8,6 +8,7 @@ import (
"github.com/alimy/cfg"
"github.com/rocboss/paopao-ce/internal/core"
"github.com/rocboss/paopao-ce/internal/dao"
"github.com/rocboss/paopao-ce/internal/dao/cache"
"github.com/sirupsen/logrus"
)
@ -16,6 +17,8 @@ var (
ts core.TweetSearchService
oss core.ObjectStorageService
DisablePhoneVerify bool
_redis core.RedisCache
)
func Initialize() {
@ -23,6 +26,7 @@ func Initialize() {
ts = dao.TweetSearchService()
oss = dao.ObjectStorageService()
DisablePhoneVerify = !cfg.If("Sms")
_redis = cache.NewRedisCache()
}
// persistMediaContents 获取媒体内容并持久化

@ -5,13 +5,8 @@
package broker
import (
"fmt"
"time"
"github.com/gin-gonic/gin"
"github.com/rocboss/paopao-ce/internal/conf"
"github.com/rocboss/paopao-ce/internal/core"
"github.com/rocboss/paopao-ce/pkg/convert"
"github.com/rocboss/paopao-ce/pkg/errcode"
)
@ -28,10 +23,8 @@ type WhisperReq struct {
// CreateWhisper 创建私信
func CreateWhisper(c *gin.Context, msg *core.Message) (*core.Message, error) {
whisperKey := fmt.Sprintf("WhisperTimes:%d", msg.SenderUserID)
// 今日频次限制
if res, _ := conf.Redis.Get(c, whisperKey).Result(); convert.StrTo(res).MustInt() >= MAX_WHISPER_NUM_DAILY {
if count, err := _redis.GetCountWhisper(c, msg.SenderUserID); err != nil || count >= MAX_WHISPER_NUM_DAILY {
return nil, errcode.TooManyWhisperNum
}
@ -42,18 +35,14 @@ func CreateWhisper(c *gin.Context, msg *core.Message) (*core.Message, error) {
}
// 写入当日(自然日)计数缓存
conf.Redis.Incr(c, whisperKey).Result()
currentTime := time.Now()
endTime := time.Date(currentTime.Year(), currentTime.Month(), currentTime.Day(), 23, 59, 59, 0, currentTime.Location())
conf.Redis.Expire(c, whisperKey, endTime.Sub(currentTime))
_redis.IncrCountWhisper(c, msg.SenderUserID)
return msg, err
}
func GetUnreadCount(userID int64) (int64, error) {
return ds.GetUnreadCount(userID)
}
func ReadMessage(id, userID int64) error {
// 获取message
message, err := ds.GetMessageByID(id)

@ -9,7 +9,6 @@ import (
"fmt"
"math"
"strings"
"time"
"github.com/gin-gonic/gin"
"github.com/rocboss/paopao-ce/internal/conf"
@ -501,8 +500,8 @@ func DeleteSearchPost(post *core.Post) error {
}
func PushPostsToSearch(c *gin.Context) {
if ok, _ := conf.Redis.SetNX(c, "JOB_PUSH_TO_SEARCH", 1, time.Hour).Result(); ok {
defer conf.Redis.Del(c, "JOB_PUSH_TO_SEARCH")
if err := _redis.SetPushToSearchJob(c); err == nil {
defer _redis.DelPushToSearchJob(c)
splitNum := 1000
totalRows, _ := GetPostCount(&core.ConditionsT{
@ -535,6 +534,8 @@ func PushPostsToSearch(c *gin.Context) {
ts.AddDocuments(docs, fmt.Sprintf("%d", posts[i].ID))
}
}
} else {
logrus.Errorf("redis: set JOB_PUSH_TO_SEARCH error: %s", err)
}
}

@ -5,7 +5,6 @@
package broker
import (
"fmt"
"regexp"
"strings"
"time"
@ -13,9 +12,7 @@ import (
"github.com/gin-gonic/gin"
"github.com/gofrs/uuid"
"github.com/rocboss/paopao-ce/internal/conf"
"github.com/rocboss/paopao-ce/internal/core"
"github.com/rocboss/paopao-ce/pkg/convert"
"github.com/rocboss/paopao-ce/pkg/errcode"
"github.com/rocboss/paopao-ce/pkg/utils"
"github.com/sirupsen/logrus"
@ -102,10 +99,8 @@ func DoLogin(ctx *gin.Context, param *AuthRequest) (*core.User, error) {
}
if user.Model != nil && user.ID > 0 {
if errTimes, err := conf.Redis.Get(ctx, fmt.Sprintf("%s:%d", _LoginErrKey, user.ID)).Result(); err == nil {
if convert.StrTo(errTimes).MustInt() >= _MaxLoginErrTimes {
return nil, errcode.TooManyLoginError
}
if count, err := _redis.GetCountLoginErr(ctx, user.ID); err == nil && count >= _MaxLoginErrTimes {
return nil, errcode.TooManyLoginError
}
// 对比密码是否正确
@ -116,15 +111,12 @@ func DoLogin(ctx *gin.Context, param *AuthRequest) (*core.User, error) {
}
// 清空登录计数
conf.Redis.Del(ctx, fmt.Sprintf("%s:%d", _LoginErrKey, user.ID))
_redis.DelCountLoginErr(ctx, user.ID)
return user, nil
}
// 登录错误计数
_, err = conf.Redis.Incr(ctx, fmt.Sprintf("%s:%d", _LoginErrKey, user.ID)).Result()
if err == nil {
conf.Redis.Expire(ctx, fmt.Sprintf("%s:%d", _LoginErrKey, user.ID), time.Hour).Result()
}
_redis.IncrCountLoginErr(ctx, user.ID)
return nil, errcode.UnauthorizedAuthFailed
}
@ -428,20 +420,12 @@ func GetUserWalletBills(userID int64, offset, limit int) ([]*core.WalletStatemen
// SendPhoneCaptcha 发送短信验证码
func SendPhoneCaptcha(ctx *gin.Context, phone string) error {
err := ds.SendPhoneCaptcha(phone)
if err != nil {
return err
}
// 写入计数缓存
conf.Redis.Incr(ctx, "PaoPaoSmsCaptcha:"+phone).Result()
currentTime := time.Now()
endTime := time.Date(currentTime.Year(), currentTime.Month(), currentTime.Day(), 23, 59, 59, 0, currentTime.Location())
conf.Redis.Expire(ctx, "PaoPaoSmsCaptcha:"+phone, endTime.Sub(currentTime))
_redis.IncrCountSmsCaptcha(ctx, phone)
return nil
}

@ -6,10 +6,8 @@ package broker
import (
"github.com/rocboss/paopao-ce/internal/core"
"time"
"github.com/gin-gonic/gin"
"github.com/rocboss/paopao-ce/internal/conf"
"github.com/rocboss/paopao-ce/pkg/errcode"
)
@ -26,7 +24,7 @@ func CreateRecharge(userID, amount int64) (*core.WalletRecharge, error) {
}
func FinishRecharge(ctx *gin.Context, id int64, tradeNo string) error {
if ok, _ := conf.Redis.SetNX(ctx, "PaoPaoRecharge:"+tradeNo, 1, time.Second*5).Result(); ok {
if err := _redis.SetRechargeStatus(ctx, tradeNo); err == nil {
recharge, err := ds.GetRechargeByID(id)
if err != nil {
return err
@ -36,7 +34,7 @@ func FinishRecharge(ctx *gin.Context, id int64, tradeNo string) error {
// 标记为已付款
err := ds.HandleRechargeSuccess(recharge, tradeNo)
defer conf.Redis.Del(ctx, "PaoPaoRecharge:"+tradeNo)
defer _redis.DelRechargeStatus(ctx, tradeNo)
if err != nil {
return err

@ -6,7 +6,6 @@ package web
import (
"context"
"fmt"
"time"
"unicode/utf8"
@ -225,8 +224,7 @@ func (s *coreSrv) SendUserWhisper(req *web.SendWhisperReq) mir.Error {
// 今日频次限制
ctx := context.Background()
whisperKey := fmt.Sprintf("WhisperTimes:%d", req.Uid)
if res, _ := s.Redis.Get(ctx, whisperKey).Result(); convert.StrTo(res).MustInt() >= _MaxWhisperNumDaily {
if count, _ := s.Redis.GetCountWhisper(ctx, req.Uid); count >= _MaxWhisperNumDaily {
return _errTooManyWhisperNum
}
@ -244,10 +242,7 @@ func (s *coreSrv) SendUserWhisper(req *web.SendWhisperReq) mir.Error {
}
// 写入当日(自然日)计数缓存
s.Redis.Incr(ctx, whisperKey).Result()
currentTime := time.Now()
endTime := time.Date(currentTime.Year(), currentTime.Month(), currentTime.Day(), 23, 59, 59, 0, currentTime.Location())
s.Redis.Expire(ctx, whisperKey, endTime.Sub(currentTime))
s.Redis.IncrCountWhisper(ctx, req.Uid)
return nil
}

@ -8,11 +8,9 @@ import (
"bytes"
"context"
"encoding/base64"
"fmt"
"image/color"
"image/png"
"regexp"
"time"
"unicode/utf8"
"github.com/afocus/captcha"
@ -40,7 +38,6 @@ var (
)
const (
_LoginErrKey = "PaoPaoUserLoginErr"
_MaxLoginErrTimes = 10
_MaxPhoneCaptcha = 10
)
@ -207,14 +204,14 @@ func (s *pubSrv) SendCaptcha(req *web.SendCaptchaReq) mir.Error {
ctx := context.Background()
// 验证图片验证码
if res, err := s.Redis.Get(ctx, "PaoPaoCaptcha:"+req.ImgCaptchaID).Result(); err != nil || res != req.ImgCaptcha {
logrus.Debugf("get captcha err:%s expect:%s got:%s", err, res, req.ImgCaptcha)
if captcha, err := s.Redis.GetImgCaptcha(ctx, req.ImgCaptchaID); err != nil || string(captcha) != req.ImgCaptcha {
logrus.Debugf("get captcha err:%s expect:%s got:%s", err, captcha, req.ImgCaptcha)
return _errErrorCaptchaPassword
}
s.Redis.Del(ctx, "PaoPaoCaptcha:"+req.ImgCaptchaID).Result()
s.Redis.DelImgCaptcha(ctx, req.ImgCaptchaID)
// 今日频次限制
if res, _ := s.Redis.Get(ctx, "PaoPaoSmsCaptcha:"+req.Phone).Result(); convert.StrTo(res).MustInt() >= _MaxPhoneCaptcha {
if count, _ := s.Redis.GetCountSmsCaptcha(ctx, req.Phone); count >= _MaxPhoneCaptcha {
return _errTooManyPhoneCaptchaSend
}
@ -222,10 +219,7 @@ func (s *pubSrv) SendCaptcha(req *web.SendCaptchaReq) mir.Error {
return xerror.ServerError
}
// 写入计数缓存
s.Redis.Incr(ctx, "PaoPaoSmsCaptcha:"+req.Phone).Result()
currentTime := time.Now()
endTime := time.Date(currentTime.Year(), currentTime.Month(), currentTime.Day(), 23, 59, 59, 0, currentTime.Location())
s.Redis.Expire(ctx, "PaoPaoSmsCaptcha:"+req.Phone, endTime.Sub(currentTime))
s.Redis.IncrCountSmsCaptcha(ctx, req.Phone)
return nil
}
@ -248,7 +242,7 @@ func (s *pubSrv) GetCaptcha() (*web.GetCaptchaResp, mir.Error) {
}
key := utils.EncodeMD5(uuid.Must(uuid.NewV4()).String())
// 五分钟有效期
s.Redis.SetEx(context.Background(), "PaoPaoCaptcha:"+key, password, time.Minute*5)
s.Redis.SetImgCaptcha(context.Background(), key, password)
return &web.GetCaptchaResp{
Id: key,
Content: "data:image/png;base64," + base64.StdEncoding.EncodeToString(emptyBuff.Bytes()),
@ -294,10 +288,8 @@ func (s *pubSrv) Login(req *web.LoginReq) (*web.LoginResp, mir.Error) {
}
if user.Model != nil && user.ID > 0 {
if errTimes, err := s.Redis.Get(ctx, fmt.Sprintf("%s:%d", _LoginErrKey, user.ID)).Result(); err == nil {
if convert.StrTo(errTimes).MustInt() >= _MaxLoginErrTimes {
return nil, _errTooManyLoginError
}
if count, err := s.Redis.GetCountLoginErr(ctx, user.ID); err == nil && count >= _MaxLoginErrTimes {
return nil, _errTooManyLoginError
}
// 对比密码是否正确
if validPassword(user.Password, req.Password, user.Salt) {
@ -305,13 +297,10 @@ func (s *pubSrv) Login(req *web.LoginReq) (*web.LoginResp, mir.Error) {
return nil, _errUserHasBeenBanned
}
// 清空登录计数
s.Redis.Del(ctx, fmt.Sprintf("%s:%d", _LoginErrKey, user.ID))
s.Redis.DelCountLoginErr(ctx, user.ID)
} else {
// 登录错误计数
_, err = s.Redis.Incr(ctx, fmt.Sprintf("%s:%d", _LoginErrKey, user.ID)).Result()
if err == nil {
s.Redis.Expire(ctx, fmt.Sprintf("%s:%d", _LoginErrKey, user.ID), time.Hour).Result()
}
s.Redis.IncrCountLoginErr(ctx, user.ID)
return nil, xerror.UnauthorizedAuthFailed
}
} else {

@ -9,6 +9,7 @@ import (
"github.com/rocboss/paopao-ce/internal/conf"
"github.com/rocboss/paopao-ce/internal/core"
"github.com/rocboss/paopao-ce/internal/dao"
"github.com/rocboss/paopao-ce/internal/dao/cache"
"github.com/sirupsen/logrus"
"github.com/smartwalle/alipay/v3"
)
@ -16,10 +17,12 @@ import (
var (
alipayClient *alipay.Client
objectStorage core.ObjectStorageService
_redis core.RedisCache
)
func Initialize() {
objectStorage = dao.ObjectStorageService()
_redis = cache.NewRedisCache()
if cfg.If("Alipay") {
alipayClient = mustAlipayClient()

@ -9,17 +9,14 @@ import (
"encoding/base64"
"image/color"
"image/png"
"time"
"github.com/afocus/captcha"
"github.com/gin-gonic/gin"
"github.com/gofrs/uuid"
"github.com/rocboss/paopao-ce/internal/conf"
"github.com/rocboss/paopao-ce/internal/core"
"github.com/rocboss/paopao-ce/internal/servants/web/assets"
"github.com/rocboss/paopao-ce/internal/servants/web/broker"
"github.com/rocboss/paopao-ce/pkg/app"
"github.com/rocboss/paopao-ce/pkg/convert"
"github.com/rocboss/paopao-ce/pkg/debug"
"github.com/rocboss/paopao-ce/pkg/errcode"
"github.com/rocboss/paopao-ce/pkg/utils"
@ -65,7 +62,7 @@ func GetCaptcha(c *gin.Context) {
key := utils.EncodeMD5(uuid.Must(uuid.NewV4()).String())
// 五分钟有效期
conf.Redis.SetEx(c, "PaoPaoCaptcha:"+key, password, time.Minute*5)
_redis.SetImgCaptcha(c, key, password)
response := app.NewResponse(c)
response.ToResponse(gin.H{
@ -85,14 +82,14 @@ func PostCaptcha(c *gin.Context) {
}
// 验证图片验证码
if res, err := conf.Redis.Get(c.Request.Context(), "PaoPaoCaptcha:"+param.ImgCaptchaID).Result(); err != nil || res != param.ImgCaptcha {
if res, err := _redis.GetImgCaptcha(c, param.ImgCaptchaID); err != nil || res != param.ImgCaptcha {
response.ToErrorResponse(errcode.ErrorCaptchaPassword)
return
}
conf.Redis.Del(c.Request.Context(), "PaoPaoCaptcha:"+param.ImgCaptchaID).Result()
_redis.DelImgCaptcha(c, param.ImgCaptchaID)
// 今日频次限制
if res, _ := conf.Redis.Get(c.Request.Context(), "PaoPaoSmsCaptcha:"+param.Phone).Result(); convert.StrTo(res).MustInt() >= MAX_PHONE_CAPTCHA {
if count, _ := _redis.GetCountSmsCaptcha(c, param.Phone); count >= MAX_PHONE_CAPTCHA {
response.ToErrorResponse(errcode.TooManyPhoneCaptchaSend)
return
}

@ -26,11 +26,7 @@ var (
func RouteWeb(e *gin.Engine) {
lazyInitial()
oss := dao.ObjectStorageService()
ds := &base.DaoServant{
Redis: conf.Redis,
Ds: dao.DataService(),
Ts: dao.TweetSearchService(),
}
ds := base.NewDaoServant()
// aways register servants
api.RegisterAdminServant(e, newAdminSrv(ds), newAdminBinding(), newAdminRender())
api.RegisterCoreServant(e, newCoreSrv(ds, oss), newCoreBinding(), newCoreRender())

Loading…
Cancel
Save