// Copyright © 2023 OpenIM SDK. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //go:build !js // +build !js package db import ( "context" "errors" "path/filepath" "sync" "time" "github.com/openimsdk/openim-sdk-core/v3/pkg/constant" "github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct" "github.com/openimsdk/openim-sdk-core/v3/pkg/utils" "github.com/openimsdk/openim-sdk-core/v3/version" "github.com/openimsdk/tools/errs" "github.com/openimsdk/tools/log" "gorm.io/driver/sqlite" "gorm.io/gorm" "gorm.io/gorm/logger" ) type DataBase struct { loginUserID string dbDir string conn *gorm.DB mRWMutex sync.RWMutex groupMtx sync.RWMutex friendMtx sync.RWMutex userMtx sync.RWMutex versionMtx sync.RWMutex superGroupMtx sync.RWMutex } func (d *DataBase) GetMultipleMessageReactionExtension(ctx context.Context, msgIDList []string) (result []*model_struct.LocalChatLogReactionExtensions, err error) { // TODO implement me panic("implement me") } func (d *DataBase) InitSuperLocalErrChatLog(ctx context.Context, groupID string) { panic("implement me") } func (d *DataBase) InitSuperLocalChatLog(ctx context.Context, groupID string) { panic("implement me") } func (d *DataBase) SetChatLogFailedStatus(ctx context.Context) { panic("implement me") } func (d *DataBase) InitDB(ctx context.Context, userID string, dataDir string) error { panic("implement me") } func (d *DataBase) Close(ctx context.Context) error { dbConn, err := d.conn.WithContext(ctx).DB() if err != nil { return err } else { if dbConn != nil { err := dbConn.Close() if err != nil { return err } } } return nil } func NewDataBase(ctx context.Context, loginUserID string, dbDir string, logLevel int) (*DataBase, error) { dataBase := &DataBase{loginUserID: loginUserID, dbDir: dbDir} err := dataBase.initDB(ctx, logLevel) if err != nil { return dataBase, utils.Wrap(err, "initDB failed "+dbDir) } return dataBase, nil } func (d *DataBase) initDB(ctx context.Context, logLevel int) error { var zLogLevel logger.LogLevel if d.loginUserID == "" { return errors.New("no uid") } d.mRWMutex.Lock() defer d.mRWMutex.Unlock() path := d.dbDir + "/OpenIM_" + constant.BigVersion + "_" + d.loginUserID + ".db" dbFileName, err := filepath.Abs(path) if err != nil { return err } log.ZInfo(ctx, "sqlite", "path", dbFileName) // slowThreshold := 500 // sqlLogger := log.NewSqlLogger(logger.LogLevel(sdk_struct.SvrConf.LogLevel), true, time.Duration(slowThreshold)*time.Millisecond) if logLevel > 5 { zLogLevel = logger.Info } else { zLogLevel = logger.Silent } db, err := gorm.Open(sqlite.Open(dbFileName), &gorm.Config{Logger: log.NewSqlLogger(zLogLevel, false, time.Millisecond*200)}) if err != nil { return utils.Wrap(err, "open db failed "+dbFileName) } log.ZDebug(ctx, "open db success", "db", db, "dbFileName", dbFileName) sqlDB, err := db.DB() if err != nil { return utils.Wrap(err, "get sql db failed") } sqlDB.SetConnMaxLifetime(time.Hour * 1) sqlDB.SetMaxOpenConns(3) sqlDB.SetMaxIdleConns(2) sqlDB.SetConnMaxIdleTime(time.Minute * 10) d.conn = db // base if err = db.AutoMigrate(&model_struct.LocalAppSDKVersion{}); err != nil { return err } if err = d.versionDataMigrate(ctx); err != nil { return err } //if err := db.Table(constant.SuperGroupTableName).AutoMigrate(superGroup); err != nil { // return err //} return nil } func (d *DataBase) versionDataMigrate(ctx context.Context) error { verModel, err := d.GetAppSDKVersion(ctx) if errs.Unwrap(err) == gorm.ErrRecordNotFound { err = d.conn.AutoMigrate( &model_struct.LocalAppSDKVersion{}, &model_struct.LocalFriend{}, &model_struct.LocalFriendRequest{}, &model_struct.LocalGroup{}, &model_struct.LocalGroupMember{}, &model_struct.LocalGroupRequest{}, &model_struct.LocalErrChatLog{}, &model_struct.LocalUser{}, &model_struct.LocalBlack{}, &model_struct.LocalConversation{}, &model_struct.NotificationSeqs{}, &model_struct.LocalChatLog{}, &model_struct.LocalAdminGroupRequest{}, &model_struct.LocalWorkMomentsNotification{}, &model_struct.LocalWorkMomentsNotificationUnreadCount{}, &model_struct.TempCacheLocalChatLog{}, &model_struct.LocalChatLogReactionExtensions{}, &model_struct.LocalUpload{}, &model_struct.LocalStranger{}, &model_struct.LocalSendingMessages{}, &model_struct.LocalUserCommand{}, &model_struct.LocalVersionSync{}, ) if err != nil { return err } err = d.SetAppSDKVersion(ctx, &model_struct.LocalAppSDKVersion{Version: version.Version}) if err != nil { return err } return nil } else if err != nil { return err } if verModel.Version != version.Version { switch version.Version { case "3.8.0": d.conn.AutoMigrate(&model_struct.LocalAppSDKVersion{}) } err = d.SetAppSDKVersion(ctx, &model_struct.LocalAppSDKVersion{Version: version.Version}) if err != nil { return err } } return nil }