package copymission import ( "context" "errors" "fmt" "strings" "time" goredis "github.com/redis/go-redis/v9" ) const matrixReplaceLockTTL = 10 * time.Minute // WithMatrixReplaceLock serializes matrix draft replacement for one copy mission. func WithMatrixReplaceLock( ctx context.Context, redis *goredis.Client, tenantID, missionID, holder string, fn func() error, ) error { if fn == nil { return nil } tenantID = strings.TrimSpace(tenantID) missionID = strings.TrimSpace(missionID) holder = strings.TrimSpace(holder) if tenantID == "" || missionID == "" { return fn() } if redis == nil { return fn() } key := fmt.Sprintf("haixun:copy_matrix:%s:%s", tenantID, missionID) if holder == "" { holder = "matrix-replace" } ok, err := redis.SetNX(ctx, key, holder, matrixReplaceLockTTL).Result() if err != nil { return err } if !ok { return errors.New("copy matrix replacement already in progress") } defer func() { script := ` if redis.call("get", KEYS[1]) == ARGV[1] then return redis.call("del", KEYS[1]) end return 0 ` _ = redis.Eval(ctx, script, []string{key}, holder).Err() }() return fn() }