fix: [2.5] Fix parsing import endTs (#40333)

Parsing import beginTs, endTs as a hybrid timestamp.

issue: https://github.com/milvus-io/milvus/issues/40326

pr: https://github.com/milvus-io/milvus/pull/40332

---------

Signed-off-by: bigsheeper <yihao.dai@zilliz.com>
pull/40365/head
yihao.dai 2025-03-05 11:40:13 +08:00 committed by GitHub
parent 9a42d3dc37
commit 7cbd40c7a1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 65 additions and 2 deletions

View File

@ -83,11 +83,14 @@ func ParseTimeRange(options Options) (uint64, uint64, error) {
for _, targetKey := range targetKeys {
for key, value := range importOptions {
if strings.EqualFold(key, targetKey) {
pTs, err := strconv.ParseInt(value, 10, 64)
ts, err := strconv.ParseUint(value, 10, 64)
if err != nil {
return 0, merr.WrapErrImportFailed(fmt.Sprintf("parse %s failed, value=%s, err=%s", targetKey, value, err))
}
return tsoutil.ComposeTS(pTs, 0), nil
if !tsoutil.IsValidHybridTs(ts) {
return 0, merr.WrapErrImportFailed(fmt.Sprintf("%s is not a valid hybrid timestamp, value=%s", targetKey, value))
}
return ts, nil
}
}
}

View File

@ -17,12 +17,15 @@
package importutilv2
import (
"fmt"
"math"
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/milvus-io/milvus-proto/go-api/v2/commonpb"
"github.com/milvus-io/milvus/pkg/v2/util/merr"
"github.com/milvus-io/milvus/pkg/v2/util/tsoutil"
)
@ -51,3 +54,37 @@ func TestOption_GetTimeout(t *testing.T) {
_, err = GetTimeoutTs(options)
assert.Error(t, err)
}
func TestOption_ParseTimeRange(t *testing.T) {
s, e, err := ParseTimeRange(nil)
assert.NoError(t, err)
assert.Equal(t, uint64(0), s)
assert.Equal(t, uint64(math.MaxUint64), e)
startTs := tsoutil.GetCurrentTime()
options := []*commonpb.KeyValuePair{{Key: StartTs, Value: fmt.Sprintf("%d", startTs)}}
s, e, err = ParseTimeRange(options)
assert.NoError(t, err)
assert.Equal(t, startTs, s)
assert.Equal(t, uint64(math.MaxUint64), e)
endTs := tsoutil.GetCurrentTime()
options = []*commonpb.KeyValuePair{{Key: EndTs, Value: fmt.Sprintf("%d", endTs)}}
s, e, err = ParseTimeRange(options)
assert.NoError(t, err)
assert.Equal(t, uint64(0), s)
assert.Equal(t, endTs, e)
options = []*commonpb.KeyValuePair{{Key: EndTs, Value: "&%#$%^&%^&$%^&&"}}
_, _, err = ParseTimeRange(options)
assert.ErrorIs(t, err, merr.ErrImportFailed)
physicalTs := time.Now().UnixMilli()
options = []*commonpb.KeyValuePair{{Key: EndTs, Value: fmt.Sprintf("%d", physicalTs)}}
_, _, err = ParseTimeRange(options)
assert.ErrorIs(t, err, merr.ErrImportFailed)
options = []*commonpb.KeyValuePair{{Key: StartTs, Value: "0"}}
_, _, err = ParseTimeRange(options)
assert.ErrorIs(t, err, merr.ErrImportFailed)
}

View File

@ -99,3 +99,16 @@ func SubByNow(ts uint64) int64 {
func PhysicalTimeFormat(ts uint64) string {
return PhysicalTime(ts).Format(time.DateTime)
}
const (
minUnixMillis = 1546300800000 // 2019-01-01 00:00:00 UTC
maxUnixMillis = 253402300799000 // 9999-12-31 23:59:59 UTC
)
func IsValidPhysicalTs(t uint64) bool {
return t >= minUnixMillis && t <= maxUnixMillis
}
func IsValidHybridTs(t uint64) bool {
return IsValidPhysicalTs(t >> logicalBits)
}

View File

@ -70,3 +70,13 @@ func TestAddPhysicalDurationOnTs(t *testing.T) {
// diff := CalculateDuration(ts2, ts1)
assert.Equal(t, ts3, ts2)
}
func TestIsValidUnixMilli(t *testing.T) {
physicalTs := uint64(time.Now().UnixMilli())
assert.True(t, IsValidPhysicalTs(physicalTs))
assert.False(t, IsValidHybridTs(physicalTs))
hybridTs := GetCurrentTime()
assert.False(t, IsValidPhysicalTs(hybridTs))
assert.True(t, IsValidHybridTs(hybridTs))
}