mirror of
				https://github.com/openimsdk/open-im-server.git
				synced 2025-10-26 21:22:16 +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
 | |
| }
 |