wip: alpha version

This commit is contained in:
loveuer
2024-03-31 20:09:20 +08:00
commit 195fbcd308
145 changed files with 16872 additions and 0 deletions

View File

@ -0,0 +1,26 @@
package database
import "encoding/json"
type encoded_value interface {
MarshalBinary() ([]byte, error)
}
type decoded_value interface {
UnmarshalBinary(bs []byte) error
}
func handleValue(value any) ([]byte, error) {
var (
bs []byte
err error
)
if imp, ok := value.(encoded_value); ok {
bs, err = imp.MarshalBinary()
} else {
bs, err = json.Marshal(value)
}
return bs, err
}

View File

@ -0,0 +1,63 @@
package database
import (
"context"
"fmt"
"gitea.com/taozitaozi/gredis"
"time"
)
var _ Caches = (*_mem)(nil)
type _mem struct {
client *gredis.Gredis
}
func (m *_mem) Get(ctx context.Context, key string) ([]byte, error) {
v, err := m.client.Get(key)
if err != nil {
return nil, err
}
bs, ok := v.([]byte)
if !ok {
return nil, fmt.Errorf("invalid value type=%T", v)
}
return bs, nil
}
func (m *_mem) GetEx(ctx context.Context, key string, duration time.Duration) ([]byte, error) {
v, err := m.client.GetEx(key, duration)
if err != nil {
return nil, err
}
bs, ok := v.([]byte)
if !ok {
return nil, fmt.Errorf("invalid value type=%T", v)
}
return bs, nil
}
func (m *_mem) Set(ctx context.Context, key string, value any) error {
bs, err := handleValue(value)
if err != nil {
return err
}
return m.client.Set(key, bs)
}
func (m *_mem) SetEx(ctx context.Context, key string, value any, duration time.Duration) error {
bs, err := handleValue(value)
if err != nil {
return err
}
return m.client.SetEx(key, bs, duration)
}
func (m *_mem) Del(ctx context.Context, keys ...string) error {
m.client.Delete(keys...)
return nil
}

View File

@ -0,0 +1,54 @@
package database
import (
"context"
"github.com/go-redis/redis/v8"
"time"
)
type _redis struct {
client *redis.Client
}
func (r *_redis) Get(ctx context.Context, key string) ([]byte, error) {
result, err := r.client.Get(ctx, key).Result()
if err != nil {
return nil, err
}
return []byte(result), nil
}
func (r *_redis) GetEx(ctx context.Context, key string, duration time.Duration) ([]byte, error) {
result, err := r.client.GetEx(ctx, key, duration).Result()
if err != nil {
return nil, err
}
return []byte(result), nil
}
func (r *_redis) Set(ctx context.Context, key string, value any) error {
bs, err := handleValue(value)
if err != nil {
return err
}
_, err = r.client.Set(ctx, key, bs, redis.KeepTTL).Result()
return err
}
func (r *_redis) SetEx(ctx context.Context, key string, value any, duration time.Duration) error {
bs, err := handleValue(value)
if err != nil {
return err
}
_, err = r.client.SetEX(ctx, key, bs, duration).Result()
return err
}
func (r *_redis) Del(ctx context.Context, keys ...string) error {
return r.client.Del(ctx, keys...).Err()
}

View File

@ -0,0 +1,6 @@
package database
var (
DB Store
Cache Caches
)

89
internal/database/init.go Normal file
View File

@ -0,0 +1,89 @@
package database
import (
"fmt"
"gitea.com/taozitaozi/gredis"
"github.com/glebarez/sqlite"
"github.com/go-redis/redis/v8"
"github.com/loveuer/nfflow/internal/opt"
"github.com/loveuer/nfflow/internal/util"
"gorm.io/driver/mysql"
"gorm.io/driver/postgres"
"gorm.io/gorm"
)
func MustInitClient() {
var (
err error
)
// todo: 可以实现自己的 "Store" sql_db, like sqlite, postgresql
if DB, err = initSql(); err != nil {
panic(fmt.Errorf("database.MustInitClient: init sql err=%v", err))
}
// todo: 可以实现自己的 "Caches" 缓存, like redis
if Cache, err = initCacher(); err != nil {
panic(fmt.Errorf("database.MustInitCache: init cache err=%v", err))
}
}
func initSql() (Store, error) {
var (
err error
client *gorm.DB
)
switch opt.Cfg.Database.Type {
case "postgresql":
dsn := fmt.Sprintf("host=%s user=%s password=%s dbname=%s port=%d sslmode=disable TimeZone=Asia/Shanghai",
opt.Cfg.Database.Host, opt.Cfg.Database.Username, opt.Cfg.Database.Password, opt.Cfg.Database.DB, opt.Cfg.Database.Port)
if client, err = gorm.Open(postgres.Open(dsn)); err != nil {
return nil, err
}
case "mysql":
dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8mb4&parseTime=True&loc=Local",
opt.Cfg.Database.Username, opt.Cfg.Database.Password, opt.Cfg.Database.Host, opt.Cfg.Database.Port, opt.Cfg.Database.DB)
if client, err = gorm.Open(mysql.Open(dsn)); err != nil {
return nil, err
}
case "sqlite":
if client, err = gorm.Open(sqlite.Open(opt.Cfg.Database.Path)); err != nil {
return nil, err
}
default:
return nil, fmt.Errorf("unsupportted databsae type=%s", opt.Cfg.Database.Type)
}
return &_db{client: client}, nil
}
func initCacher() (Caches, error) {
var (
err error
)
switch opt.Cfg.Cache.Type {
case "redis":
var rc *redis.Client
rc = redis.NewClient(&redis.Options{
Addr: fmt.Sprintf("%s:%d", opt.Cfg.Cache.Host, opt.Cfg.Cache.Port),
Username: opt.Cfg.Cache.Username,
Password: opt.Cfg.Cache.Password,
})
if err = rc.Ping(util.Timeout(5)).Err(); err != nil {
return nil, fmt.Errorf("redis ping err=%v", err)
}
return &_redis{client: rc}, nil
case "memory":
var mc *gredis.Gredis
mc = gredis.NewGredis(-1)
return &_mem{client: mc}, nil
default:
return nil, fmt.Errorf("unsupportted cache type=%s", opt.Cfg.Cache.Type)
}
}

View File

@ -0,0 +1,21 @@
package database
import (
"context"
"gorm.io/gorm"
"time"
)
type Caches interface {
Get(ctx context.Context, key string) ([]byte, error)
GetEx(ctx context.Context, key string, duration time.Duration) ([]byte, error)
// Set value 会被序列化, 优先使用 MarshalBinary 方法, 没有则执行 json.Marshal
Set(ctx context.Context, key string, value any) error
// SetEx value 会被序列化, 优先使用 MarshalBinary 方法, 没有则执行 json.Marshal
SetEx(ctx context.Context, key string, value any, duration time.Duration) error
Del(ctx context.Context, keys ...string) error
}
type Store interface {
Session(ctx context.Context) *gorm.DB
}

20
internal/database/sql.go Normal file
View File

@ -0,0 +1,20 @@
package database
import (
"context"
"github.com/loveuer/nfflow/internal/opt"
"gorm.io/gorm"
)
type _db struct {
client *gorm.DB
}
func (d *_db) Session(ctx context.Context) *gorm.DB {
s := d.client.Session(&gorm.Session{})
if opt.Debug > 0 || opt.DBDebug {
s = s.Debug()
}
return s
}