mirror of
				https://github.com/openimsdk/open-im-server.git
				synced 2025-11-04 11:22:10 +08:00 
			
		
		
		
	* update wip contents. * update protocol pkg. * feat: add BatchOption struct and method. * fix: remove unnecessary field. * feat: implement true BatchGetIncrGroupMember RPC method and corresponding dependency methods. * fix: update mongo version collection have unique index. * optimize method structures. * update resp in add sortVersion field. * fix uncorrect condition. * add errs pkg.
		
			
				
	
	
		
			154 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			154 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
package incrversion
 | 
						|
 | 
						|
import (
 | 
						|
	"context"
 | 
						|
	"fmt"
 | 
						|
 | 
						|
	"github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
 | 
						|
	"github.com/openimsdk/tools/errs"
 | 
						|
	"go.mongodb.org/mongo-driver/bson/primitive"
 | 
						|
)
 | 
						|
 | 
						|
//func Limit(maxSync int, version uint64) int {
 | 
						|
//	if version == 0 {
 | 
						|
//		return 0
 | 
						|
//	}
 | 
						|
//	return maxSync
 | 
						|
//}
 | 
						|
 | 
						|
const syncLimit = 200
 | 
						|
 | 
						|
const (
 | 
						|
	tagQuery = iota + 1
 | 
						|
	tagFull
 | 
						|
	tagEqual
 | 
						|
)
 | 
						|
 | 
						|
type Option[A, B any] struct {
 | 
						|
	Ctx           context.Context
 | 
						|
	VersionKey    string
 | 
						|
	VersionID     string
 | 
						|
	VersionNumber uint64
 | 
						|
	//SyncLimit       int
 | 
						|
	CacheMaxVersion func(ctx context.Context, dId string) (*model.VersionLog, error)
 | 
						|
	Version         func(ctx context.Context, dId string, version uint, limit int) (*model.VersionLog, error)
 | 
						|
	//SortID          func(ctx context.Context, dId string) ([]string, error)
 | 
						|
	Find func(ctx context.Context, ids []string) ([]A, error)
 | 
						|
	Resp func(version *model.VersionLog, deleteIds []string, insertList, updateList []A, full bool) *B
 | 
						|
}
 | 
						|
 | 
						|
func (o *Option[A, B]) newError(msg string) error {
 | 
						|
	return errs.ErrInternalServer.WrapMsg(msg)
 | 
						|
}
 | 
						|
 | 
						|
func (o *Option[A, B]) check() error {
 | 
						|
	if o.Ctx == nil {
 | 
						|
		return o.newError("opt ctx is nil")
 | 
						|
	}
 | 
						|
	if o.VersionKey == "" {
 | 
						|
		return o.newError("versionKey is empty")
 | 
						|
	}
 | 
						|
	//if o.SyncLimit <= 0 {
 | 
						|
	//	return o.newError("invalid synchronization quantity")
 | 
						|
	//}
 | 
						|
	if o.Version == nil {
 | 
						|
		return o.newError("func version is nil")
 | 
						|
	}
 | 
						|
	//if o.SortID == nil {
 | 
						|
	//	return o.newError("func allID is nil")
 | 
						|
	//}
 | 
						|
	if o.Find == nil {
 | 
						|
		return o.newError("func find is nil")
 | 
						|
	}
 | 
						|
	if o.Resp == nil {
 | 
						|
		return o.newError("func resp is nil")
 | 
						|
	}
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
func (o *Option[A, B]) validVersion() bool {
 | 
						|
	objID, err := primitive.ObjectIDFromHex(o.VersionID)
 | 
						|
	return err == nil && (!objID.IsZero()) && o.VersionNumber > 0
 | 
						|
}
 | 
						|
 | 
						|
func (o *Option[A, B]) equalID(objID primitive.ObjectID) bool {
 | 
						|
	return o.VersionID == objID.Hex()
 | 
						|
}
 | 
						|
 | 
						|
func (o *Option[A, B]) getVersion(tag *int) (*model.VersionLog, error) {
 | 
						|
	if o.CacheMaxVersion == nil {
 | 
						|
		if o.validVersion() {
 | 
						|
			*tag = tagQuery
 | 
						|
			return o.Version(o.Ctx, o.VersionKey, uint(o.VersionNumber), syncLimit)
 | 
						|
		}
 | 
						|
		*tag = tagFull
 | 
						|
		return o.Version(o.Ctx, o.VersionKey, 0, 0)
 | 
						|
	} else {
 | 
						|
		cache, err := o.CacheMaxVersion(o.Ctx, o.VersionKey)
 | 
						|
		if err != nil {
 | 
						|
			return nil, err
 | 
						|
		}
 | 
						|
		if !o.validVersion() {
 | 
						|
			*tag = tagFull
 | 
						|
			return cache, nil
 | 
						|
		}
 | 
						|
		if !o.equalID(cache.ID) {
 | 
						|
			*tag = tagFull
 | 
						|
			return cache, nil
 | 
						|
		}
 | 
						|
		if o.VersionNumber == uint64(cache.Version) {
 | 
						|
			*tag = tagEqual
 | 
						|
			return cache, nil
 | 
						|
		}
 | 
						|
		*tag = tagQuery
 | 
						|
		return o.Version(o.Ctx, o.VersionKey, uint(o.VersionNumber), syncLimit)
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func (o *Option[A, B]) Build() (*B, error) {
 | 
						|
	if err := o.check(); err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
	var tag int
 | 
						|
	version, err := o.getVersion(&tag)
 | 
						|
	if err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
	var full bool
 | 
						|
	switch tag {
 | 
						|
	case tagQuery:
 | 
						|
		full = version.ID.Hex() != o.VersionID || uint64(version.Version) < o.VersionNumber || len(version.Logs) != version.LogLen
 | 
						|
	case tagFull:
 | 
						|
		full = true
 | 
						|
	case tagEqual:
 | 
						|
		full = false
 | 
						|
	default:
 | 
						|
		panic(fmt.Errorf("undefined tag %d", tag))
 | 
						|
	}
 | 
						|
	var (
 | 
						|
		insertIds []string
 | 
						|
		deleteIds []string
 | 
						|
		updateIds []string
 | 
						|
	)
 | 
						|
	if !full {
 | 
						|
		insertIds, deleteIds, updateIds = version.DeleteAndChangeIDs()
 | 
						|
	}
 | 
						|
	var (
 | 
						|
		insertList []A
 | 
						|
		updateList []A
 | 
						|
	)
 | 
						|
	if len(insertIds) > 0 {
 | 
						|
		insertList, err = o.Find(o.Ctx, insertIds)
 | 
						|
		if err != nil {
 | 
						|
			return nil, err
 | 
						|
		}
 | 
						|
	}
 | 
						|
	if len(updateIds) > 0 {
 | 
						|
		updateList, err = o.Find(o.Ctx, updateIds)
 | 
						|
		if err != nil {
 | 
						|
			return nil, err
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return o.Resp(version, deleteIds, insertList, updateList, full), nil
 | 
						|
}
 |