mirror of
https://gitee.com/milvus-io/milvus.git
synced 2024-12-02 03:48:37 +08:00
fix: streaming service related fix patch (#34696)
issue: #33285 - add idAlloc interface - fix binary unsafe bug for message - fix service discovery lost when repeated address with different server id --------- Signed-off-by: chyezh <chyezh@outlook.com>
This commit is contained in:
parent
fbc10ac695
commit
cc8f7aa110
@ -2,5 +2,5 @@ package streamingcoord
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
MetaPrefix = "streamingcoord-meta"
|
MetaPrefix = "streamingcoord-meta"
|
||||||
PChannelMeta = MetaPrefix + "/pchannel-meta"
|
PChannelMeta = MetaPrefix + "/pchannel"
|
||||||
)
|
)
|
||||||
|
@ -13,7 +13,7 @@ import "google/protobuf/empty.proto";
|
|||||||
|
|
||||||
// MessageID is the unique identifier of a message.
|
// MessageID is the unique identifier of a message.
|
||||||
message MessageID {
|
message MessageID {
|
||||||
bytes id = 1;
|
string id = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Message is the basic unit of communication between publisher and consumer.
|
// Message is the basic unit of communication between publisher and consumer.
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
package streamingpb
|
package streamingpb
|
||||||
|
|
||||||
const (
|
const (
|
||||||
ServiceMethodPrefix = "/milvus.proto.log"
|
ServiceMethodPrefix = "/milvus.proto.streaming"
|
||||||
)
|
)
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
package timestamp
|
package idalloc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
@ -28,15 +28,28 @@ const batchAllocateSize = 1000
|
|||||||
|
|
||||||
var _ Allocator = (*allocatorImpl)(nil)
|
var _ Allocator = (*allocatorImpl)(nil)
|
||||||
|
|
||||||
// NewAllocator creates a new allocator.
|
// NewTSOAllocator creates a new allocator.
|
||||||
func NewAllocator(rc types.RootCoordClient) Allocator {
|
func NewTSOAllocator(rc types.RootCoordClient) Allocator {
|
||||||
return &allocatorImpl{
|
return &allocatorImpl{
|
||||||
mu: sync.Mutex{},
|
mu: sync.Mutex{},
|
||||||
remoteAllocator: newRemoteAllocator(rc),
|
remoteAllocator: newTSOAllocator(rc),
|
||||||
localAllocator: newLocalAllocator(),
|
localAllocator: newLocalAllocator(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewIDAllocator creates a new allocator.
|
||||||
|
func NewIDAllocator(rc types.RootCoordClient) Allocator {
|
||||||
|
return &allocatorImpl{
|
||||||
|
mu: sync.Mutex{},
|
||||||
|
remoteAllocator: newIDAllocator(rc),
|
||||||
|
localAllocator: newLocalAllocator(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type remoteBatchAllocator interface {
|
||||||
|
batchAllocate(ctx context.Context, count uint32) (uint64, int, error)
|
||||||
|
}
|
||||||
|
|
||||||
type Allocator interface {
|
type Allocator interface {
|
||||||
// Allocate allocates a timestamp.
|
// Allocate allocates a timestamp.
|
||||||
Allocate(ctx context.Context) (uint64, error)
|
Allocate(ctx context.Context) (uint64, error)
|
||||||
@ -48,7 +61,7 @@ type Allocator interface {
|
|||||||
|
|
||||||
type allocatorImpl struct {
|
type allocatorImpl struct {
|
||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
remoteAllocator *remoteAllocator
|
remoteAllocator remoteBatchAllocator
|
||||||
localAllocator *localAllocator
|
localAllocator *localAllocator
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,7 +90,7 @@ func (ta *allocatorImpl) Sync() {
|
|||||||
// allocateRemote allocates timestamp from remote root coordinator.
|
// allocateRemote allocates timestamp from remote root coordinator.
|
||||||
func (ta *allocatorImpl) allocateRemote(ctx context.Context) (uint64, error) {
|
func (ta *allocatorImpl) allocateRemote(ctx context.Context) (uint64, error) {
|
||||||
// Update local allocator from remote.
|
// Update local allocator from remote.
|
||||||
start, count, err := ta.remoteAllocator.allocate(ctx, batchAllocateSize)
|
start, count, err := ta.remoteAllocator.batchAllocate(ctx, batchAllocateSize)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package timestamp
|
package idalloc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
@ -19,7 +19,7 @@ func TestTimestampAllocator(t *testing.T) {
|
|||||||
paramtable.SetNodeID(1)
|
paramtable.SetNodeID(1)
|
||||||
|
|
||||||
client := NewMockRootCoordClient(t)
|
client := NewMockRootCoordClient(t)
|
||||||
allocator := NewAllocator(client)
|
allocator := NewTSOAllocator(client)
|
||||||
|
|
||||||
for i := 0; i < 5000; i++ {
|
for i := 0; i < 5000; i++ {
|
||||||
ts, err := allocator.Allocate(context.Background())
|
ts, err := allocator.Allocate(context.Background())
|
||||||
@ -46,7 +46,7 @@ func TestTimestampAllocator(t *testing.T) {
|
|||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
allocator = NewAllocator(client)
|
allocator = NewTSOAllocator(client)
|
||||||
_, err := allocator.Allocate(context.Background())
|
_, err := allocator.Allocate(context.Background())
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package timestamp
|
package idalloc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
@ -54,22 +54,22 @@ func (a *localAllocator) exhausted() {
|
|||||||
a.nextStartID = a.endStartID
|
a.nextStartID = a.endStartID
|
||||||
}
|
}
|
||||||
|
|
||||||
// remoteAllocator allocate timestamp from remote root coordinator.
|
// tsoAllocator allocate timestamp from remote root coordinator.
|
||||||
type remoteAllocator struct {
|
type tsoAllocator struct {
|
||||||
rc types.RootCoordClient
|
rc types.RootCoordClient
|
||||||
nodeID int64
|
nodeID int64
|
||||||
}
|
}
|
||||||
|
|
||||||
// newRemoteAllocator creates a new remote allocator.
|
// newTSOAllocator creates a new remote allocator.
|
||||||
func newRemoteAllocator(rc types.RootCoordClient) *remoteAllocator {
|
func newTSOAllocator(rc types.RootCoordClient) *tsoAllocator {
|
||||||
a := &remoteAllocator{
|
a := &tsoAllocator{
|
||||||
nodeID: paramtable.GetNodeID(),
|
nodeID: paramtable.GetNodeID(),
|
||||||
rc: rc,
|
rc: rc,
|
||||||
}
|
}
|
||||||
return a
|
return a
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ta *remoteAllocator) allocate(ctx context.Context, count uint32) (uint64, int, error) {
|
func (ta *tsoAllocator) batchAllocate(ctx context.Context, count uint32) (uint64, int, error) {
|
||||||
ctx, cancel := context.WithTimeout(ctx, 10*time.Second)
|
ctx, cancel := context.WithTimeout(ctx, 10*time.Second)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
req := &rootcoordpb.AllocTimestampRequest{
|
req := &rootcoordpb.AllocTimestampRequest{
|
||||||
@ -93,3 +93,46 @@ func (ta *remoteAllocator) allocate(ctx context.Context, count uint32) (uint64,
|
|||||||
}
|
}
|
||||||
return resp.GetTimestamp(), int(resp.GetCount()), nil
|
return resp.GetTimestamp(), int(resp.GetCount()), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// idAllocator allocate timestamp from remote root coordinator.
|
||||||
|
type idAllocator struct {
|
||||||
|
rc types.RootCoordClient
|
||||||
|
nodeID int64
|
||||||
|
}
|
||||||
|
|
||||||
|
// newIDAllocator creates a new remote allocator.
|
||||||
|
func newIDAllocator(rc types.RootCoordClient) *idAllocator {
|
||||||
|
a := &idAllocator{
|
||||||
|
nodeID: paramtable.GetNodeID(),
|
||||||
|
rc: rc,
|
||||||
|
}
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ta *idAllocator) batchAllocate(ctx context.Context, count uint32) (uint64, int, error) {
|
||||||
|
ctx, cancel := context.WithTimeout(ctx, 10*time.Second)
|
||||||
|
defer cancel()
|
||||||
|
req := &rootcoordpb.AllocIDRequest{
|
||||||
|
Base: commonpbutil.NewMsgBase(
|
||||||
|
commonpbutil.WithMsgType(commonpb.MsgType_RequestID),
|
||||||
|
commonpbutil.WithMsgID(0),
|
||||||
|
commonpbutil.WithSourceID(ta.nodeID),
|
||||||
|
),
|
||||||
|
Count: count,
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := ta.rc.AllocID(ctx, req)
|
||||||
|
if err != nil {
|
||||||
|
return 0, 0, fmt.Errorf("AllocID Failed:%w", err)
|
||||||
|
}
|
||||||
|
if resp.GetStatus().GetErrorCode() != commonpb.ErrorCode_Success {
|
||||||
|
return 0, 0, fmt.Errorf("AllocID Failed:%s", resp.GetStatus().GetReason())
|
||||||
|
}
|
||||||
|
if resp == nil {
|
||||||
|
return 0, 0, fmt.Errorf("empty AllocID")
|
||||||
|
}
|
||||||
|
if resp.GetID() < 0 {
|
||||||
|
panic("get unexpected negative id")
|
||||||
|
}
|
||||||
|
return uint64(resp.GetID()), int(resp.GetCount()), nil
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package timestamp
|
package idalloc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
@ -58,14 +58,14 @@ func TestLocalAllocator(t *testing.T) {
|
|||||||
assert.Zero(t, ts)
|
assert.Zero(t, ts)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRemoteAllocator(t *testing.T) {
|
func TestRemoteTSOAllocator(t *testing.T) {
|
||||||
paramtable.Init()
|
paramtable.Init()
|
||||||
paramtable.SetNodeID(1)
|
paramtable.SetNodeID(1)
|
||||||
|
|
||||||
client := NewMockRootCoordClient(t)
|
client := NewMockRootCoordClient(t)
|
||||||
|
|
||||||
allocator := newRemoteAllocator(client)
|
allocator := newTSOAllocator(client)
|
||||||
ts, count, err := allocator.allocate(context.Background(), 100)
|
ts, count, err := allocator.batchAllocate(context.Background(), 100)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.NotZero(t, ts)
|
assert.NotZero(t, ts)
|
||||||
assert.Equal(t, count, 100)
|
assert.Equal(t, count, 100)
|
||||||
@ -77,8 +77,8 @@ func TestRemoteAllocator(t *testing.T) {
|
|||||||
return nil, errors.New("test")
|
return nil, errors.New("test")
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
allocator = newRemoteAllocator(client)
|
allocator = newTSOAllocator(client)
|
||||||
_, _, err = allocator.allocate(context.Background(), 100)
|
_, _, err = allocator.batchAllocate(context.Background(), 100)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
|
|
||||||
client.EXPECT().AllocTimestamp(mock.Anything, mock.Anything).Unset()
|
client.EXPECT().AllocTimestamp(mock.Anything, mock.Anything).Unset()
|
||||||
@ -91,7 +91,45 @@ func TestRemoteAllocator(t *testing.T) {
|
|||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
allocator = newRemoteAllocator(client)
|
allocator = newTSOAllocator(client)
|
||||||
_, _, err = allocator.allocate(context.Background(), 100)
|
_, _, err = allocator.batchAllocate(context.Background(), 100)
|
||||||
|
assert.Error(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRemoteIDAllocator(t *testing.T) {
|
||||||
|
paramtable.Init()
|
||||||
|
paramtable.SetNodeID(1)
|
||||||
|
|
||||||
|
client := NewMockRootCoordClient(t)
|
||||||
|
|
||||||
|
allocator := newIDAllocator(client)
|
||||||
|
ts, count, err := allocator.batchAllocate(context.Background(), 100)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.NotZero(t, ts)
|
||||||
|
assert.Equal(t, count, 100)
|
||||||
|
|
||||||
|
// Test error.
|
||||||
|
client = mocks.NewMockRootCoordClient(t)
|
||||||
|
client.EXPECT().AllocID(mock.Anything, mock.Anything).RunAndReturn(
|
||||||
|
func(ctx context.Context, atr *rootcoordpb.AllocIDRequest, co ...grpc.CallOption) (*rootcoordpb.AllocIDResponse, error) {
|
||||||
|
return nil, errors.New("test")
|
||||||
|
},
|
||||||
|
)
|
||||||
|
allocator = newIDAllocator(client)
|
||||||
|
_, _, err = allocator.batchAllocate(context.Background(), 100)
|
||||||
|
assert.Error(t, err)
|
||||||
|
|
||||||
|
client.EXPECT().AllocID(mock.Anything, mock.Anything).Unset()
|
||||||
|
client.EXPECT().AllocID(mock.Anything, mock.Anything).RunAndReturn(
|
||||||
|
func(ctx context.Context, atr *rootcoordpb.AllocIDRequest, co ...grpc.CallOption) (*rootcoordpb.AllocIDResponse, error) {
|
||||||
|
return &rootcoordpb.AllocIDResponse{
|
||||||
|
Status: &commonpb.Status{
|
||||||
|
ErrorCode: commonpb.ErrorCode_ForceDeny,
|
||||||
|
},
|
||||||
|
}, nil
|
||||||
|
},
|
||||||
|
)
|
||||||
|
allocator = newIDAllocator(client)
|
||||||
|
_, _, err = allocator.batchAllocate(context.Background(), 100)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
}
|
}
|
@ -1,7 +1,7 @@
|
|||||||
//go:build test
|
//go:build test
|
||||||
// +build test
|
// +build test
|
||||||
|
|
||||||
package timestamp
|
package idalloc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
@ -34,6 +34,21 @@ func NewMockRootCoordClient(t *testing.T) *mocks.MockRootCoordClient {
|
|||||||
Count: atr.Count,
|
Count: atr.Count,
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
)
|
).Maybe()
|
||||||
|
client.EXPECT().AllocID(mock.Anything, mock.Anything).RunAndReturn(
|
||||||
|
func(ctx context.Context, atr *rootcoordpb.AllocIDRequest, co ...grpc.CallOption) (*rootcoordpb.AllocIDResponse, error) {
|
||||||
|
if atr.Count > 1000 {
|
||||||
|
panic(fmt.Sprintf("count %d is too large", atr.Count))
|
||||||
|
}
|
||||||
|
c := counter.Add(uint64(atr.Count))
|
||||||
|
return &rootcoordpb.AllocIDResponse{
|
||||||
|
Status: &commonpb.Status{
|
||||||
|
ErrorCode: commonpb.ErrorCode_Success,
|
||||||
|
},
|
||||||
|
ID: int64(c - uint64(atr.Count)),
|
||||||
|
Count: atr.Count,
|
||||||
|
}, nil
|
||||||
|
},
|
||||||
|
).Maybe()
|
||||||
return client
|
return client
|
||||||
}
|
}
|
@ -5,7 +5,7 @@ import (
|
|||||||
|
|
||||||
clientv3 "go.etcd.io/etcd/client/v3"
|
clientv3 "go.etcd.io/etcd/client/v3"
|
||||||
|
|
||||||
"github.com/milvus-io/milvus/internal/streamingnode/server/resource/timestamp"
|
"github.com/milvus-io/milvus/internal/streamingnode/server/resource/idalloc"
|
||||||
"github.com/milvus-io/milvus/internal/types"
|
"github.com/milvus-io/milvus/internal/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -35,9 +35,10 @@ func Init(opts ...optResourceInit) {
|
|||||||
for _, opt := range opts {
|
for _, opt := range opts {
|
||||||
opt(r)
|
opt(r)
|
||||||
}
|
}
|
||||||
r.timestampAllocator = timestamp.NewAllocator(r.rootCoordClient)
|
r.timestampAllocator = idalloc.NewTSOAllocator(r.rootCoordClient)
|
||||||
|
r.idAllocator = idalloc.NewIDAllocator(r.rootCoordClient)
|
||||||
|
|
||||||
assertNotNil(r.TimestampAllocator())
|
assertNotNil(r.TSOAllocator())
|
||||||
assertNotNil(r.ETCD())
|
assertNotNil(r.ETCD())
|
||||||
assertNotNil(r.RootCoordClient())
|
assertNotNil(r.RootCoordClient())
|
||||||
}
|
}
|
||||||
@ -50,16 +51,22 @@ func Resource() *resourceImpl {
|
|||||||
// resourceImpl is a basic resource dependency for streamingnode server.
|
// resourceImpl is a basic resource dependency for streamingnode server.
|
||||||
// All utility on it is concurrent-safe and singleton.
|
// All utility on it is concurrent-safe and singleton.
|
||||||
type resourceImpl struct {
|
type resourceImpl struct {
|
||||||
timestampAllocator timestamp.Allocator
|
timestampAllocator idalloc.Allocator
|
||||||
|
idAllocator idalloc.Allocator
|
||||||
etcdClient *clientv3.Client
|
etcdClient *clientv3.Client
|
||||||
rootCoordClient types.RootCoordClient
|
rootCoordClient types.RootCoordClient
|
||||||
}
|
}
|
||||||
|
|
||||||
// TimestampAllocator returns the timestamp allocator to allocate timestamp.
|
// TSOAllocator returns the timestamp allocator to allocate timestamp.
|
||||||
func (r *resourceImpl) TimestampAllocator() timestamp.Allocator {
|
func (r *resourceImpl) TSOAllocator() idalloc.Allocator {
|
||||||
return r.timestampAllocator
|
return r.timestampAllocator
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IDAllocator returns the id allocator to allocate id.
|
||||||
|
func (r *resourceImpl) IDAllocator() idalloc.Allocator {
|
||||||
|
return r.idAllocator
|
||||||
|
}
|
||||||
|
|
||||||
// ETCD returns the etcd client.
|
// ETCD returns the etcd client.
|
||||||
func (r *resourceImpl) ETCD() *clientv3.Client {
|
func (r *resourceImpl) ETCD() *clientv3.Client {
|
||||||
return r.etcdClient
|
return r.etcdClient
|
||||||
|
@ -21,7 +21,7 @@ func TestInit(t *testing.T) {
|
|||||||
})
|
})
|
||||||
Init(OptETCD(&clientv3.Client{}), OptRootCoordClient(mocks.NewMockRootCoordClient(t)))
|
Init(OptETCD(&clientv3.Client{}), OptRootCoordClient(mocks.NewMockRootCoordClient(t)))
|
||||||
|
|
||||||
assert.NotNil(t, Resource().TimestampAllocator())
|
assert.NotNil(t, Resource().TSOAllocator())
|
||||||
assert.NotNil(t, Resource().ETCD())
|
assert.NotNil(t, Resource().ETCD())
|
||||||
assert.NotNil(t, Resource().RootCoordClient())
|
assert.NotNil(t, Resource().RootCoordClient())
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
package resource
|
package resource
|
||||||
|
|
||||||
import "github.com/milvus-io/milvus/internal/streamingnode/server/resource/timestamp"
|
import "github.com/milvus-io/milvus/internal/streamingnode/server/resource/idalloc"
|
||||||
|
|
||||||
// InitForTest initializes the singleton of resources for test.
|
// InitForTest initializes the singleton of resources for test.
|
||||||
func InitForTest(opts ...optResourceInit) {
|
func InitForTest(opts ...optResourceInit) {
|
||||||
@ -12,6 +12,6 @@ func InitForTest(opts ...optResourceInit) {
|
|||||||
opt(r)
|
opt(r)
|
||||||
}
|
}
|
||||||
if r.rootCoordClient != nil {
|
if r.rootCoordClient != nil {
|
||||||
r.timestampAllocator = timestamp.NewAllocator(r.rootCoordClient)
|
r.timestampAllocator = idalloc.NewTSOAllocator(r.rootCoordClient)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,9 +31,7 @@ func CreateConsumeServer(walManager walmanager.Manager, streamServer streamingpb
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, status.NewInvaildArgument("create consumer request is required")
|
return nil, status.NewInvaildArgument("create consumer request is required")
|
||||||
}
|
}
|
||||||
|
l, err := walManager.GetAvailableWAL(typeconverter.NewPChannelInfoFromProto(createReq.GetPchannel()))
|
||||||
pchanelInfo := typeconverter.NewPChannelInfoFromProto(createReq.Pchannel)
|
|
||||||
l, err := walManager.GetAvailableWAL(pchanelInfo)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -19,12 +19,10 @@ func (p *produceGrpcServerHelper) SendProduceMessage(resp *streamingpb.ProduceMe
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SendCreated sends the create response to client.
|
// SendCreated sends the create response to client.
|
||||||
func (p *produceGrpcServerHelper) SendCreated(walName string) error {
|
func (p *produceGrpcServerHelper) SendCreated(resp *streamingpb.CreateProducerResponse) error {
|
||||||
return p.Send(&streamingpb.ProduceResponse{
|
return p.Send(&streamingpb.ProduceResponse{
|
||||||
Response: &streamingpb.ProduceResponse_Create{
|
Response: &streamingpb.ProduceResponse_Create{
|
||||||
Create: &streamingpb.CreateProducerResponse{
|
Create: resp,
|
||||||
WalName: walName,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,7 @@ func CreateProduceServer(walManager walmanager.Manager, streamServer streamingpb
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, status.NewInvaildArgument("create producer request is required")
|
return nil, status.NewInvaildArgument("create producer request is required")
|
||||||
}
|
}
|
||||||
l, err := walManager.GetAvailableWAL(typeconverter.NewPChannelInfoFromProto(createReq.Pchannel))
|
l, err := walManager.GetAvailableWAL(typeconverter.NewPChannelInfoFromProto(createReq.GetPchannel()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -41,7 +41,9 @@ func CreateProduceServer(walManager walmanager.Manager, streamServer streamingpb
|
|||||||
produceServer := &produceGrpcServerHelper{
|
produceServer := &produceGrpcServerHelper{
|
||||||
StreamingNodeHandlerService_ProduceServer: streamServer,
|
StreamingNodeHandlerService_ProduceServer: streamServer,
|
||||||
}
|
}
|
||||||
if err := produceServer.SendCreated(l.WALName()); err != nil {
|
if err := produceServer.SendCreated(&streamingpb.CreateProducerResponse{
|
||||||
|
WalName: l.WALName(),
|
||||||
|
}); err != nil {
|
||||||
return nil, errors.Wrap(err, "at send created")
|
return nil, errors.Wrap(err, "at send created")
|
||||||
}
|
}
|
||||||
return &ProduceServer{
|
return &ProduceServer{
|
||||||
@ -170,13 +172,13 @@ func (p *ProduceServer) handleProduce(req *streamingpb.ProduceMessageRequest) {
|
|||||||
func (p *ProduceServer) validateMessage(msg message.MutableMessage) error {
|
func (p *ProduceServer) validateMessage(msg message.MutableMessage) error {
|
||||||
// validate the msg.
|
// validate the msg.
|
||||||
if !msg.Version().GT(message.VersionOld) {
|
if !msg.Version().GT(message.VersionOld) {
|
||||||
return status.NewInner("unsupported message version")
|
return status.NewInvaildArgument("unsupported message version")
|
||||||
}
|
}
|
||||||
if !msg.MessageType().Valid() {
|
if !msg.MessageType().Valid() {
|
||||||
return status.NewInner("unsupported message type")
|
return status.NewInvaildArgument("unsupported message type")
|
||||||
}
|
}
|
||||||
if msg.Payload() == nil {
|
if msg.Payload() == nil {
|
||||||
return status.NewInner("empty payload for message")
|
return status.NewInvaildArgument("empty payload for message")
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package producer
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"io"
|
"io"
|
||||||
|
"strconv"
|
||||||
"sync"
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
@ -56,6 +57,7 @@ func TestCreateProduceServer(t *testing.T) {
|
|||||||
l := mock_wal.NewMockWAL(t)
|
l := mock_wal.NewMockWAL(t)
|
||||||
l.EXPECT().WALName().Return("test")
|
l.EXPECT().WALName().Return("test")
|
||||||
manager.ExpectedCalls = nil
|
manager.ExpectedCalls = nil
|
||||||
|
l.EXPECT().WALName().Return("test")
|
||||||
manager.EXPECT().GetAvailableWAL(types.PChannelInfo{Name: "test", Term: 1}).Return(l, nil)
|
manager.EXPECT().GetAvailableWAL(types.PChannelInfo{Name: "test", Term: 1}).Return(l, nil)
|
||||||
grpcProduceServer.EXPECT().Send(mock.Anything).Return(errors.New("send created failed"))
|
grpcProduceServer.EXPECT().Send(mock.Anything).Return(errors.New("send created failed"))
|
||||||
assertCreateProduceServerFail(t, manager, grpcProduceServer)
|
assertCreateProduceServerFail(t, manager, grpcProduceServer)
|
||||||
@ -214,7 +216,7 @@ func TestProduceServerRecvArm(t *testing.T) {
|
|||||||
Payload: []byte("test"),
|
Payload: []byte("test"),
|
||||||
Properties: map[string]string{
|
Properties: map[string]string{
|
||||||
"_v": "1",
|
"_v": "1",
|
||||||
"_t": "1",
|
"_t": strconv.FormatInt(int64(message.MessageTypeTimeTick), 10),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -100,7 +100,7 @@ func (w *walAdaptorImpl) AppendAsync(ctx context.Context, msg message.MutableMes
|
|||||||
_ = w.appendExecutionPool.Submit(func() (struct{}, error) {
|
_ = w.appendExecutionPool.Submit(func() (struct{}, error) {
|
||||||
defer w.lifetime.Done()
|
defer w.lifetime.Done()
|
||||||
|
|
||||||
msgID, err := w.inner.Append(ctx, msg)
|
msgID, err := w.Append(ctx, msg)
|
||||||
cb(msgID, err)
|
cb(msgID, err)
|
||||||
return struct{}{}, nil
|
return struct{}{}, nil
|
||||||
})
|
})
|
||||||
|
@ -16,7 +16,7 @@ import (
|
|||||||
|
|
||||||
"github.com/milvus-io/milvus-proto/go-api/v2/commonpb"
|
"github.com/milvus-io/milvus-proto/go-api/v2/commonpb"
|
||||||
"github.com/milvus-io/milvus/internal/streamingnode/server/resource"
|
"github.com/milvus-io/milvus/internal/streamingnode/server/resource"
|
||||||
"github.com/milvus-io/milvus/internal/streamingnode/server/resource/timestamp"
|
"github.com/milvus-io/milvus/internal/streamingnode/server/resource/idalloc"
|
||||||
"github.com/milvus-io/milvus/internal/streamingnode/server/wal"
|
"github.com/milvus-io/milvus/internal/streamingnode/server/wal"
|
||||||
"github.com/milvus-io/milvus/internal/streamingnode/server/wal/registry"
|
"github.com/milvus-io/milvus/internal/streamingnode/server/wal/registry"
|
||||||
"github.com/milvus-io/milvus/pkg/streaming/util/message"
|
"github.com/milvus-io/milvus/pkg/streaming/util/message"
|
||||||
@ -32,7 +32,7 @@ type walTestFramework struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestWAL(t *testing.T) {
|
func TestWAL(t *testing.T) {
|
||||||
rc := timestamp.NewMockRootCoordClient(t)
|
rc := idalloc.NewMockRootCoordClient(t)
|
||||||
resource.InitForTest(resource.OptRootCoordClient(rc))
|
resource.InitForTest(resource.OptRootCoordClient(rc))
|
||||||
|
|
||||||
b := registry.MustGetBuilder(walimplstest.WALName)
|
b := registry.MustGetBuilder(walimplstest.WALName)
|
||||||
|
@ -7,7 +7,7 @@ import (
|
|||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
"github.com/milvus-io/milvus/internal/streamingnode/server/resource"
|
"github.com/milvus-io/milvus/internal/streamingnode/server/resource"
|
||||||
"github.com/milvus-io/milvus/internal/streamingnode/server/resource/timestamp"
|
"github.com/milvus-io/milvus/internal/streamingnode/server/resource/idalloc"
|
||||||
"github.com/milvus-io/milvus/pkg/mocks/streaming/util/mock_message"
|
"github.com/milvus-io/milvus/pkg/mocks/streaming/util/mock_message"
|
||||||
"github.com/milvus-io/milvus/pkg/util/paramtable"
|
"github.com/milvus-io/milvus/pkg/util/paramtable"
|
||||||
)
|
)
|
||||||
@ -18,7 +18,7 @@ func TestAck(t *testing.T) {
|
|||||||
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
||||||
rc := timestamp.NewMockRootCoordClient(t)
|
rc := idalloc.NewMockRootCoordClient(t)
|
||||||
resource.InitForTest(resource.OptRootCoordClient(rc))
|
resource.InitForTest(resource.OptRootCoordClient(rc))
|
||||||
|
|
||||||
ackManager := NewAckManager()
|
ackManager := NewAckManager()
|
||||||
|
@ -31,7 +31,7 @@ func (ta *AckManager) Allocate(ctx context.Context) (*Acker, error) {
|
|||||||
defer ta.mu.Unlock()
|
defer ta.mu.Unlock()
|
||||||
|
|
||||||
// allocate one from underlying allocator first.
|
// allocate one from underlying allocator first.
|
||||||
ts, err := resource.Resource().TimestampAllocator().Allocate(ctx)
|
ts, err := resource.Resource().TSOAllocator().Allocate(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -47,7 +47,7 @@ func (ta *AckManager) Allocate(ctx context.Context) (*Acker, error) {
|
|||||||
// Concurrent safe to call with Allocate.
|
// Concurrent safe to call with Allocate.
|
||||||
func (ta *AckManager) SyncAndGetAcknowledged(ctx context.Context) ([]*AckDetail, error) {
|
func (ta *AckManager) SyncAndGetAcknowledged(ctx context.Context) ([]*AckDetail, error) {
|
||||||
// local timestamp may out of date, sync the underlying allocator before get last all acknowledged.
|
// local timestamp may out of date, sync the underlying allocator before get last all acknowledged.
|
||||||
resource.Resource().TimestampAllocator().Sync()
|
resource.Resource().TSOAllocator().Sync()
|
||||||
|
|
||||||
// Allocate may be uncalled in long term, and the recorder may be out of date.
|
// Allocate may be uncalled in long term, and the recorder may be out of date.
|
||||||
// Do a Allocate and Ack, can sync up the recorder with internal timetick.TimestampAllocator latest time.
|
// Do a Allocate and Ack, can sync up the recorder with internal timetick.TimestampAllocator latest time.
|
||||||
|
@ -12,16 +12,20 @@ var _ Manager = (*managerImpl)(nil)
|
|||||||
// Manager is the interface for managing the wal instances.
|
// Manager is the interface for managing the wal instances.
|
||||||
type Manager interface {
|
type Manager interface {
|
||||||
// Open opens a wal instance for the channel on this Manager.
|
// Open opens a wal instance for the channel on this Manager.
|
||||||
|
// Return `IgnoreOperation` error if the channel is not found.
|
||||||
|
// Return `UnmatchedChannelTerm` error if the channel term is not matched.
|
||||||
Open(ctx context.Context, channel types.PChannelInfo) error
|
Open(ctx context.Context, channel types.PChannelInfo) error
|
||||||
|
|
||||||
// GetAvailableWAL returns a available wal instance for the channel.
|
// GetAvailableWAL returns a available wal instance for the channel.
|
||||||
// Return nil if the wal instance is not found.
|
// Return nil if the wal instance is not found.
|
||||||
GetAvailableWAL(channel types.PChannelInfo) (wal.WAL, error)
|
GetAvailableWAL(types.PChannelInfo) (wal.WAL, error)
|
||||||
|
|
||||||
// GetAllAvailableWALInfo returns all available channel info.
|
// GetAllAvailableWALInfo returns all available channel info.
|
||||||
GetAllAvailableChannels() ([]types.PChannelInfo, error)
|
GetAllAvailableChannels() ([]types.PChannelInfo, error)
|
||||||
|
|
||||||
// Remove removes the wal instance for the channel.
|
// Remove removes the wal instance for the channel.
|
||||||
|
// Return `IgnoreOperation` error if the channel is not found.
|
||||||
|
// Return `UnmatchedChannelTerm` error if the channel term is not matched.
|
||||||
Remove(ctx context.Context, channel types.PChannelInfo) error
|
Remove(ctx context.Context, channel types.PChannelInfo) error
|
||||||
|
|
||||||
// Close these manager and release all managed WAL.
|
// Close these manager and release all managed WAL.
|
||||||
|
@ -71,6 +71,7 @@ func (m *managerImpl) Remove(ctx context.Context, channel types.PChannelInfo) (e
|
|||||||
m.lifetime.Done()
|
m.lifetime.Done()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warn("remove wal failed", zap.Error(err), zap.String("channel", channel.Name), zap.Int64("term", channel.Term))
|
log.Warn("remove wal failed", zap.Error(err), zap.String("channel", channel.Name), zap.Int64("term", channel.Term))
|
||||||
|
return
|
||||||
}
|
}
|
||||||
log.Info("remove wal success", zap.String("channel", channel.Name), zap.Int64("term", channel.Term))
|
log.Info("remove wal success", zap.String("channel", channel.Name), zap.Int64("term", channel.Term))
|
||||||
}()
|
}()
|
||||||
|
@ -1237,3 +1237,8 @@ func saveServerInfoInternal(role string, serverID int64, pid int) {
|
|||||||
func SaveServerInfo(role string, serverID int64) {
|
func SaveServerInfo(role string, serverID int64) {
|
||||||
saveServerInfoInternal(role, serverID, os.Getpid())
|
saveServerInfoInternal(role, serverID, os.Getpid())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetSessionPrefixByRole get session prefix by role
|
||||||
|
func GetSessionPrefixByRole(role string) string {
|
||||||
|
return path.Join(paramtable.Get().EtcdCfg.MetaRootPath.GetValue(), DefaultServiceRoot, role)
|
||||||
|
}
|
||||||
|
@ -17,7 +17,7 @@ import (
|
|||||||
|
|
||||||
var _ balancer.Picker = &serverIDPicker{}
|
var _ balancer.Picker = &serverIDPicker{}
|
||||||
|
|
||||||
var ErrNoSubConnNotExist = status.New(codes.Unavailable, "sub connection not exist").Err()
|
var ErrSubConnNotExist = status.New(codes.Unavailable, "subConn not exist").Err()
|
||||||
|
|
||||||
type subConnInfo struct {
|
type subConnInfo struct {
|
||||||
serverID int64
|
serverID int64
|
||||||
@ -107,18 +107,18 @@ func (p *serverIDPicker) useGivenAddr(_ balancer.PickInfo, serverID int64) (*sub
|
|||||||
// FailPrecondition will be converted to Internal by grpc framework in function `IsRestrictedControlPlaneCode`.
|
// FailPrecondition will be converted to Internal by grpc framework in function `IsRestrictedControlPlaneCode`.
|
||||||
// Use Unavailable here.
|
// Use Unavailable here.
|
||||||
// Unavailable code is retried in many cases, so it's better to be used here to avoid when Subconn is not ready scene.
|
// Unavailable code is retried in many cases, so it's better to be used here to avoid when Subconn is not ready scene.
|
||||||
return nil, ErrNoSubConnNotExist
|
return nil, ErrSubConnNotExist
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsErrNoSubConnForPick checks whether the error is ErrNoSubConnForPick.
|
// IsErrSubConnNoExist checks whether the error is ErrNoSubConnForPick.
|
||||||
func IsErrNoSubConnForPick(err error) bool {
|
func IsErrSubConnNoExist(err error) bool {
|
||||||
if errors.Is(err, ErrNoSubConnNotExist) {
|
if errors.Is(err, ErrSubConnNotExist) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
if se, ok := err.(interface {
|
if se, ok := err.(interface {
|
||||||
GRPCStatus() *status.Status
|
GRPCStatus() *status.Status
|
||||||
}); ok {
|
}); ok {
|
||||||
return errors.Is(se.GRPCStatus().Err(), ErrNoSubConnNotExist)
|
return errors.Is(se.GRPCStatus().Err(), ErrSubConnNotExist)
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
@ -91,13 +91,13 @@ func TestServerIDPickerBuilder(t *testing.T) {
|
|||||||
Ctx: contextutil.WithPickServerID(context.Background(), 4),
|
Ctx: contextutil.WithPickServerID(context.Background(), 4),
|
||||||
})
|
})
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
assert.ErrorIs(t, err, ErrNoSubConnNotExist)
|
assert.ErrorIs(t, err, ErrSubConnNotExist)
|
||||||
assert.NotNil(t, info)
|
assert.NotNil(t, info)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestIsErrNoSubConnForPick(t *testing.T) {
|
func TestIsErrNoSubConnForPick(t *testing.T) {
|
||||||
assert.True(t, IsErrNoSubConnForPick(ErrNoSubConnNotExist))
|
assert.True(t, IsErrSubConnNoExist(ErrSubConnNotExist))
|
||||||
assert.False(t, IsErrNoSubConnForPick(errors.New("test")))
|
assert.False(t, IsErrSubConnNoExist(errors.New("test")))
|
||||||
err := status.ConvertStreamingError("test", ErrNoSubConnNotExist)
|
err := status.ConvertStreamingError("test", ErrSubConnNotExist)
|
||||||
assert.True(t, IsErrNoSubConnForPick(err))
|
assert.True(t, IsErrSubConnNoExist(err))
|
||||||
}
|
}
|
||||||
|
@ -58,7 +58,10 @@ func (d *channelAssignmentDiscoverer) parseState() VersionedState {
|
|||||||
for _, assignment := range d.lastDiscovery.Assignments {
|
for _, assignment := range d.lastDiscovery.Assignments {
|
||||||
assignment := assignment
|
assignment := assignment
|
||||||
addrs = append(addrs, resolver.Address{
|
addrs = append(addrs, resolver.Address{
|
||||||
Addr: assignment.NodeInfo.Address,
|
Addr: assignment.NodeInfo.Address,
|
||||||
|
// resolverAttributes is important to use when resolving, server id to make resolver.Address with same adresss different.
|
||||||
|
Attributes: attributes.WithServerID(new(attributes.Attributes), assignment.NodeInfo.ServerID),
|
||||||
|
// balancerAttributes can be seen by picker of grpc balancer.
|
||||||
BalancerAttributes: attributes.WithChannelAssignmentInfo(new(attributes.Attributes), &assignment),
|
BalancerAttributes: attributes.WithChannelAssignmentInfo(new(attributes.Attributes), &assignment),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ import (
|
|||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/mock"
|
"github.com/stretchr/testify/mock"
|
||||||
|
|
||||||
|
"github.com/milvus-io/milvus/internal/util/streamingutil/service/attributes"
|
||||||
"github.com/milvus-io/milvus/pkg/mocks/streaming/util/mock_types"
|
"github.com/milvus-io/milvus/pkg/mocks/streaming/util/mock_types"
|
||||||
"github.com/milvus-io/milvus/pkg/streaming/util/types"
|
"github.com/milvus-io/milvus/pkg/streaming/util/types"
|
||||||
"github.com/milvus-io/milvus/pkg/util/typeutil"
|
"github.com/milvus-io/milvus/pkg/util/typeutil"
|
||||||
@ -92,6 +93,12 @@ func TestChannelAssignmentDiscoverer(t *testing.T) {
|
|||||||
idx++
|
idx++
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// resolver attributes
|
||||||
|
for _, addr := range state.State.Addresses {
|
||||||
|
serverID := attributes.GetServerID(addr.Attributes)
|
||||||
|
assert.NotNil(t, serverID)
|
||||||
|
}
|
||||||
return io.EOF
|
return io.EOF
|
||||||
})
|
})
|
||||||
assert.ErrorIs(t, err, io.EOF)
|
assert.ErrorIs(t, err, io.EOF)
|
||||||
|
@ -166,16 +166,18 @@ func (sw *sessionDiscoverer) parseState() VersionedState {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// filter low version.
|
// filter low version.
|
||||||
|
// !!! important, stopping nodes should not be removed here.
|
||||||
if !sw.versionRange(v) {
|
if !sw.versionRange(v) {
|
||||||
sw.logger.Info("skip low version node", zap.Int64("serverID", session.ServerID), zap.String("version", session.Version))
|
sw.logger.Info("skip low version node", zap.Int64("serverID", session.ServerID), zap.String("version", session.Version))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// !!! important, stopping nodes should not be removed here.
|
|
||||||
attr := new(attributes.Attributes)
|
|
||||||
attr = attributes.WithSession(attr, session)
|
|
||||||
addrs = append(addrs, resolver.Address{
|
addrs = append(addrs, resolver.Address{
|
||||||
Addr: session.Address,
|
Addr: session.Address,
|
||||||
BalancerAttributes: attr,
|
// resolverAttributes is important to use when resolving, server id to make resolver.Address with same adresss different.
|
||||||
|
Attributes: attributes.WithServerID(new(attributes.Attributes), session.ServerID),
|
||||||
|
// balancerAttributes can be seen by picker of grpc balancer.
|
||||||
|
BalancerAttributes: attributes.WithSession(new(attributes.Attributes), session),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@ import (
|
|||||||
clientv3 "go.etcd.io/etcd/client/v3"
|
clientv3 "go.etcd.io/etcd/client/v3"
|
||||||
|
|
||||||
"github.com/milvus-io/milvus/internal/util/sessionutil"
|
"github.com/milvus-io/milvus/internal/util/sessionutil"
|
||||||
|
"github.com/milvus-io/milvus/internal/util/streamingutil/service/attributes"
|
||||||
"github.com/milvus-io/milvus/pkg/util/etcd"
|
"github.com/milvus-io/milvus/pkg/util/etcd"
|
||||||
"github.com/milvus-io/milvus/pkg/util/typeutil"
|
"github.com/milvus-io/milvus/pkg/util/typeutil"
|
||||||
)
|
)
|
||||||
@ -96,8 +97,8 @@ func TestSessionDiscoverer(t *testing.T) {
|
|||||||
// Do a init discover here.
|
// Do a init discover here.
|
||||||
d = NewSessionDiscoverer(etcdClient, "session/", targetVersion)
|
d = NewSessionDiscoverer(etcdClient, "session/", targetVersion)
|
||||||
err = d.Discover(ctx, func(state VersionedState) error {
|
err = d.Discover(ctx, func(state VersionedState) error {
|
||||||
|
// balance attributes
|
||||||
sessions := state.Sessions()
|
sessions := state.Sessions()
|
||||||
|
|
||||||
expectedSessions := make(map[int64]*sessionutil.SessionRaw, len(expected[idx]))
|
expectedSessions := make(map[int64]*sessionutil.SessionRaw, len(expected[idx]))
|
||||||
for k, v := range expected[idx] {
|
for k, v := range expected[idx] {
|
||||||
if semver.MustParse(v.Version).GT(semver.MustParse(targetVersion)) {
|
if semver.MustParse(v.Version).GT(semver.MustParse(targetVersion)) {
|
||||||
@ -105,6 +106,12 @@ func TestSessionDiscoverer(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert.Equal(t, expectedSessions, sessions)
|
assert.Equal(t, expectedSessions, sessions)
|
||||||
|
|
||||||
|
// resolver attributes
|
||||||
|
for _, addr := range state.State.Addresses {
|
||||||
|
serverID := attributes.GetServerID(addr.Attributes)
|
||||||
|
assert.NotNil(t, serverID)
|
||||||
|
}
|
||||||
return io.EOF
|
return io.EOF
|
||||||
})
|
})
|
||||||
assert.ErrorIs(t, err, io.EOF)
|
assert.ErrorIs(t, err, io.EOF)
|
||||||
|
@ -43,6 +43,8 @@ func (r *watchBasedGRPCResolver) Close() {
|
|||||||
r.lifetime.Close()
|
r.lifetime.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update updates the state of the resolver.
|
||||||
|
// Return error if the resolver is closed.
|
||||||
func (r *watchBasedGRPCResolver) Update(state VersionedState) error {
|
func (r *watchBasedGRPCResolver) Update(state VersionedState) error {
|
||||||
if r.lifetime.Add(lifetime.IsWorking) != nil {
|
if r.lifetime.Add(lifetime.IsWorking) != nil {
|
||||||
return errors.New("resolver is closed")
|
return errors.New("resolver is closed")
|
||||||
@ -50,8 +52,9 @@ func (r *watchBasedGRPCResolver) Update(state VersionedState) error {
|
|||||||
defer r.lifetime.Done()
|
defer r.lifetime.Done()
|
||||||
|
|
||||||
if err := r.cc.UpdateState(state.State); err != nil {
|
if err := r.cc.UpdateState(state.State); err != nil {
|
||||||
// watch based resolver could ignore the error.
|
// watch based resolver could ignore the error, just log and return nil
|
||||||
r.logger.Warn("fail to update resolver state", zap.Error(err))
|
r.logger.Warn("fail to update resolver state", zap.Error(err))
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
r.logger.Info("update resolver state success", zap.Any("state", state.State))
|
r.logger.Info("update resolver state success", zap.Any("state", state.State))
|
||||||
return nil
|
return nil
|
||||||
|
@ -52,8 +52,8 @@ func TestDeliverPolicy(t *testing.T) {
|
|||||||
assert.Equal(t, policy.Policy(), policy2.Policy())
|
assert.Equal(t, policy.Policy(), policy2.Policy())
|
||||||
|
|
||||||
msgID := mock_message.NewMockMessageID(t)
|
msgID := mock_message.NewMockMessageID(t)
|
||||||
msgID.EXPECT().Marshal().Return([]byte("mock"))
|
msgID.EXPECT().Marshal().Return("mock")
|
||||||
message.RegisterMessageIDUnmsarshaler("mock", func(b []byte) (message.MessageID, error) {
|
message.RegisterMessageIDUnmsarshaler("mock", func(b string) (message.MessageID, error) {
|
||||||
return msgID, nil
|
return msgID, nil
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -26,4 +26,6 @@ packages:
|
|||||||
github.com/milvus-io/milvus/pkg/streaming/util/types:
|
github.com/milvus-io/milvus/pkg/streaming/util/types:
|
||||||
interfaces:
|
interfaces:
|
||||||
AssignmentDiscoverWatcher:
|
AssignmentDiscoverWatcher:
|
||||||
|
AssignmentRebalanceTrigger:
|
||||||
|
|
||||||
|
|
@ -147,16 +147,14 @@ func (_c *MockMessageID_LTE_Call) RunAndReturn(run func(message.MessageID) bool)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Marshal provides a mock function with given fields:
|
// Marshal provides a mock function with given fields:
|
||||||
func (_m *MockMessageID) Marshal() []byte {
|
func (_m *MockMessageID) Marshal() string {
|
||||||
ret := _m.Called()
|
ret := _m.Called()
|
||||||
|
|
||||||
var r0 []byte
|
var r0 string
|
||||||
if rf, ok := ret.Get(0).(func() []byte); ok {
|
if rf, ok := ret.Get(0).(func() string); ok {
|
||||||
r0 = rf()
|
r0 = rf()
|
||||||
} else {
|
} else {
|
||||||
if ret.Get(0) != nil {
|
r0 = ret.Get(0).(string)
|
||||||
r0 = ret.Get(0).([]byte)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return r0
|
return r0
|
||||||
@ -179,12 +177,12 @@ func (_c *MockMessageID_Marshal_Call) Run(run func()) *MockMessageID_Marshal_Cal
|
|||||||
return _c
|
return _c
|
||||||
}
|
}
|
||||||
|
|
||||||
func (_c *MockMessageID_Marshal_Call) Return(_a0 []byte) *MockMessageID_Marshal_Call {
|
func (_c *MockMessageID_Marshal_Call) Return(_a0 string) *MockMessageID_Marshal_Call {
|
||||||
_c.Call.Return(_a0)
|
_c.Call.Return(_a0)
|
||||||
return _c
|
return _c
|
||||||
}
|
}
|
||||||
|
|
||||||
func (_c *MockMessageID_Marshal_Call) RunAndReturn(run func() []byte) *MockMessageID_Marshal_Call {
|
func (_c *MockMessageID_Marshal_Call) RunAndReturn(run func() string) *MockMessageID_Marshal_Call {
|
||||||
_c.Call.Return(run)
|
_c.Call.Return(run)
|
||||||
return _c
|
return _c
|
||||||
}
|
}
|
||||||
|
@ -190,15 +190,15 @@ func (_c *MockMutableMessage_Payload_Call) RunAndReturn(run func() []byte) *Mock
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Properties provides a mock function with given fields:
|
// Properties provides a mock function with given fields:
|
||||||
func (_m *MockMutableMessage) Properties() message.Properties {
|
func (_m *MockMutableMessage) Properties() message.RProperties {
|
||||||
ret := _m.Called()
|
ret := _m.Called()
|
||||||
|
|
||||||
var r0 message.Properties
|
var r0 message.RProperties
|
||||||
if rf, ok := ret.Get(0).(func() message.Properties); ok {
|
if rf, ok := ret.Get(0).(func() message.RProperties); ok {
|
||||||
r0 = rf()
|
r0 = rf()
|
||||||
} else {
|
} else {
|
||||||
if ret.Get(0) != nil {
|
if ret.Get(0) != nil {
|
||||||
r0 = ret.Get(0).(message.Properties)
|
r0 = ret.Get(0).(message.RProperties)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -222,12 +222,12 @@ func (_c *MockMutableMessage_Properties_Call) Run(run func()) *MockMutableMessag
|
|||||||
return _c
|
return _c
|
||||||
}
|
}
|
||||||
|
|
||||||
func (_c *MockMutableMessage_Properties_Call) Return(_a0 message.Properties) *MockMutableMessage_Properties_Call {
|
func (_c *MockMutableMessage_Properties_Call) Return(_a0 message.RProperties) *MockMutableMessage_Properties_Call {
|
||||||
_c.Call.Return(_a0)
|
_c.Call.Return(_a0)
|
||||||
return _c
|
return _c
|
||||||
}
|
}
|
||||||
|
|
||||||
func (_c *MockMutableMessage_Properties_Call) RunAndReturn(run func() message.Properties) *MockMutableMessage_Properties_Call {
|
func (_c *MockMutableMessage_Properties_Call) RunAndReturn(run func() message.RProperties) *MockMutableMessage_Properties_Call {
|
||||||
_c.Call.Return(run)
|
_c.Call.Return(run)
|
||||||
return _c
|
return _c
|
||||||
}
|
}
|
||||||
@ -361,6 +361,50 @@ func (_c *MockMutableMessage_WithTimeTick_Call) RunAndReturn(run func(uint64) me
|
|||||||
return _c
|
return _c
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WithVChannel provides a mock function with given fields: vChannel
|
||||||
|
func (_m *MockMutableMessage) WithVChannel(vChannel string) message.MutableMessage {
|
||||||
|
ret := _m.Called(vChannel)
|
||||||
|
|
||||||
|
var r0 message.MutableMessage
|
||||||
|
if rf, ok := ret.Get(0).(func(string) message.MutableMessage); ok {
|
||||||
|
r0 = rf(vChannel)
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).(message.MutableMessage)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0
|
||||||
|
}
|
||||||
|
|
||||||
|
// MockMutableMessage_WithVChannel_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WithVChannel'
|
||||||
|
type MockMutableMessage_WithVChannel_Call struct {
|
||||||
|
*mock.Call
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithVChannel is a helper method to define mock.On call
|
||||||
|
// - vChannel string
|
||||||
|
func (_e *MockMutableMessage_Expecter) WithVChannel(vChannel interface{}) *MockMutableMessage_WithVChannel_Call {
|
||||||
|
return &MockMutableMessage_WithVChannel_Call{Call: _e.mock.On("WithVChannel", vChannel)}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockMutableMessage_WithVChannel_Call) Run(run func(vChannel string)) *MockMutableMessage_WithVChannel_Call {
|
||||||
|
_c.Call.Run(func(args mock.Arguments) {
|
||||||
|
run(args[0].(string))
|
||||||
|
})
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockMutableMessage_WithVChannel_Call) Return(_a0 message.MutableMessage) *MockMutableMessage_WithVChannel_Call {
|
||||||
|
_c.Call.Return(_a0)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockMutableMessage_WithVChannel_Call) RunAndReturn(run func(string) message.MutableMessage) *MockMutableMessage_WithVChannel_Call {
|
||||||
|
_c.Call.Return(run)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
// NewMockMutableMessage creates a new instance of MockMutableMessage. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
|
// NewMockMutableMessage creates a new instance of MockMutableMessage. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
|
||||||
// The first argument is typically a *testing.T value.
|
// The first argument is typically a *testing.T value.
|
||||||
func NewMockMutableMessage(t interface {
|
func NewMockMutableMessage(t interface {
|
||||||
|
@ -65,6 +65,50 @@ func (_c *MockAssignmentDiscoverWatcher_AssignmentDiscover_Call) RunAndReturn(ru
|
|||||||
return _c
|
return _c
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ReportAssignmentError provides a mock function with given fields: ctx, pchannel, err
|
||||||
|
func (_m *MockAssignmentDiscoverWatcher) ReportAssignmentError(ctx context.Context, pchannel types.PChannelInfo, err error) error {
|
||||||
|
ret := _m.Called(ctx, pchannel, err)
|
||||||
|
|
||||||
|
var r0 error
|
||||||
|
if rf, ok := ret.Get(0).(func(context.Context, types.PChannelInfo, error) error); ok {
|
||||||
|
r0 = rf(ctx, pchannel, err)
|
||||||
|
} else {
|
||||||
|
r0 = ret.Error(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0
|
||||||
|
}
|
||||||
|
|
||||||
|
// MockAssignmentDiscoverWatcher_ReportAssignmentError_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ReportAssignmentError'
|
||||||
|
type MockAssignmentDiscoverWatcher_ReportAssignmentError_Call struct {
|
||||||
|
*mock.Call
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReportAssignmentError is a helper method to define mock.On call
|
||||||
|
// - ctx context.Context
|
||||||
|
// - pchannel types.PChannelInfo
|
||||||
|
// - err error
|
||||||
|
func (_e *MockAssignmentDiscoverWatcher_Expecter) ReportAssignmentError(ctx interface{}, pchannel interface{}, err interface{}) *MockAssignmentDiscoverWatcher_ReportAssignmentError_Call {
|
||||||
|
return &MockAssignmentDiscoverWatcher_ReportAssignmentError_Call{Call: _e.mock.On("ReportAssignmentError", ctx, pchannel, err)}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockAssignmentDiscoverWatcher_ReportAssignmentError_Call) Run(run func(ctx context.Context, pchannel types.PChannelInfo, err error)) *MockAssignmentDiscoverWatcher_ReportAssignmentError_Call {
|
||||||
|
_c.Call.Run(func(args mock.Arguments) {
|
||||||
|
run(args[0].(context.Context), args[1].(types.PChannelInfo), args[2].(error))
|
||||||
|
})
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockAssignmentDiscoverWatcher_ReportAssignmentError_Call) Return(_a0 error) *MockAssignmentDiscoverWatcher_ReportAssignmentError_Call {
|
||||||
|
_c.Call.Return(_a0)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockAssignmentDiscoverWatcher_ReportAssignmentError_Call) RunAndReturn(run func(context.Context, types.PChannelInfo, error) error) *MockAssignmentDiscoverWatcher_ReportAssignmentError_Call {
|
||||||
|
_c.Call.Return(run)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
// NewMockAssignmentDiscoverWatcher creates a new instance of MockAssignmentDiscoverWatcher. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
|
// NewMockAssignmentDiscoverWatcher creates a new instance of MockAssignmentDiscoverWatcher. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
|
||||||
// The first argument is typically a *testing.T value.
|
// The first argument is typically a *testing.T value.
|
||||||
func NewMockAssignmentDiscoverWatcher(t interface {
|
func NewMockAssignmentDiscoverWatcher(t interface {
|
||||||
|
@ -0,0 +1,81 @@
|
|||||||
|
// Code generated by mockery v2.32.4. DO NOT EDIT.
|
||||||
|
|
||||||
|
package mock_types
|
||||||
|
|
||||||
|
import (
|
||||||
|
context "context"
|
||||||
|
|
||||||
|
types "github.com/milvus-io/milvus/pkg/streaming/util/types"
|
||||||
|
mock "github.com/stretchr/testify/mock"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MockAssignmentRebalanceTrigger is an autogenerated mock type for the AssignmentRebalanceTrigger type
|
||||||
|
type MockAssignmentRebalanceTrigger struct {
|
||||||
|
mock.Mock
|
||||||
|
}
|
||||||
|
|
||||||
|
type MockAssignmentRebalanceTrigger_Expecter struct {
|
||||||
|
mock *mock.Mock
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_m *MockAssignmentRebalanceTrigger) EXPECT() *MockAssignmentRebalanceTrigger_Expecter {
|
||||||
|
return &MockAssignmentRebalanceTrigger_Expecter{mock: &_m.Mock}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReportAssignmentError provides a mock function with given fields: ctx, pchannel, err
|
||||||
|
func (_m *MockAssignmentRebalanceTrigger) ReportAssignmentError(ctx context.Context, pchannel types.PChannelInfo, err error) error {
|
||||||
|
ret := _m.Called(ctx, pchannel, err)
|
||||||
|
|
||||||
|
var r0 error
|
||||||
|
if rf, ok := ret.Get(0).(func(context.Context, types.PChannelInfo, error) error); ok {
|
||||||
|
r0 = rf(ctx, pchannel, err)
|
||||||
|
} else {
|
||||||
|
r0 = ret.Error(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0
|
||||||
|
}
|
||||||
|
|
||||||
|
// MockAssignmentRebalanceTrigger_ReportAssignmentError_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ReportAssignmentError'
|
||||||
|
type MockAssignmentRebalanceTrigger_ReportAssignmentError_Call struct {
|
||||||
|
*mock.Call
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReportAssignmentError is a helper method to define mock.On call
|
||||||
|
// - ctx context.Context
|
||||||
|
// - pchannel types.PChannelInfo
|
||||||
|
// - err error
|
||||||
|
func (_e *MockAssignmentRebalanceTrigger_Expecter) ReportAssignmentError(ctx interface{}, pchannel interface{}, err interface{}) *MockAssignmentRebalanceTrigger_ReportAssignmentError_Call {
|
||||||
|
return &MockAssignmentRebalanceTrigger_ReportAssignmentError_Call{Call: _e.mock.On("ReportAssignmentError", ctx, pchannel, err)}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockAssignmentRebalanceTrigger_ReportAssignmentError_Call) Run(run func(ctx context.Context, pchannel types.PChannelInfo, err error)) *MockAssignmentRebalanceTrigger_ReportAssignmentError_Call {
|
||||||
|
_c.Call.Run(func(args mock.Arguments) {
|
||||||
|
run(args[0].(context.Context), args[1].(types.PChannelInfo), args[2].(error))
|
||||||
|
})
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockAssignmentRebalanceTrigger_ReportAssignmentError_Call) Return(_a0 error) *MockAssignmentRebalanceTrigger_ReportAssignmentError_Call {
|
||||||
|
_c.Call.Return(_a0)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockAssignmentRebalanceTrigger_ReportAssignmentError_Call) RunAndReturn(run func(context.Context, types.PChannelInfo, error) error) *MockAssignmentRebalanceTrigger_ReportAssignmentError_Call {
|
||||||
|
_c.Call.Return(run)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewMockAssignmentRebalanceTrigger creates a new instance of MockAssignmentRebalanceTrigger. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
|
||||||
|
// The first argument is typically a *testing.T value.
|
||||||
|
func NewMockAssignmentRebalanceTrigger(t interface {
|
||||||
|
mock.TestingT
|
||||||
|
Cleanup(func())
|
||||||
|
}) *MockAssignmentRebalanceTrigger {
|
||||||
|
mock := &MockAssignmentRebalanceTrigger{}
|
||||||
|
mock.Mock.Test(t)
|
||||||
|
|
||||||
|
t.Cleanup(func() { mock.AssertExpectations(t) })
|
||||||
|
|
||||||
|
return mock
|
||||||
|
}
|
@ -43,14 +43,14 @@ func (b *MutableMesasgeBuilder) WithPayload(payload []byte) *MutableMesasgeBuild
|
|||||||
}
|
}
|
||||||
|
|
||||||
// WithProperty creates a new builder with message property.
|
// WithProperty creates a new builder with message property.
|
||||||
// A key started with '_' is reserved for log system, should never used at user of client.
|
// A key started with '_' is reserved for streaming system, should never used at user of client.
|
||||||
func (b *MutableMesasgeBuilder) WithProperty(key string, val string) *MutableMesasgeBuilder {
|
func (b *MutableMesasgeBuilder) WithProperty(key string, val string) *MutableMesasgeBuilder {
|
||||||
b.properties.Set(key, val)
|
b.properties.Set(key, val)
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithProperties creates a new builder with message properties.
|
// WithProperties creates a new builder with message properties.
|
||||||
// A key started with '_' is reserved for log system, should never used at user of client.
|
// A key started with '_' is reserved for streaming system, should never used at user of client.
|
||||||
func (b *MutableMesasgeBuilder) WithProperties(kvs map[string]string) *MutableMesasgeBuilder {
|
func (b *MutableMesasgeBuilder) WithProperties(kvs map[string]string) *MutableMesasgeBuilder {
|
||||||
for key, val := range kvs {
|
for key, val := range kvs {
|
||||||
b.properties.Set(key, val)
|
b.properties.Set(key, val)
|
||||||
|
25
pkg/streaming/util/message/encoder.go
Normal file
25
pkg/streaming/util/message/encoder.go
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
package message
|
||||||
|
|
||||||
|
import "strconv"
|
||||||
|
|
||||||
|
const base = 36
|
||||||
|
|
||||||
|
// EncodeInt64 encodes int64 to string.
|
||||||
|
func EncodeInt64(value int64) string {
|
||||||
|
return strconv.FormatInt(value, base)
|
||||||
|
}
|
||||||
|
|
||||||
|
// EncodeUint64 encodes uint64 to string.
|
||||||
|
func EncodeUint64(value uint64) string {
|
||||||
|
return strconv.FormatUint(value, base)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DecodeUint64 decodes string to uint64.
|
||||||
|
func DecodeUint64(value string) (uint64, error) {
|
||||||
|
return strconv.ParseUint(value, base, 64)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DecodeInt64 decodes string to int64.
|
||||||
|
func DecodeInt64(value string) (int64, error) {
|
||||||
|
return strconv.ParseInt(value, base, 64)
|
||||||
|
}
|
@ -21,6 +21,10 @@ type BasicMessage interface {
|
|||||||
|
|
||||||
// EstimateSize returns the estimated size of message.
|
// EstimateSize returns the estimated size of message.
|
||||||
EstimateSize() int
|
EstimateSize() int
|
||||||
|
|
||||||
|
// Properties returns the message properties.
|
||||||
|
// Should be used with read-only promise.
|
||||||
|
Properties() RProperties
|
||||||
}
|
}
|
||||||
|
|
||||||
// MutableMessage is the mutable message interface.
|
// MutableMessage is the mutable message interface.
|
||||||
@ -29,23 +33,23 @@ type MutableMessage interface {
|
|||||||
BasicMessage
|
BasicMessage
|
||||||
|
|
||||||
// WithLastConfirmed sets the last confirmed message id of current message.
|
// WithLastConfirmed sets the last confirmed message id of current message.
|
||||||
// !!! preserved for log system internal usage, don't call it outside of log system.
|
// !!! preserved for streaming system internal usage, don't call it outside of log system.
|
||||||
WithLastConfirmed(id MessageID) MutableMessage
|
WithLastConfirmed(id MessageID) MutableMessage
|
||||||
|
|
||||||
// WithTimeTick sets the time tick of current message.
|
// WithTimeTick sets the time tick of current message.
|
||||||
// !!! preserved for log system internal usage, don't call it outside of log system.
|
// !!! preserved for streaming system internal usage, don't call it outside of log system.
|
||||||
WithTimeTick(tt uint64) MutableMessage
|
WithTimeTick(tt uint64) MutableMessage
|
||||||
|
|
||||||
// Properties returns the message properties.
|
// WithVChannel sets the virtual channel of current message.
|
||||||
Properties() Properties
|
// !!! preserved for streaming system internal usage, don't call it outside of log system.
|
||||||
|
WithVChannel(vChannel string) MutableMessage
|
||||||
|
|
||||||
// IntoImmutableMessage converts the mutable message to immutable message.
|
// IntoImmutableMessage converts the mutable message to immutable message.
|
||||||
IntoImmutableMessage(msgID MessageID) ImmutableMessage
|
IntoImmutableMessage(msgID MessageID) ImmutableMessage
|
||||||
}
|
}
|
||||||
|
|
||||||
// ImmutableMessage is the read-only message interface.
|
// ImmutableMessage is the read-only message interface.
|
||||||
// Once a message is persistent by wal, it will be immutable.
|
// Once a message is persistent by wal or temporary generated by wal, it will be immutable.
|
||||||
// And the message id will be assigned.
|
|
||||||
type ImmutableMessage interface {
|
type ImmutableMessage interface {
|
||||||
BasicMessage
|
BasicMessage
|
||||||
|
|
||||||
@ -71,7 +75,4 @@ type ImmutableMessage interface {
|
|||||||
|
|
||||||
// MessageID returns the message id of current message.
|
// MessageID returns the message id of current message.
|
||||||
MessageID() MessageID
|
MessageID() MessageID
|
||||||
|
|
||||||
// Properties returns the message read only properties.
|
|
||||||
Properties() RProperties
|
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,6 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/golang/protobuf/proto"
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
"github.com/milvus-io/milvus/pkg/mocks/streaming/util/mock_message"
|
"github.com/milvus-io/milvus/pkg/mocks/streaming/util/mock_message"
|
||||||
@ -25,16 +24,16 @@ func TestMessage(t *testing.T) {
|
|||||||
assert.Equal(t, "value", v)
|
assert.Equal(t, "value", v)
|
||||||
assert.True(t, ok)
|
assert.True(t, ok)
|
||||||
assert.Equal(t, message.MessageTypeTimeTick, mutableMessage.MessageType())
|
assert.Equal(t, message.MessageTypeTimeTick, mutableMessage.MessageType())
|
||||||
assert.Equal(t, 21, mutableMessage.EstimateSize())
|
assert.Equal(t, 24, mutableMessage.EstimateSize())
|
||||||
mutableMessage.WithTimeTick(123)
|
mutableMessage.WithTimeTick(123)
|
||||||
v, ok = mutableMessage.Properties().Get("_tt")
|
v, ok = mutableMessage.Properties().Get("_tt")
|
||||||
assert.True(t, ok)
|
assert.True(t, ok)
|
||||||
tt, n := proto.DecodeVarint([]byte(v))
|
tt, err := message.DecodeUint64(v)
|
||||||
assert.Equal(t, uint64(123), tt)
|
assert.Equal(t, uint64(123), tt)
|
||||||
assert.Equal(t, len([]byte(v)), n)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
lcMsgID := mock_message.NewMockMessageID(t)
|
lcMsgID := mock_message.NewMockMessageID(t)
|
||||||
lcMsgID.EXPECT().Marshal().Return([]byte("lcMsgID"))
|
lcMsgID.EXPECT().Marshal().Return("lcMsgID")
|
||||||
mutableMessage.WithLastConfirmed(lcMsgID)
|
mutableMessage.WithLastConfirmed(lcMsgID)
|
||||||
v, ok = mutableMessage.Properties().Get("_lc")
|
v, ok = mutableMessage.Properties().Get("_lc")
|
||||||
assert.True(t, ok)
|
assert.True(t, ok)
|
||||||
@ -43,8 +42,8 @@ func TestMessage(t *testing.T) {
|
|||||||
msgID := mock_message.NewMockMessageID(t)
|
msgID := mock_message.NewMockMessageID(t)
|
||||||
msgID.EXPECT().EQ(msgID).Return(true)
|
msgID.EXPECT().EQ(msgID).Return(true)
|
||||||
msgID.EXPECT().WALName().Return("testMsgID")
|
msgID.EXPECT().WALName().Return("testMsgID")
|
||||||
message.RegisterMessageIDUnmsarshaler("testMsgID", func(data []byte) (message.MessageID, error) {
|
message.RegisterMessageIDUnmsarshaler("testMsgID", func(data string) (message.MessageID, error) {
|
||||||
if string(data) == "lcMsgID" {
|
if data == "lcMsgID" {
|
||||||
return msgID, nil
|
return msgID, nil
|
||||||
}
|
}
|
||||||
panic(fmt.Sprintf("unexpected data: %s", data))
|
panic(fmt.Sprintf("unexpected data: %s", data))
|
||||||
@ -54,8 +53,8 @@ func TestMessage(t *testing.T) {
|
|||||||
[]byte("payload"),
|
[]byte("payload"),
|
||||||
map[string]string{
|
map[string]string{
|
||||||
"key": "value",
|
"key": "value",
|
||||||
"_t": "1",
|
"_t": "1200",
|
||||||
"_tt": string(proto.EncodeVarint(456)),
|
"_tt": message.EncodeUint64(456),
|
||||||
"_v": "1",
|
"_v": "1",
|
||||||
"_lc": "lcMsgID",
|
"_lc": "lcMsgID",
|
||||||
})
|
})
|
||||||
@ -67,7 +66,7 @@ func TestMessage(t *testing.T) {
|
|||||||
assert.Equal(t, "value", v)
|
assert.Equal(t, "value", v)
|
||||||
assert.True(t, ok)
|
assert.True(t, ok)
|
||||||
assert.Equal(t, message.MessageTypeTimeTick, immutableMessage.MessageType())
|
assert.Equal(t, message.MessageTypeTimeTick, immutableMessage.MessageType())
|
||||||
assert.Equal(t, 36, immutableMessage.EstimateSize())
|
assert.Equal(t, 39, immutableMessage.EstimateSize())
|
||||||
assert.Equal(t, message.Version(1), immutableMessage.Version())
|
assert.Equal(t, message.Version(1), immutableMessage.Version())
|
||||||
assert.Equal(t, uint64(456), immutableMessage.TimeTick())
|
assert.Equal(t, uint64(456), immutableMessage.TimeTick())
|
||||||
assert.NotNil(t, immutableMessage.LastConfirmedMessageID())
|
assert.NotNil(t, immutableMessage.LastConfirmedMessageID())
|
||||||
@ -77,7 +76,7 @@ func TestMessage(t *testing.T) {
|
|||||||
[]byte("payload"),
|
[]byte("payload"),
|
||||||
map[string]string{
|
map[string]string{
|
||||||
"key": "value",
|
"key": "value",
|
||||||
"_t": "1",
|
"_t": "1200",
|
||||||
})
|
})
|
||||||
|
|
||||||
assert.True(t, immutableMessage.MessageID().EQ(msgID))
|
assert.True(t, immutableMessage.MessageID().EQ(msgID))
|
||||||
@ -87,7 +86,7 @@ func TestMessage(t *testing.T) {
|
|||||||
assert.Equal(t, "value", v)
|
assert.Equal(t, "value", v)
|
||||||
assert.True(t, ok)
|
assert.True(t, ok)
|
||||||
assert.Equal(t, message.MessageTypeTimeTick, immutableMessage.MessageType())
|
assert.Equal(t, message.MessageTypeTimeTick, immutableMessage.MessageType())
|
||||||
assert.Equal(t, 18, immutableMessage.EstimateSize())
|
assert.Equal(t, 21, immutableMessage.EstimateSize())
|
||||||
assert.Equal(t, message.Version(0), immutableMessage.Version())
|
assert.Equal(t, message.Version(0), immutableMessage.Version())
|
||||||
assert.Panics(t, func() {
|
assert.Panics(t, func() {
|
||||||
immutableMessage.TimeTick()
|
immutableMessage.TimeTick()
|
||||||
|
@ -22,10 +22,10 @@ func RegisterMessageIDUnmsarshaler(name string, unmarshaler MessageIDUnmarshaler
|
|||||||
}
|
}
|
||||||
|
|
||||||
// MessageIDUnmarshaler is the unmarshaler for message id.
|
// MessageIDUnmarshaler is the unmarshaler for message id.
|
||||||
type MessageIDUnmarshaler = func(b []byte) (MessageID, error)
|
type MessageIDUnmarshaler = func(b string) (MessageID, error)
|
||||||
|
|
||||||
// UnmsarshalMessageID unmarshal the message id.
|
// UnmsarshalMessageID unmarshal the message id.
|
||||||
func UnmarshalMessageID(name string, b []byte) (MessageID, error) {
|
func UnmarshalMessageID(name string, b string) (MessageID, error) {
|
||||||
unmarshaler, ok := messageIDUnmarshaler.Get(name)
|
unmarshaler, ok := messageIDUnmarshaler.Get(name)
|
||||||
if !ok {
|
if !ok {
|
||||||
panic("MessageID Unmarshaler not registered: " + name)
|
panic("MessageID Unmarshaler not registered: " + name)
|
||||||
@ -48,5 +48,5 @@ type MessageID interface {
|
|||||||
EQ(MessageID) bool
|
EQ(MessageID) bool
|
||||||
|
|
||||||
// Marshal marshal the message id.
|
// Marshal marshal the message id.
|
||||||
Marshal() []byte
|
Marshal() string
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package message_test
|
package message_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/cockroachdb/errors"
|
"github.com/cockroachdb/errors"
|
||||||
@ -14,28 +13,28 @@ import (
|
|||||||
func TestRegisterMessageIDUnmarshaler(t *testing.T) {
|
func TestRegisterMessageIDUnmarshaler(t *testing.T) {
|
||||||
msgID := mock_message.NewMockMessageID(t)
|
msgID := mock_message.NewMockMessageID(t)
|
||||||
|
|
||||||
message.RegisterMessageIDUnmsarshaler("test", func(b []byte) (message.MessageID, error) {
|
message.RegisterMessageIDUnmsarshaler("test", func(b string) (message.MessageID, error) {
|
||||||
if bytes.Equal(b, []byte("123")) {
|
if b == "123" {
|
||||||
return msgID, nil
|
return msgID, nil
|
||||||
}
|
}
|
||||||
return nil, errors.New("invalid")
|
return nil, errors.New("invalid")
|
||||||
})
|
})
|
||||||
|
|
||||||
id, err := message.UnmarshalMessageID("test", []byte("123"))
|
id, err := message.UnmarshalMessageID("test", "123")
|
||||||
assert.NotNil(t, id)
|
assert.NotNil(t, id)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
id, err = message.UnmarshalMessageID("test", []byte("1234"))
|
id, err = message.UnmarshalMessageID("test", "1234")
|
||||||
assert.Nil(t, id)
|
assert.Nil(t, id)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
|
|
||||||
assert.Panics(t, func() {
|
assert.Panics(t, func() {
|
||||||
message.UnmarshalMessageID("test1", []byte("123"))
|
message.UnmarshalMessageID("test1", "123")
|
||||||
})
|
})
|
||||||
|
|
||||||
assert.Panics(t, func() {
|
assert.Panics(t, func() {
|
||||||
message.RegisterMessageIDUnmsarshaler("test", func(b []byte) (message.MessageID, error) {
|
message.RegisterMessageIDUnmsarshaler("test", func(b string) (message.MessageID, error) {
|
||||||
if bytes.Equal(b, []byte("123")) {
|
if b == "123" {
|
||||||
return msgID, nil
|
return msgID, nil
|
||||||
}
|
}
|
||||||
return nil, errors.New("invalid")
|
return nil, errors.New("invalid")
|
||||||
|
@ -2,8 +2,6 @@ package message
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/golang/protobuf/proto"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type messageImpl struct {
|
type messageImpl struct {
|
||||||
@ -35,7 +33,7 @@ func (m *messageImpl) Payload() []byte {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Properties returns the message properties.
|
// Properties returns the message properties.
|
||||||
func (m *messageImpl) Properties() Properties {
|
func (m *messageImpl) Properties() RProperties {
|
||||||
return m.properties
|
return m.properties
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -45,10 +43,15 @@ func (m *messageImpl) EstimateSize() int {
|
|||||||
return len(m.payload) + m.properties.EstimateSize()
|
return len(m.payload) + m.properties.EstimateSize()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WithVChannel sets the virtual channel of current message.
|
||||||
|
func (m *messageImpl) WithVChannel(vChannel string) MutableMessage {
|
||||||
|
m.properties.Set(messageVChannel, vChannel)
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
// WithTimeTick sets the time tick of current message.
|
// WithTimeTick sets the time tick of current message.
|
||||||
func (m *messageImpl) WithTimeTick(tt uint64) MutableMessage {
|
func (m *messageImpl) WithTimeTick(tt uint64) MutableMessage {
|
||||||
t := proto.EncodeVarint(tt)
|
m.properties.Set(messageTimeTick, EncodeUint64(tt))
|
||||||
m.properties.Set(messageTimeTick, string(t))
|
|
||||||
return m
|
return m
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,10 +85,9 @@ func (m *immutableMessageImpl) TimeTick() uint64 {
|
|||||||
if !ok {
|
if !ok {
|
||||||
panic(fmt.Sprintf("there's a bug in the message codes, timetick lost in properties of message, id: %+v", m.id))
|
panic(fmt.Sprintf("there's a bug in the message codes, timetick lost in properties of message, id: %+v", m.id))
|
||||||
}
|
}
|
||||||
v := []byte(value)
|
tt, err := DecodeUint64(value)
|
||||||
tt, n := proto.DecodeVarint(v)
|
if err != nil {
|
||||||
if n != len(v) {
|
panic(fmt.Sprintf("there's a bug in the message codes, dirty timetick %s in properties of message, id: %+v", value, m.id))
|
||||||
panic(fmt.Sprintf("there's a bug in the message codes, dirty timetick in properties of message, id: %+v", m.id))
|
|
||||||
}
|
}
|
||||||
return tt
|
return tt
|
||||||
}
|
}
|
||||||
@ -95,7 +97,7 @@ func (m *immutableMessageImpl) LastConfirmedMessageID() MessageID {
|
|||||||
if !ok {
|
if !ok {
|
||||||
panic(fmt.Sprintf("there's a bug in the message codes, last confirmed message lost in properties of message, id: %+v", m.id))
|
panic(fmt.Sprintf("there's a bug in the message codes, last confirmed message lost in properties of message, id: %+v", m.id))
|
||||||
}
|
}
|
||||||
id, err := UnmarshalMessageID(m.id.WALName(), []byte(value))
|
id, err := UnmarshalMessageID(m.id.WALName(), value)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(fmt.Sprintf("there's a bug in the message codes, dirty last confirmed message in properties of message, id: %+v", m.id))
|
panic(fmt.Sprintf("there's a bug in the message codes, dirty last confirmed message in properties of message, id: %+v", m.id))
|
||||||
}
|
}
|
||||||
@ -114,8 +116,3 @@ func (m *immutableMessageImpl) VChannel() string {
|
|||||||
}
|
}
|
||||||
return value
|
return value
|
||||||
}
|
}
|
||||||
|
|
||||||
// Properties returns the message read only properties.
|
|
||||||
func (m *immutableMessageImpl) Properties() RProperties {
|
|
||||||
return m.properties
|
|
||||||
}
|
|
||||||
|
@ -11,9 +11,15 @@ func TestMessageType(t *testing.T) {
|
|||||||
assert.Equal(t, "0", s)
|
assert.Equal(t, "0", s)
|
||||||
typ := unmarshalMessageType("0")
|
typ := unmarshalMessageType("0")
|
||||||
assert.Equal(t, MessageTypeUnknown, typ)
|
assert.Equal(t, MessageTypeUnknown, typ)
|
||||||
|
assert.False(t, MessageTypeUnknown.Valid())
|
||||||
|
|
||||||
typ = unmarshalMessageType("882s9")
|
typ = unmarshalMessageType("882s9")
|
||||||
assert.Equal(t, MessageTypeUnknown, typ)
|
assert.Equal(t, MessageTypeUnknown, typ)
|
||||||
|
|
||||||
|
s = MessageTypeTimeTick.marshal()
|
||||||
|
typ = unmarshalMessageType(s)
|
||||||
|
assert.Equal(t, MessageTypeTimeTick, typ)
|
||||||
|
assert.True(t, MessageTypeTimeTick.Valid())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestVersion(t *testing.T) {
|
func TestVersion(t *testing.T) {
|
||||||
|
@ -1,17 +1,35 @@
|
|||||||
package message
|
package message
|
||||||
|
|
||||||
import "strconv"
|
import (
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/milvus-io/milvus-proto/go-api/v2/commonpb"
|
||||||
|
)
|
||||||
|
|
||||||
type MessageType int32
|
type MessageType int32
|
||||||
|
|
||||||
const (
|
const (
|
||||||
MessageTypeUnknown MessageType = 0
|
MessageTypeUnknown MessageType = MessageType(commonpb.MsgType_Undefined)
|
||||||
MessageTypeTimeTick MessageType = 1
|
MessageTypeTimeTick MessageType = MessageType(commonpb.MsgType_TimeTick)
|
||||||
|
MessageTypeInsert MessageType = MessageType(commonpb.MsgType_Insert)
|
||||||
|
MessageTypeDelete MessageType = MessageType(commonpb.MsgType_Delete)
|
||||||
|
MessageTypeFlush MessageType = MessageType(commonpb.MsgType_Flush)
|
||||||
|
MessageTypeCreateCollection MessageType = MessageType(commonpb.MsgType_CreateCollection)
|
||||||
|
MessageTypeDropCollection MessageType = MessageType(commonpb.MsgType_DropCollection)
|
||||||
|
MessageTypeCreatePartition MessageType = MessageType(commonpb.MsgType_CreatePartition)
|
||||||
|
MessageTypeDropPartition MessageType = MessageType(commonpb.MsgType_DropPartition)
|
||||||
)
|
)
|
||||||
|
|
||||||
var messageTypeName = map[MessageType]string{
|
var messageTypeName = map[MessageType]string{
|
||||||
MessageTypeUnknown: "MESSAGE_TYPE_UNKNOWN",
|
MessageTypeUnknown: "UNKNOWN",
|
||||||
MessageTypeTimeTick: "MESSAGE_TYPE_TIME_TICK",
|
MessageTypeTimeTick: "TIME_TICK",
|
||||||
|
MessageTypeInsert: "INSERT",
|
||||||
|
MessageTypeDelete: "DELETE",
|
||||||
|
MessageTypeFlush: "FLUSH",
|
||||||
|
MessageTypeCreateCollection: "CREATE_COLLECTION",
|
||||||
|
MessageTypeDropCollection: "DROP_COLLECTION",
|
||||||
|
MessageTypeCreatePartition: "CREATE_PARTITION",
|
||||||
|
MessageTypeDropPartition: "DROP_PARTITION",
|
||||||
}
|
}
|
||||||
|
|
||||||
// String implements fmt.Stringer interface.
|
// String implements fmt.Stringer interface.
|
||||||
@ -26,8 +44,8 @@ func (t MessageType) marshal() string {
|
|||||||
|
|
||||||
// Valid checks if the MessageType is valid.
|
// Valid checks if the MessageType is valid.
|
||||||
func (t MessageType) Valid() bool {
|
func (t MessageType) Valid() bool {
|
||||||
return t == MessageTypeTimeTick
|
_, ok := messageTypeName[t]
|
||||||
// TODO: fill more.
|
return t != MessageTypeUnknown && ok
|
||||||
}
|
}
|
||||||
|
|
||||||
// unmarshalMessageType unmarshal MessageType from string.
|
// unmarshalMessageType unmarshal MessageType from string.
|
||||||
|
@ -88,3 +88,8 @@ func DeliverFilterVChannel(vchannel string) DeliverFilter {
|
|||||||
vchannel: vchannel,
|
vchannel: vchannel,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsDeliverFilterTimeTick checks if the filter is time tick filter.
|
||||||
|
func IsDeliverFilterTimeTick(filter DeliverFilter) bool {
|
||||||
|
return filter.Type() == DeliverFilterTypeTimeTickGT || filter.Type() == DeliverFilterTypeTimeTickGTE
|
||||||
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package types
|
package types
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
const (
|
const (
|
||||||
InitialTerm int64 = -1
|
InitialTerm int64 = -1
|
||||||
)
|
)
|
||||||
@ -10,6 +12,10 @@ type PChannelInfo struct {
|
|||||||
Term int64 // term of pchannel.
|
Term int64 // term of pchannel.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *PChannelInfo) String() string {
|
||||||
|
return fmt.Sprintf("%s@%d", c.Name, c.Term)
|
||||||
|
}
|
||||||
|
|
||||||
type PChannelInfoAssigned struct {
|
type PChannelInfoAssigned struct {
|
||||||
Channel PChannelInfo
|
Channel PChannelInfo
|
||||||
Node StreamingNodeInfo
|
Node StreamingNodeInfo
|
||||||
|
@ -19,6 +19,15 @@ type AssignmentDiscoverWatcher interface {
|
|||||||
// The callback will be called when the discovery is changed.
|
// The callback will be called when the discovery is changed.
|
||||||
// The final error will be returned when the watcher is closed or broken.
|
// The final error will be returned when the watcher is closed or broken.
|
||||||
AssignmentDiscover(ctx context.Context, cb func(*VersionedStreamingNodeAssignments) error) error
|
AssignmentDiscover(ctx context.Context, cb func(*VersionedStreamingNodeAssignments) error) error
|
||||||
|
|
||||||
|
AssignmentRebalanceTrigger
|
||||||
|
}
|
||||||
|
|
||||||
|
// AssignmentRebalanceTrigger is the interface for triggering the re-balance of the pchannel.
|
||||||
|
type AssignmentRebalanceTrigger interface {
|
||||||
|
// ReportStreamingError is used to report the streaming error.
|
||||||
|
// Trigger a re-balance of the pchannel.
|
||||||
|
ReportAssignmentError(ctx context.Context, pchannel PChannelInfo, err error) error
|
||||||
}
|
}
|
||||||
|
|
||||||
// VersionedStreamingNodeAssignments is the relation between server and channels with version.
|
// VersionedStreamingNodeAssignments is the relation between server and channels with version.
|
||||||
|
@ -1,14 +1,17 @@
|
|||||||
package pulsar
|
package pulsar
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/hex"
|
||||||
|
|
||||||
"github.com/apache/pulsar-client-go/pulsar"
|
"github.com/apache/pulsar-client-go/pulsar"
|
||||||
|
"github.com/cockroachdb/errors"
|
||||||
|
|
||||||
"github.com/milvus-io/milvus/pkg/streaming/util/message"
|
"github.com/milvus-io/milvus/pkg/streaming/util/message"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ message.MessageID = pulsarID{}
|
var _ message.MessageID = pulsarID{}
|
||||||
|
|
||||||
func UnmarshalMessageID(data []byte) (message.MessageID, error) {
|
func UnmarshalMessageID(data string) (message.MessageID, error) {
|
||||||
id, err := unmarshalMessageID(data)
|
id, err := unmarshalMessageID(data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -16,10 +19,14 @@ func UnmarshalMessageID(data []byte) (message.MessageID, error) {
|
|||||||
return id, nil
|
return id, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func unmarshalMessageID(data []byte) (pulsarID, error) {
|
func unmarshalMessageID(data string) (pulsarID, error) {
|
||||||
msgID, err := pulsar.DeserializeMessageID(data)
|
val, err := hex.DecodeString(data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return pulsarID{nil}, err
|
return pulsarID{nil}, errors.Wrapf(message.ErrInvalidMessageID, "decode pulsar fail when decode hex with err: %s, id: %s", err.Error(), data)
|
||||||
|
}
|
||||||
|
msgID, err := pulsar.DeserializeMessageID(val)
|
||||||
|
if err != nil {
|
||||||
|
return pulsarID{nil}, errors.Wrapf(message.ErrInvalidMessageID, "decode pulsar fail when deserialize with err: %s, id: %s", err.Error(), data)
|
||||||
}
|
}
|
||||||
return pulsarID{msgID}, nil
|
return pulsarID{msgID}, nil
|
||||||
}
|
}
|
||||||
@ -61,6 +68,6 @@ func (id pulsarID) EQ(other message.MessageID) bool {
|
|||||||
id.BatchIdx() == id2.BatchIdx()
|
id.BatchIdx() == id2.BatchIdx()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (id pulsarID) Marshal() []byte {
|
func (id pulsarID) Marshal() string {
|
||||||
return id.Serialize()
|
return hex.EncodeToString(id.Serialize())
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,7 @@ func TestMessageID(t *testing.T) {
|
|||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.True(t, msgID.EQ(pulsarID{newMessageIDOfPulsar(1, 2, 3)}))
|
assert.True(t, msgID.EQ(pulsarID{newMessageIDOfPulsar(1, 2, 3)}))
|
||||||
|
|
||||||
_, err = UnmarshalMessageID([]byte{0x01, 0x02, 0x03, 0x04})
|
_, err = UnmarshalMessageID(string([]byte{0x01, 0x02, 0x03, 0x04}))
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,11 +1,7 @@
|
|||||||
package rmq
|
package rmq
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/base64"
|
|
||||||
|
|
||||||
"github.com/cockroachdb/errors"
|
"github.com/cockroachdb/errors"
|
||||||
"github.com/golang/protobuf/proto"
|
|
||||||
"google.golang.org/protobuf/encoding/protowire"
|
|
||||||
|
|
||||||
"github.com/milvus-io/milvus/pkg/streaming/util/message"
|
"github.com/milvus-io/milvus/pkg/streaming/util/message"
|
||||||
)
|
)
|
||||||
@ -13,7 +9,7 @@ import (
|
|||||||
var _ message.MessageID = rmqID(0)
|
var _ message.MessageID = rmqID(0)
|
||||||
|
|
||||||
// UnmarshalMessageID unmarshal the message id.
|
// UnmarshalMessageID unmarshal the message id.
|
||||||
func UnmarshalMessageID(data []byte) (message.MessageID, error) {
|
func UnmarshalMessageID(data string) (message.MessageID, error) {
|
||||||
id, err := unmarshalMessageID(data)
|
id, err := unmarshalMessageID(data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -22,12 +18,12 @@ func UnmarshalMessageID(data []byte) (message.MessageID, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// unmashalMessageID unmarshal the message id.
|
// unmashalMessageID unmarshal the message id.
|
||||||
func unmarshalMessageID(data []byte) (rmqID, error) {
|
func unmarshalMessageID(data string) (rmqID, error) {
|
||||||
v, n := proto.DecodeVarint(data)
|
v, err := message.DecodeUint64(data)
|
||||||
if n <= 0 || n != len(data) {
|
if err != nil {
|
||||||
return 0, errors.Wrapf(message.ErrInvalidMessageID, "rmqID: %s", base64.RawStdEncoding.EncodeToString(data))
|
return 0, errors.Wrapf(message.ErrInvalidMessageID, "decode rmqID fail with err: %s, id: %s", err.Error(), data)
|
||||||
}
|
}
|
||||||
return rmqID(protowire.DecodeZigZag(v)), nil
|
return rmqID(v), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// rmqID is the message id for rmq.
|
// rmqID is the message id for rmq.
|
||||||
@ -54,6 +50,6 @@ func (id rmqID) EQ(other message.MessageID) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Marshal marshal the message id.
|
// Marshal marshal the message id.
|
||||||
func (id rmqID) Marshal() []byte {
|
func (id rmqID) Marshal() string {
|
||||||
return proto.EncodeVarint(protowire.EncodeZigZag(int64(id)))
|
return message.EncodeInt64(int64(id))
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,6 @@ func TestMessageID(t *testing.T) {
|
|||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, rmqID(1), msgID)
|
assert.Equal(t, rmqID(1), msgID)
|
||||||
|
|
||||||
_, err = UnmarshalMessageID([]byte{0x01, 0x02, 0x03, 0x04})
|
_, err = UnmarshalMessageID(string([]byte{0x01, 0x02, 0x03, 0x04}))
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
}
|
}
|
||||||
|
@ -4,8 +4,6 @@
|
|||||||
package walimplstest
|
package walimplstest
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"github.com/milvus-io/milvus/pkg/streaming/util/message"
|
"github.com/milvus-io/milvus/pkg/streaming/util/message"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -17,7 +15,7 @@ func NewTestMessageID(id int64) message.MessageID {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// UnmarshalTestMessageID unmarshal the message id.
|
// UnmarshalTestMessageID unmarshal the message id.
|
||||||
func UnmarshalTestMessageID(data []byte) (message.MessageID, error) {
|
func UnmarshalTestMessageID(data string) (message.MessageID, error) {
|
||||||
id, err := unmarshalTestMessageID(data)
|
id, err := unmarshalTestMessageID(data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -26,8 +24,8 @@ func UnmarshalTestMessageID(data []byte) (message.MessageID, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// unmashalTestMessageID unmarshal the message id.
|
// unmashalTestMessageID unmarshal the message id.
|
||||||
func unmarshalTestMessageID(data []byte) (testMessageID, error) {
|
func unmarshalTestMessageID(data string) (testMessageID, error) {
|
||||||
id, err := strconv.ParseInt(string(data), 10, 64)
|
id, err := message.DecodeInt64(data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
@ -58,6 +56,6 @@ func (id testMessageID) EQ(other message.MessageID) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Marshal marshal the message id.
|
// Marshal marshal the message id.
|
||||||
func (id testMessageID) Marshal() []byte {
|
func (id testMessageID) Marshal() string {
|
||||||
return []byte(strconv.FormatInt(int64(id), 10))
|
return message.EncodeInt64(int64(id))
|
||||||
}
|
}
|
||||||
|
@ -120,6 +120,7 @@ go test -race -cover -tags dynamic,test "${PKG_DIR}/log/..." -failfast -count=1
|
|||||||
go test -race -cover -tags dynamic,test "${PKG_DIR}/mq/..." -failfast -count=1 -ldflags="-r ${RPATH}"
|
go test -race -cover -tags dynamic,test "${PKG_DIR}/mq/..." -failfast -count=1 -ldflags="-r ${RPATH}"
|
||||||
go test -race -cover -tags dynamic,test "${PKG_DIR}/tracer/..." -failfast -count=1 -ldflags="-r ${RPATH}"
|
go test -race -cover -tags dynamic,test "${PKG_DIR}/tracer/..." -failfast -count=1 -ldflags="-r ${RPATH}"
|
||||||
go test -race -cover -tags dynamic,test "${PKG_DIR}/util/..." -failfast -count=1 -ldflags="-r ${RPATH}"
|
go test -race -cover -tags dynamic,test "${PKG_DIR}/util/..." -failfast -count=1 -ldflags="-r ${RPATH}"
|
||||||
|
go test -race -cover -tags dynamic,test "${PKG_DIR}/streaming/..." -failfast -count=1 -ldflags="-r ${RPATH}"
|
||||||
popd
|
popd
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -169,6 +170,9 @@ function test_streaming()
|
|||||||
go test -race -cover -tags dynamic,test "${MILVUS_DIR}/streamingcoord/..." -failfast -count=1 -ldflags="-r ${RPATH}"
|
go test -race -cover -tags dynamic,test "${MILVUS_DIR}/streamingcoord/..." -failfast -count=1 -ldflags="-r ${RPATH}"
|
||||||
go test -race -cover -tags dynamic,test "${MILVUS_DIR}/streamingnode/..." -failfast -count=1 -ldflags="-r ${RPATH}"
|
go test -race -cover -tags dynamic,test "${MILVUS_DIR}/streamingnode/..." -failfast -count=1 -ldflags="-r ${RPATH}"
|
||||||
go test -race -cover -tags dynamic,test "${MILVUS_DIR}/util/streamingutil/..." -failfast -count=1 -ldflags="-r ${RPATH}"
|
go test -race -cover -tags dynamic,test "${MILVUS_DIR}/util/streamingutil/..." -failfast -count=1 -ldflags="-r ${RPATH}"
|
||||||
|
pushd pkg
|
||||||
|
go test -race -cover -tags dynamic,test "${PKG_DIR}/streaming/..." -failfast -count=1 -ldflags="-r ${RPATH}"
|
||||||
|
popd
|
||||||
}
|
}
|
||||||
|
|
||||||
function test_all()
|
function test_all()
|
||||||
|
Loading…
Reference in New Issue
Block a user