mirror of https://github.com/milvus-io/milvus.git
Add the limitation of the traceable interval to timeTravel (#14498)
Signed-off-by: zhenshan.cao <zhenshan.cao@zilliz.com>pull/14555/head
parent
c5c38bdb2e
commit
32a5126705
|
@ -177,7 +177,6 @@ dataCoord:
|
||||||
|
|
||||||
compaction:
|
compaction:
|
||||||
enableAutoCompaction: true
|
enableAutoCompaction: true
|
||||||
retentionDuration: 432000 # 5 days in seconds
|
|
||||||
|
|
||||||
gc:
|
gc:
|
||||||
interval: 3600 # gc interval in seconds
|
interval: 3600 # gc interval in seconds
|
||||||
|
@ -220,7 +219,7 @@ log:
|
||||||
msgChannel:
|
msgChannel:
|
||||||
# Channel name generation rule: ${namePrefix}-${ChannelIdx}
|
# Channel name generation rule: ${namePrefix}-${ChannelIdx}
|
||||||
chanNamePrefix:
|
chanNamePrefix:
|
||||||
cluster: "by-dev"
|
cluster: "by-dev"
|
||||||
rootCoordTimeTick: "rootcoord-timetick"
|
rootCoordTimeTick: "rootcoord-timetick"
|
||||||
rootCoordStatistics: "rootcoord-statistics"
|
rootCoordStatistics: "rootcoord-statistics"
|
||||||
rootCoordDml: "rootcoord-dml"
|
rootCoordDml: "rootcoord-dml"
|
||||||
|
@ -250,6 +249,7 @@ msgChannel:
|
||||||
common:
|
common:
|
||||||
defaultPartitionName: "_default" # default partition name for a collection
|
defaultPartitionName: "_default" # default partition name for a collection
|
||||||
defaultIndexName: "_default_idx" # default index name
|
defaultIndexName: "_default_idx" # default index name
|
||||||
|
retentionDuration: 432000 # 5 days in seconds
|
||||||
|
|
||||||
knowhere:
|
knowhere:
|
||||||
# Default value: auto
|
# Default value: auto
|
||||||
|
|
|
@ -73,7 +73,7 @@ func getTimetravelReverseTime(ctx context.Context, allocator allocator) (*timetr
|
||||||
}
|
}
|
||||||
|
|
||||||
pts, _ := tsoutil.ParseTS(ts)
|
pts, _ := tsoutil.ParseTS(ts)
|
||||||
ttpts := pts.Add(-time.Duration(Params.DataCoordCfg.CompactionRetentionDuration) * time.Second)
|
ttpts := pts.Add(-time.Duration(Params.DataCoordCfg.RetentionDuration) * time.Second)
|
||||||
tt := tsoutil.ComposeTS(ttpts.UnixNano()/int64(time.Millisecond), 0)
|
tt := tsoutil.ComposeTS(ttpts.UnixNano()/int64(time.Millisecond), 0)
|
||||||
return &timetravel{tt}, nil
|
return &timetravel{tt}, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -113,10 +113,10 @@ func TestVerifyResponse(t *testing.T) {
|
||||||
|
|
||||||
func Test_getTimetravelReverseTime(t *testing.T) {
|
func Test_getTimetravelReverseTime(t *testing.T) {
|
||||||
Params.Init()
|
Params.Init()
|
||||||
Params.DataCoordCfg.CompactionRetentionDuration = 43200 // 5 days
|
Params.DataCoordCfg.RetentionDuration = 43200 // 5 days
|
||||||
|
|
||||||
tFixed := time.Date(2021, 11, 15, 0, 0, 0, 0, time.Local)
|
tFixed := time.Date(2021, 11, 15, 0, 0, 0, 0, time.Local)
|
||||||
tBefore := tFixed.Add(-time.Duration(Params.DataCoordCfg.CompactionRetentionDuration) * time.Second)
|
tBefore := tFixed.Add(-time.Duration(Params.DataCoordCfg.RetentionDuration) * time.Second)
|
||||||
|
|
||||||
type args struct {
|
type args struct {
|
||||||
allocator allocator
|
allocator allocator
|
||||||
|
|
|
@ -2341,14 +2341,6 @@ func (node *Proxy) Query(ctx context.Context, request *milvuspb.QueryRequest) (*
|
||||||
defer sp.Finish()
|
defer sp.Finish()
|
||||||
traceID, _, _ := trace.InfoFromSpan(sp)
|
traceID, _, _ := trace.InfoFromSpan(sp)
|
||||||
|
|
||||||
queryRequest := &milvuspb.QueryRequest{
|
|
||||||
DbName: request.DbName,
|
|
||||||
CollectionName: request.CollectionName,
|
|
||||||
PartitionNames: request.PartitionNames,
|
|
||||||
Expr: request.Expr,
|
|
||||||
OutputFields: request.OutputFields,
|
|
||||||
}
|
|
||||||
|
|
||||||
qt := &queryTask{
|
qt := &queryTask{
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
Condition: NewTaskCondition(ctx),
|
Condition: NewTaskCondition(ctx),
|
||||||
|
@ -2360,7 +2352,7 @@ func (node *Proxy) Query(ctx context.Context, request *milvuspb.QueryRequest) (*
|
||||||
ResultChannelID: strconv.FormatInt(Params.ProxyCfg.ProxyID, 10),
|
ResultChannelID: strconv.FormatInt(Params.ProxyCfg.ProxyID, 10),
|
||||||
},
|
},
|
||||||
resultBuf: make(chan []*internalpb.RetrieveResults),
|
resultBuf: make(chan []*internalpb.RetrieveResults),
|
||||||
query: queryRequest,
|
query: request,
|
||||||
chMgr: node.chMgr,
|
chMgr: node.chMgr,
|
||||||
qc: node.queryCoord,
|
qc: node.queryCoord,
|
||||||
}
|
}
|
||||||
|
@ -2371,9 +2363,9 @@ func (node *Proxy) Query(ctx context.Context, request *milvuspb.QueryRequest) (*
|
||||||
rpcReceived(method),
|
rpcReceived(method),
|
||||||
zap.String("traceID", traceID),
|
zap.String("traceID", traceID),
|
||||||
zap.String("role", typeutil.ProxyRole),
|
zap.String("role", typeutil.ProxyRole),
|
||||||
zap.String("db", queryRequest.DbName),
|
zap.String("db", request.DbName),
|
||||||
zap.String("collection", queryRequest.CollectionName),
|
zap.String("collection", request.CollectionName),
|
||||||
zap.Any("partitions", queryRequest.PartitionNames))
|
zap.Any("partitions", request.PartitionNames))
|
||||||
|
|
||||||
if err := node.sched.dqQueue.Enqueue(qt); err != nil {
|
if err := node.sched.dqQueue.Enqueue(qt); err != nil {
|
||||||
log.Warn(
|
log.Warn(
|
||||||
|
@ -2381,9 +2373,9 @@ func (node *Proxy) Query(ctx context.Context, request *milvuspb.QueryRequest) (*
|
||||||
zap.Error(err),
|
zap.Error(err),
|
||||||
zap.String("traceID", traceID),
|
zap.String("traceID", traceID),
|
||||||
zap.String("role", typeutil.ProxyRole),
|
zap.String("role", typeutil.ProxyRole),
|
||||||
zap.String("db", queryRequest.DbName),
|
zap.String("db", request.DbName),
|
||||||
zap.String("collection", queryRequest.CollectionName),
|
zap.String("collection", request.CollectionName),
|
||||||
zap.Any("partitions", queryRequest.PartitionNames))
|
zap.Any("partitions", request.PartitionNames))
|
||||||
|
|
||||||
return &milvuspb.QueryResults{
|
return &milvuspb.QueryResults{
|
||||||
Status: &commonpb.Status{
|
Status: &commonpb.Status{
|
||||||
|
@ -2400,9 +2392,9 @@ func (node *Proxy) Query(ctx context.Context, request *milvuspb.QueryRequest) (*
|
||||||
zap.Int64("MsgID", qt.ID()),
|
zap.Int64("MsgID", qt.ID()),
|
||||||
zap.Uint64("BeginTs", qt.BeginTs()),
|
zap.Uint64("BeginTs", qt.BeginTs()),
|
||||||
zap.Uint64("EndTs", qt.EndTs()),
|
zap.Uint64("EndTs", qt.EndTs()),
|
||||||
zap.String("db", queryRequest.DbName),
|
zap.String("db", request.DbName),
|
||||||
zap.String("collection", queryRequest.CollectionName),
|
zap.String("collection", request.CollectionName),
|
||||||
zap.Any("partitions", queryRequest.PartitionNames))
|
zap.Any("partitions", request.PartitionNames))
|
||||||
|
|
||||||
if err := qt.WaitToFinish(); err != nil {
|
if err := qt.WaitToFinish(); err != nil {
|
||||||
log.Warn(
|
log.Warn(
|
||||||
|
@ -2413,9 +2405,9 @@ func (node *Proxy) Query(ctx context.Context, request *milvuspb.QueryRequest) (*
|
||||||
zap.Int64("MsgID", qt.ID()),
|
zap.Int64("MsgID", qt.ID()),
|
||||||
zap.Uint64("BeginTs", qt.BeginTs()),
|
zap.Uint64("BeginTs", qt.BeginTs()),
|
||||||
zap.Uint64("EndTs", qt.EndTs()),
|
zap.Uint64("EndTs", qt.EndTs()),
|
||||||
zap.String("db", queryRequest.DbName),
|
zap.String("db", request.DbName),
|
||||||
zap.String("collection", queryRequest.CollectionName),
|
zap.String("collection", request.CollectionName),
|
||||||
zap.Any("partitions", queryRequest.PartitionNames))
|
zap.Any("partitions", request.PartitionNames))
|
||||||
|
|
||||||
return &milvuspb.QueryResults{
|
return &milvuspb.QueryResults{
|
||||||
Status: &commonpb.Status{
|
Status: &commonpb.Status{
|
||||||
|
@ -2432,9 +2424,9 @@ func (node *Proxy) Query(ctx context.Context, request *milvuspb.QueryRequest) (*
|
||||||
zap.Int64("MsgID", qt.ID()),
|
zap.Int64("MsgID", qt.ID()),
|
||||||
zap.Uint64("BeginTs", qt.BeginTs()),
|
zap.Uint64("BeginTs", qt.BeginTs()),
|
||||||
zap.Uint64("EndTs", qt.EndTs()),
|
zap.Uint64("EndTs", qt.EndTs()),
|
||||||
zap.String("db", queryRequest.DbName),
|
zap.String("db", request.DbName),
|
||||||
zap.String("collection", queryRequest.CollectionName),
|
zap.String("collection", request.CollectionName),
|
||||||
zap.Any("partitions", queryRequest.PartitionNames))
|
zap.Any("partitions", request.PartitionNames))
|
||||||
|
|
||||||
return &milvuspb.QueryResults{
|
return &milvuspb.QueryResults{
|
||||||
Status: qt.result.Status,
|
Status: qt.result.Status,
|
||||||
|
|
|
@ -31,6 +31,7 @@ import (
|
||||||
|
|
||||||
"github.com/milvus-io/milvus/internal/util/etcd"
|
"github.com/milvus-io/milvus/internal/util/etcd"
|
||||||
"github.com/milvus-io/milvus/internal/util/sessionutil"
|
"github.com/milvus-io/milvus/internal/util/sessionutil"
|
||||||
|
"github.com/milvus-io/milvus/internal/util/tsoutil"
|
||||||
|
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
|
|
||||||
|
@ -1256,6 +1257,32 @@ func TestProxy(t *testing.T) {
|
||||||
// TODO(dragondriver): compare search result
|
// TODO(dragondriver): compare search result
|
||||||
})
|
})
|
||||||
|
|
||||||
|
wg.Add(1)
|
||||||
|
t.Run("search_travel", func(t *testing.T) {
|
||||||
|
defer wg.Done()
|
||||||
|
past := time.Now().Add(time.Duration(-1*Params.ProxyCfg.RetentionDuration-100) * time.Second)
|
||||||
|
travelTs := tsoutil.ComposeTSByTime(past, 0)
|
||||||
|
req := constructSearchRequest()
|
||||||
|
req.TravelTimestamp = travelTs
|
||||||
|
//resp, err := proxy.Search(ctx, req)
|
||||||
|
res, err := proxy.Search(ctx, req)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.NotEqual(t, commonpb.ErrorCode_Success, res.Status.ErrorCode)
|
||||||
|
})
|
||||||
|
|
||||||
|
wg.Add(1)
|
||||||
|
t.Run("search_travel_succ", func(t *testing.T) {
|
||||||
|
defer wg.Done()
|
||||||
|
past := time.Now().Add(time.Duration(-1*Params.ProxyCfg.RetentionDuration+100) * time.Second)
|
||||||
|
travelTs := tsoutil.ComposeTSByTime(past, 0)
|
||||||
|
req := constructSearchRequest()
|
||||||
|
req.TravelTimestamp = travelTs
|
||||||
|
//resp, err := proxy.Search(ctx, req)
|
||||||
|
res, err := proxy.Search(ctx, req)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, commonpb.ErrorCode_Success, res.Status.ErrorCode)
|
||||||
|
})
|
||||||
|
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
t.Run("query", func(t *testing.T) {
|
t.Run("query", func(t *testing.T) {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
|
@ -1275,6 +1302,46 @@ func TestProxy(t *testing.T) {
|
||||||
// assert.Equal(t, commonpb.ErrorCode_Success, resp.Status.ErrorCode)
|
// assert.Equal(t, commonpb.ErrorCode_Success, resp.Status.ErrorCode)
|
||||||
// TODO(dragondriver): compare query result
|
// TODO(dragondriver): compare query result
|
||||||
})
|
})
|
||||||
|
|
||||||
|
wg.Add(1)
|
||||||
|
t.Run("query_travel", func(t *testing.T) {
|
||||||
|
defer wg.Done()
|
||||||
|
past := time.Now().Add(time.Duration(-1*Params.ProxyCfg.RetentionDuration-100) * time.Second)
|
||||||
|
travelTs := tsoutil.ComposeTSByTime(past, 0)
|
||||||
|
queryReq := &milvuspb.QueryRequest{
|
||||||
|
Base: nil,
|
||||||
|
DbName: dbName,
|
||||||
|
CollectionName: collectionName,
|
||||||
|
Expr: expr,
|
||||||
|
OutputFields: nil,
|
||||||
|
PartitionNames: nil,
|
||||||
|
TravelTimestamp: travelTs,
|
||||||
|
GuaranteeTimestamp: 0,
|
||||||
|
}
|
||||||
|
res, err := proxy.Query(ctx, queryReq)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.NotEqual(t, commonpb.ErrorCode_Success, res.Status.ErrorCode)
|
||||||
|
})
|
||||||
|
|
||||||
|
wg.Add(1)
|
||||||
|
t.Run("query_travel_succ", func(t *testing.T) {
|
||||||
|
defer wg.Done()
|
||||||
|
past := time.Now().Add(time.Duration(-1*Params.ProxyCfg.RetentionDuration+100) * time.Second)
|
||||||
|
travelTs := tsoutil.ComposeTSByTime(past, 0)
|
||||||
|
queryReq := &milvuspb.QueryRequest{
|
||||||
|
Base: nil,
|
||||||
|
DbName: dbName,
|
||||||
|
CollectionName: collectionName,
|
||||||
|
Expr: expr,
|
||||||
|
OutputFields: nil,
|
||||||
|
PartitionNames: nil,
|
||||||
|
TravelTimestamp: travelTs,
|
||||||
|
GuaranteeTimestamp: 0,
|
||||||
|
}
|
||||||
|
res, err := proxy.Query(ctx, queryReq)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, commonpb.ErrorCode_EmptyCollection, res.Status.ErrorCode)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
|
|
|
@ -28,6 +28,7 @@ import (
|
||||||
"sort"
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
"github.com/golang/protobuf/proto"
|
"github.com/golang/protobuf/proto"
|
||||||
|
@ -1577,6 +1578,12 @@ func (st *searchTask) PreExecute(ctx context.Context) error {
|
||||||
travelTimestamp := st.query.TravelTimestamp
|
travelTimestamp := st.query.TravelTimestamp
|
||||||
if travelTimestamp == 0 {
|
if travelTimestamp == 0 {
|
||||||
travelTimestamp = st.BeginTs()
|
travelTimestamp = st.BeginTs()
|
||||||
|
} else {
|
||||||
|
durationSeconds := tsoutil.CalculateDuration(st.BeginTs(), travelTimestamp) / 1000
|
||||||
|
if durationSeconds > Params.ProxyCfg.RetentionDuration {
|
||||||
|
duration := time.Second * time.Duration(durationSeconds)
|
||||||
|
return fmt.Errorf("only support to travel back to %s so far", duration.String())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
guaranteeTimestamp := st.query.GuaranteeTimestamp
|
guaranteeTimestamp := st.query.GuaranteeTimestamp
|
||||||
if guaranteeTimestamp == 0 {
|
if guaranteeTimestamp == 0 {
|
||||||
|
@ -2186,10 +2193,15 @@ func (qt *queryTask) PreExecute(ctx context.Context) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
travelTimestamp := qt.query.TravelTimestamp
|
travelTimestamp := qt.query.TravelTimestamp
|
||||||
if travelTimestamp == 0 {
|
if travelTimestamp == 0 {
|
||||||
travelTimestamp = qt.BeginTs()
|
travelTimestamp = qt.BeginTs()
|
||||||
|
} else {
|
||||||
|
durationSeconds := tsoutil.CalculateDuration(qt.BeginTs(), travelTimestamp) / 1000
|
||||||
|
if durationSeconds > Params.ProxyCfg.RetentionDuration {
|
||||||
|
duration := time.Second * time.Duration(durationSeconds)
|
||||||
|
return fmt.Errorf("only support to travel back to %s so far", duration.String())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
guaranteeTimestamp := qt.query.GuaranteeTimestamp
|
guaranteeTimestamp := qt.query.GuaranteeTimestamp
|
||||||
if guaranteeTimestamp == 0 {
|
if guaranteeTimestamp == 0 {
|
||||||
|
|
|
@ -42,6 +42,9 @@ const (
|
||||||
|
|
||||||
// SuggestPulsarMaxMessageSize defines the maximum size of Pulsar message.
|
// SuggestPulsarMaxMessageSize defines the maximum size of Pulsar message.
|
||||||
SuggestPulsarMaxMessageSize = 5 * 1024 * 1024
|
SuggestPulsarMaxMessageSize = 5 * 1024 * 1024
|
||||||
|
|
||||||
|
// DefaultRetentionDuration defines the default duration for retention which is 5 days in seconds.
|
||||||
|
DefaultRetentionDuration = 3600 * 24 * 5
|
||||||
)
|
)
|
||||||
|
|
||||||
// GlobalParamTable is a derived struct of BaseParamTable.
|
// GlobalParamTable is a derived struct of BaseParamTable.
|
||||||
|
@ -489,6 +492,8 @@ type proxyConfig struct {
|
||||||
|
|
||||||
PulsarMaxMessageSize int
|
PulsarMaxMessageSize int
|
||||||
|
|
||||||
|
RetentionDuration int64
|
||||||
|
|
||||||
CreatedTime time.Time
|
CreatedTime time.Time
|
||||||
UpdatedTime time.Time
|
UpdatedTime time.Time
|
||||||
}
|
}
|
||||||
|
@ -518,6 +523,7 @@ func (p *proxyConfig) init(bp *BaseParamTable) {
|
||||||
p.initMaxTaskNum()
|
p.initMaxTaskNum()
|
||||||
p.initBufFlagExpireTime()
|
p.initBufFlagExpireTime()
|
||||||
p.initBufFlagCleanupInterval()
|
p.initBufFlagCleanupInterval()
|
||||||
|
p.initRetentionDuration()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Refresh is called after session init
|
// Refresh is called after session init
|
||||||
|
@ -668,6 +674,10 @@ func (p *proxyConfig) initBufFlagCleanupInterval() {
|
||||||
p.BufFlagCleanupInterval = time.Duration(interval) * time.Second
|
p.BufFlagCleanupInterval = time.Duration(interval) * time.Second
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *proxyConfig) initRetentionDuration() {
|
||||||
|
p.RetentionDuration = p.BaseParams.ParseInt64WithDefault("common.retentionDuration", DefaultRetentionDuration)
|
||||||
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// --- querycoord ---
|
// --- querycoord ---
|
||||||
type queryCoordConfig struct {
|
type queryCoordConfig struct {
|
||||||
|
@ -1298,8 +1308,8 @@ type dataCoordConfig struct {
|
||||||
EnableCompaction bool
|
EnableCompaction bool
|
||||||
EnableGarbageCollection bool
|
EnableGarbageCollection bool
|
||||||
|
|
||||||
CompactionRetentionDuration int64
|
RetentionDuration int64
|
||||||
EnableAutoCompaction bool
|
EnableAutoCompaction bool
|
||||||
|
|
||||||
// Garbage Collection
|
// Garbage Collection
|
||||||
GCInterval time.Duration
|
GCInterval time.Duration
|
||||||
|
@ -1342,7 +1352,7 @@ func (p *dataCoordConfig) init(bp *BaseParamTable) {
|
||||||
p.initMinioBucketName()
|
p.initMinioBucketName()
|
||||||
p.initMinioRootPath()
|
p.initMinioRootPath()
|
||||||
|
|
||||||
p.initCompactionRetentionDuration()
|
p.initRetentionDuration()
|
||||||
p.initEnableAutoCompaction()
|
p.initEnableAutoCompaction()
|
||||||
|
|
||||||
p.initEnableGarbageCollection()
|
p.initEnableGarbageCollection()
|
||||||
|
@ -1556,8 +1566,8 @@ func (p *dataCoordConfig) initMinioRootPath() {
|
||||||
p.MinioRootPath = rootPath
|
p.MinioRootPath = rootPath
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *dataCoordConfig) initCompactionRetentionDuration() {
|
func (p *dataCoordConfig) initRetentionDuration() {
|
||||||
p.CompactionRetentionDuration = p.BaseParams.ParseInt64WithDefault("dataCoord.compaction.retentionDuration", 432000)
|
p.RetentionDuration = p.BaseParams.ParseInt64WithDefault("common.retentionDuration", DefaultRetentionDuration)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *dataCoordConfig) initEnableAutoCompaction() {
|
func (p *dataCoordConfig) initEnableAutoCompaction() {
|
||||||
|
|
|
@ -55,6 +55,13 @@ func ParseHybridTs(ts uint64) (int64, int64) {
|
||||||
return int64(physical), int64(logical)
|
return int64(physical), int64(logical)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CalculateDuration returns the number of milliseconds obtained by subtracting ts2 from ts1.
|
||||||
|
func CalculateDuration(ts1, ts2 typeutil.Timestamp) int64 {
|
||||||
|
p1, _ := ParseHybridTs(ts1)
|
||||||
|
p2, _ := ParseHybridTs(ts2)
|
||||||
|
return p1 - p2
|
||||||
|
}
|
||||||
|
|
||||||
// Mod24H parses the ts to millisecond in one day
|
// Mod24H parses the ts to millisecond in one day
|
||||||
func Mod24H(ts uint64) uint64 {
|
func Mod24H(ts uint64) uint64 {
|
||||||
logical := ts & logicalBitsMask
|
logical := ts & logicalBitsMask
|
||||||
|
|
|
@ -49,3 +49,12 @@ func Test_Tso(t *testing.T) {
|
||||||
assert.Equal(t, typeutil.ZeroTimestamp, l)
|
assert.Equal(t, typeutil.ZeroTimestamp, l)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCalculateDuration(t *testing.T) {
|
||||||
|
now := time.Now()
|
||||||
|
ts1 := ComposeTSByTime(now, 0)
|
||||||
|
durationInMilliSecs := int64(20 * 1000)
|
||||||
|
ts2 := ComposeTSByTime(now.Add(time.Duration(durationInMilliSecs)*time.Millisecond), 0)
|
||||||
|
diff := CalculateDuration(ts2, ts1)
|
||||||
|
assert.Equal(t, durationInMilliSecs, diff)
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue