mirror of
				https://github.com/openimsdk/open-im-server.git
				synced 2025-11-04 19:32:17 +08:00 
			
		
		
		
	
		
			
				
	
	
		
			164 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			164 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
package listdemo
 | 
						|
 | 
						|
import (
 | 
						|
	"context"
 | 
						|
	"github.com/openimsdk/tools/db/mongoutil"
 | 
						|
	"github.com/openimsdk/tools/errs"
 | 
						|
	"github.com/pkg/errors"
 | 
						|
	"go.mongodb.org/mongo-driver/bson"
 | 
						|
	"go.mongodb.org/mongo-driver/mongo"
 | 
						|
	"time"
 | 
						|
)
 | 
						|
 | 
						|
var (
 | 
						|
	ErrListNotFound = errors.New("list not found")
 | 
						|
	ErrElemExist    = errors.New("elem exist")
 | 
						|
	ErrNeedFull     = errors.New("need full")
 | 
						|
	ErrNotFound     = mongo.ErrNoDocuments
 | 
						|
)
 | 
						|
 | 
						|
type Elem struct {
 | 
						|
	ID      string
 | 
						|
	Version uint
 | 
						|
}
 | 
						|
 | 
						|
type ChangeLog struct {
 | 
						|
	ChangeIDs []Elem
 | 
						|
	DeleteIDs []Elem
 | 
						|
}
 | 
						|
 | 
						|
type WriteLog struct {
 | 
						|
	DID           string    `bson:"d_id"`
 | 
						|
	Logs          []LogElem `bson:"logs"`
 | 
						|
	Version       uint      `bson:"version"`
 | 
						|
	LastUpdate    time.Time `bson:"last_update"`
 | 
						|
	DeleteVersion uint      `bson:"delete_version"`
 | 
						|
}
 | 
						|
 | 
						|
type LogElem struct {
 | 
						|
	EID        string    `bson:"e_id"`
 | 
						|
	Deleted    bool      `bson:"deleted"`
 | 
						|
	Version    uint      `bson:"version"`
 | 
						|
	UpdateTime time.Time `bson:"update_time"`
 | 
						|
}
 | 
						|
 | 
						|
type LogModel struct {
 | 
						|
	coll *mongo.Collection
 | 
						|
}
 | 
						|
 | 
						|
func (l *LogModel) InitIndex(ctx context.Context) error {
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
func (l *LogModel) WriteLog(ctx context.Context, dId string, eId string, deleted bool) error {
 | 
						|
	now := time.Now()
 | 
						|
	res, err := l.writeLog(ctx, dId, eId, deleted, now)
 | 
						|
	if err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
	if res.MatchedCount > 0 {
 | 
						|
		return nil
 | 
						|
	}
 | 
						|
	wl := WriteLog{
 | 
						|
		DID: dId,
 | 
						|
		Logs: []LogElem{
 | 
						|
			{
 | 
						|
				EID:        eId,
 | 
						|
				Deleted:    deleted,
 | 
						|
				Version:    1,
 | 
						|
				UpdateTime: now,
 | 
						|
			},
 | 
						|
		},
 | 
						|
		Version:       1,
 | 
						|
		LastUpdate:    now,
 | 
						|
		DeleteVersion: 0,
 | 
						|
	}
 | 
						|
	if _, err := l.coll.InsertOne(ctx, &wl); err == nil {
 | 
						|
		return nil
 | 
						|
	} else if !mongo.IsDuplicateKeyError(err) {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
	if res, err := l.writeLog(ctx, dId, eId, deleted, now); err != nil {
 | 
						|
		return err
 | 
						|
	} else if res.ModifiedCount == 0 {
 | 
						|
		return errs.ErrInternalServer.WrapMsg("mongodb return value that should not occur", "coll", l.coll.Name(), "dId", dId, "eId", eId)
 | 
						|
	}
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
func (l *LogModel) writeLog(ctx context.Context, dId string, eId string, deleted bool, now time.Time) (*mongo.UpdateResult, error) {
 | 
						|
	filter := bson.M{
 | 
						|
		"d_id": dId,
 | 
						|
	}
 | 
						|
	elem := bson.M{
 | 
						|
		"e_id":        eId,
 | 
						|
		"version":     "$version",
 | 
						|
		"deleted":     deleted,
 | 
						|
		"update_time": now,
 | 
						|
	}
 | 
						|
	pipeline := []bson.M{
 | 
						|
		{
 | 
						|
			"$addFields": bson.M{
 | 
						|
				"elem_index": bson.M{
 | 
						|
					"$indexOfArray": []any{"$logs.e_id", eId},
 | 
						|
				},
 | 
						|
			},
 | 
						|
		},
 | 
						|
		{
 | 
						|
			"$set": bson.M{
 | 
						|
				"version":     bson.M{"$add": []any{"$version", 1}},
 | 
						|
				"update_time": now,
 | 
						|
			},
 | 
						|
		},
 | 
						|
		{
 | 
						|
			"$set": bson.M{
 | 
						|
				"logs": bson.M{
 | 
						|
					"$cond": bson.M{
 | 
						|
						"if": bson.M{
 | 
						|
							"$lt": []any{"$elem_index", 0},
 | 
						|
						},
 | 
						|
						"then": bson.M{
 | 
						|
							"$concatArrays": []any{
 | 
						|
								"$logs",
 | 
						|
								[]bson.M{
 | 
						|
									elem,
 | 
						|
								},
 | 
						|
							},
 | 
						|
						},
 | 
						|
						"else": bson.M{
 | 
						|
							"$map": bson.M{
 | 
						|
								"input": bson.M{
 | 
						|
									"$range": []any{0, bson.M{"$size": "$logs"}},
 | 
						|
								},
 | 
						|
								"as": "i",
 | 
						|
								"in": bson.M{
 | 
						|
									"$cond": bson.M{
 | 
						|
										"if": bson.M{
 | 
						|
											"$eq": []any{"$$i", "$elem_index"},
 | 
						|
										},
 | 
						|
										"then": elem,
 | 
						|
										"else": bson.M{
 | 
						|
											"$arrayElemAt": []any{
 | 
						|
												"$logs",
 | 
						|
												"$$i",
 | 
						|
											},
 | 
						|
										},
 | 
						|
									},
 | 
						|
								},
 | 
						|
							},
 | 
						|
						},
 | 
						|
					},
 | 
						|
				},
 | 
						|
			},
 | 
						|
		},
 | 
						|
		{
 | 
						|
			"$unset": "elem_index",
 | 
						|
		},
 | 
						|
	}
 | 
						|
	return mongoutil.UpdateMany(ctx, l.coll, filter, pipeline)
 | 
						|
}
 | 
						|
 | 
						|
func (l *LogModel) FindChangeLog(ctx context.Context, did string, version uint) (*ChangeLog, error) {
 | 
						|
	return nil, nil
 | 
						|
}
 |