Browse Source

v0.0.1开发:inner服务更新用户在线状态接口开发

#Suyghur 2 years ago
parent
commit
d4a367f42b

+ 0 - 73
comm/ds/rbtree/iterator.go

@@ -1,73 +0,0 @@
-//@File     iterator.go
-//@Time     2022/05/12
-//@Author   #Suyghur,
-
-package rbtree
-
-import "ylink/comm/utils/iterator"
-
-type RbTreeIterator struct {
-	node *Node
-}
-
-// NewIterator creates a RbTreeIterator from the passed node
-func NewIterator(node *Node) *RbTreeIterator {
-	return &RbTreeIterator{node: node}
-}
-
-// IsValid returns true if the iterator is valid, otherwise returns false
-func (iter *RbTreeIterator) IsValid() bool {
-	if iter.node != nil {
-		return true
-	}
-	return false
-}
-
-// Next moves the pointer of the iterator to the next node, and returns itself
-func (iter *RbTreeIterator) Next() iterator.ConstIterator {
-	if iter.IsValid() {
-		iter.node = iter.node.Next()
-	}
-	return iter
-}
-
-// Prev moves the pointer of the iterator to the previous node, and returns itself
-func (iter *RbTreeIterator) Prev() iterator.ConstBidIterator {
-	if iter.IsValid() {
-		iter.node = iter.node.Prev()
-	}
-	return iter
-}
-
-// Key returns the node's key of the iterator point to
-func (iter *RbTreeIterator) Key() interface{} {
-	return iter.node.Key()
-}
-
-// Value returns the node's value of the iterator point to
-func (iter *RbTreeIterator) Value() interface{} {
-	return iter.node.Value()
-}
-
-//SetValue sets the node's value of the iterator point to
-func (iter *RbTreeIterator) SetValue(val interface{}) error {
-	iter.node.SetValue(val)
-	return nil
-}
-
-// Clone clones the iterator into a new RbTreeIterator
-func (iter *RbTreeIterator) Clone() iterator.ConstIterator {
-	return NewIterator(iter.node)
-}
-
-// Equal returns true if the iterator is equal to the passed iterator
-func (iter *RbTreeIterator) Equal(other iterator.ConstIterator) bool {
-	otherIter, ok := other.(*RbTreeIterator)
-	if !ok {
-		return false
-	}
-	if otherIter.node == iter.node {
-		return true
-	}
-	return false
-}

+ 0 - 87
comm/ds/rbtree/node.go

@@ -1,87 +0,0 @@
-//@File     node.go
-//@Time     2022/05/12
-//@Author   #Suyghur,
-
-package rbtree
-
-type Color bool
-
-const (
-	RED   = false
-	BLACK = true
-)
-
-type Node struct {
-	parent *Node
-	left   *Node
-	right  *Node
-	color  Color
-	key    interface{}
-	value  interface{}
-}
-
-func (node *Node) Key() interface{} {
-	return node.key
-}
-
-func (node *Node) Value() interface{} {
-	return node.value
-}
-
-func (node *Node) SetValue(value interface{}) {
-	node.value = value
-}
-
-func (node *Node) Next() *Node {
-	return successor(node)
-}
-
-func (node *Node) Prev() *Node {
-	return preSuccessor(node)
-}
-
-// successor returns the successor of the Node
-func successor(node *Node) *Node {
-	if node.right != nil {
-		return minimum(node.right)
-	}
-	y := node.parent
-	for y != nil && node == y.right {
-		node = y
-		y = node.parent
-	}
-	return y
-}
-
-// preSuccessor returns the preSuccessor of the Node
-func preSuccessor(node *Node) *Node {
-	if node.left != nil {
-		return maximum(node.left)
-	}
-	if node.parent != nil {
-		if node.parent.right == node {
-			return node.parent
-		}
-		for node.parent != nil && node.parent.left == node {
-			node = node.parent
-		}
-		return node.parent
-	}
-	return nil
-}
-
-// minimum finds the minimum Node of subtree n.
-func minimum(node *Node) *Node {
-	for node.left != nil {
-		node = node.left
-	}
-	return node
-}
-
-// maximum finds the maximum Node of subtree n.
-func maximum(node *Node) *Node {
-	for node.right != nil {
-		node = node.right
-	}
-	return node
-}

+ 0 - 481
comm/ds/rbtree/rbtree.go

@@ -1,481 +0,0 @@
-//@File     rbtree.go
-//@Time     2022/05/12
-//@Author   #Suyghur,
-
-package rbtree
-
-import (
-	"fmt"
-	"ylink/comm/utils/comparator"
-	"ylink/comm/utils/visitor"
-)
-
-var defaultKeyComparator = comparator.BuiltinTypeComparator
-
-type Options struct {
-	keyCmp comparator.Comparator
-}
-
-// Option is a function type used to set Options
-type Option func(option *Options)
-
-//WithKeyComparator is used to set RbTree's key comparator
-func WithKeyComparator(cmp comparator.Comparator) Option {
-	return func(option *Options) {
-		option.keyCmp = cmp
-	}
-}
-
-type RbTree struct {
-	root   *Node
-	size   int
-	keyCmp comparator.Comparator
-}
-
-// New creates a new RbTree
-func New(opts ...Option) *RbTree {
-	option := Options{
-		keyCmp: defaultKeyComparator,
-	}
-	for _, opt := range opts {
-		opt(&option)
-	}
-	return &RbTree{keyCmp: option.keyCmp}
-}
-
-// Clear clears the RbTree
-func (tree *RbTree) Clear() {
-	tree.root = nil
-	tree.size = 0
-}
-
-// Find finds the first node that the key is equal to the passed key, and returns its value
-func (tree *RbTree) Find(key interface{}) interface{} {
-	n := tree.findFirstNode(key)
-	if n != nil {
-		return n.value
-	}
-	return nil
-}
-
-// FindNode the first node that the key is equal to the passed key and return it
-func (tree *RbTree) FindNode(key interface{}) *Node {
-	return tree.findFirstNode(key)
-}
-
-// Begin returns the node with minimum key in the RbTree
-func (tree *RbTree) Begin() *Node {
-	return tree.First()
-}
-
-// First returns the node with minimum key in the RbTree
-func (tree *RbTree) First() *Node {
-	if tree.root == nil {
-		return nil
-	}
-	return minimum(tree.root)
-}
-
-// RBegin returns the Node with maximum key in the RbTree
-func (tree *RbTree) RBegin() *Node {
-	return tree.Last()
-}
-
-// Last returns the Node with maximum key in the RbTree
-func (tree *RbTree) Last() *Node {
-	if tree.root == nil {
-		return nil
-	}
-	return maximum(tree.root)
-}
-
-// IterFirst returns the iterator of first node
-func (tree *RbTree) IterFirst() *RbTreeIterator {
-	return NewIterator(tree.First())
-}
-
-// IterLast returns the iterator of first node
-func (tree *RbTree) IterLast() *RbTreeIterator {
-	return NewIterator(tree.Last())
-}
-
-// Empty returns true if Tree is empty,otherwise returns false.
-func (tree *RbTree) Empty() bool {
-	if tree.size == 0 {
-		return true
-	}
-	return false
-}
-
-// Size returns the size of the rbtree.
-func (tree *RbTree) Size() int {
-	return tree.size
-}
-
-// Insert inserts a key-value pair into the RbTree.
-func (tree *RbTree) Insert(key, value interface{}) {
-	x := tree.root
-	var y *Node
-
-	for x != nil {
-		y = x
-		if tree.keyCmp(key, x.key) < 0 {
-			x = x.left
-		} else {
-			x = x.right
-		}
-	}
-
-	z := &Node{parent: y, color: RED, key: key, value: value}
-	tree.size++
-
-	if y == nil {
-		z.color = BLACK
-		tree.root = z
-		return
-	} else if tree.keyCmp(z.key, y.key) < 0 {
-		y.left = z
-	} else {
-		y.right = z
-	}
-	tree.rbInsertFixup(z)
-}
-
-func (tree *RbTree) rbInsertFixup(z *Node) {
-	var y *Node
-	for z.parent != nil && z.parent.color == RED {
-		if z.parent == z.parent.parent.left {
-			y = z.parent.parent.right
-			if y != nil && y.color == RED {
-				z.parent.color = BLACK
-				y.color = BLACK
-				z.parent.parent.color = RED
-				z = z.parent.parent
-			} else {
-				if z == z.parent.right {
-					z = z.parent
-					tree.leftRotate(z)
-				}
-				z.parent.color = BLACK
-				z.parent.parent.color = RED
-				tree.rightRotate(z.parent.parent)
-			}
-		} else {
-			y = z.parent.parent.left
-			if y != nil && y.color == RED {
-				z.parent.color = BLACK
-				y.color = BLACK
-				z.parent.parent.color = RED
-				z = z.parent.parent
-			} else {
-				if z == z.parent.left {
-					z = z.parent
-					tree.rightRotate(z)
-				}
-				z.parent.color = BLACK
-				z.parent.parent.color = RED
-				tree.leftRotate(z.parent.parent)
-			}
-		}
-	}
-	tree.root.color = BLACK
-}
-
-// Delete deletes node from the RbTree
-func (tree *RbTree) Delete(node *Node) {
-	z := node
-	if z == nil {
-		return
-	}
-
-	var x, y *Node
-	if z.left != nil && z.right != nil {
-		y = successor(z)
-	} else {
-		y = z
-	}
-
-	if y.left != nil {
-		x = y.left
-	} else {
-		x = y.right
-	}
-
-	xparent := y.parent
-	if x != nil {
-		x.parent = xparent
-	}
-	if y.parent == nil {
-		tree.root = x
-	} else if y == y.parent.left {
-		y.parent.left = x
-	} else {
-		y.parent.right = x
-	}
-
-	if y != z {
-		z.key = y.key
-		z.value = y.value
-	}
-
-	if y.color == BLACK {
-		tree.rbDeleteFixup(x, xparent)
-	}
-	tree.size--
-}
-
-func (tree *RbTree) rbDeleteFixup(x, parent *Node) {
-	var w *Node
-	for x != tree.root && getColor(x) == BLACK {
-		if x != nil {
-			parent = x.parent
-		}
-		if x == parent.left {
-			x, w = tree.rbFixupLeft(x, parent, w)
-		} else {
-			x, w = tree.rbFixupRight(x, parent, w)
-		}
-	}
-	if x != nil {
-		x.color = BLACK
-	}
-}
-
-func (tree *RbTree) rbFixupLeft(x, parent, w *Node) (*Node, *Node) {
-	w = parent.right
-	if w.color == RED {
-		w.color = BLACK
-		parent.color = RED
-		tree.leftRotate(parent)
-		w = parent.right
-	}
-	if getColor(w.left) == BLACK && getColor(w.right) == BLACK {
-		w.color = RED
-		x = parent
-	} else {
-		if getColor(w.right) == BLACK {
-			if w.left != nil {
-				w.left.color = BLACK
-			}
-			w.color = RED
-			tree.rightRotate(w)
-			w = parent.right
-		}
-		w.color = parent.color
-		parent.color = BLACK
-		if w.right != nil {
-			w.right.color = BLACK
-		}
-		tree.leftRotate(parent)
-		x = tree.root
-	}
-	return x, w
-}
-
-func (tree *RbTree) rbFixupRight(x, parent, w *Node) (*Node, *Node) {
-	w = parent.left
-	if w.color == RED {
-		w.color = BLACK
-		parent.color = RED
-		tree.rightRotate(parent)
-		w = parent.left
-	}
-	if getColor(w.left) == BLACK && getColor(w.right) == BLACK {
-		w.color = RED
-		x = parent
-	} else {
-		if getColor(w.left) == BLACK {
-			if w.right != nil {
-				w.right.color = BLACK
-			}
-			w.color = RED
-			tree.leftRotate(w)
-			w = parent.left
-		}
-		w.color = parent.color
-		parent.color = BLACK
-		if w.left != nil {
-			w.left.color = BLACK
-		}
-		tree.rightRotate(parent)
-		x = tree.root
-	}
-	return x, w
-}
-
-func (tree *RbTree) leftRotate(x *Node) {
-	y := x.right
-	x.right = y.left
-	if y.left != nil {
-		y.left.parent = x
-	}
-	y.parent = x.parent
-	if x.parent == nil {
-		tree.root = y
-	} else if x == x.parent.left {
-		x.parent.left = y
-	} else {
-		x.parent.right = y
-	}
-	y.left = x
-	x.parent = y
-}
-
-func (tree *RbTree) rightRotate(x *Node) {
-	y := x.left
-	x.left = y.right
-	if y.right != nil {
-		y.right.parent = x
-	}
-	y.parent = x.parent
-	if x.parent == nil {
-		tree.root = y
-	} else if x == x.parent.right {
-		x.parent.right = y
-	} else {
-		x.parent.left = y
-	}
-	y.right = x
-	x.parent = y
-}
-
-// findNode finds the node that its key is equal to the passed key, and returns it.
-func (tree *RbTree) findNode(key interface{}) *Node {
-	x := tree.root
-	for x != nil {
-		if tree.keyCmp(key, x.key) < 0 {
-			x = x.left
-		} else {
-			if tree.keyCmp(key, x.key) == 0 {
-				return x
-			}
-			x = x.right
-		}
-	}
-	return nil
-}
-
-// findNode finds the first node that its key is equal to the passed key, and returns it
-func (tree *RbTree) findFirstNode(key interface{}) *Node {
-	node := tree.FindLowerBoundNode(key)
-	if node == nil {
-		return nil
-	}
-	if tree.keyCmp(node.key, key) == 0 {
-		return node
-	}
-	return nil
-}
-
-// FindLowerBoundNode finds the first node that its key is equal or greater than the passed key, and returns it
-func (tree *RbTree) FindLowerBoundNode(key interface{}) *Node {
-	return tree.findLowerBoundNode(tree.root, key)
-}
-
-func (tree *RbTree) findLowerBoundNode(x *Node, key interface{}) *Node {
-	if x == nil {
-		return nil
-	}
-	if tree.keyCmp(key, x.key) <= 0 {
-		ret := tree.findLowerBoundNode(x.left, key)
-		if ret == nil {
-			return x
-		}
-		if tree.keyCmp(ret.key, x.key) <= 0 {
-			return ret
-		}
-		return x
-	}
-	return tree.findLowerBoundNode(x.right, key)
-}
-
-// FindUpperBoundNode finds the first node that its key is greater than the passed key, and returns it
-func (tree *RbTree) FindUpperBoundNode(key interface{}) *Node {
-	return tree.findUpperBoundNode(tree.root, key)
-}
-
-func (tree *RbTree) findUpperBoundNode(x *Node, key interface{}) *Node {
-	if x == nil {
-		return nil
-	}
-	if tree.keyCmp(key, x.key) >= 0 {
-		return tree.findUpperBoundNode(x.right, key)
-	}
-	ret := tree.findUpperBoundNode(x.left, key)
-	if ret == nil {
-		return x
-	}
-	if tree.keyCmp(ret.key, x.key) <= 0 {
-		return ret
-	}
-	return x
-}
-
-// Traversal traversals elements in the RbTree, it will not stop until to the end of RbTree or the visitor returns false
-func (tree *RbTree) Traversal(visitor visitor.KvVisitor) {
-	for node := tree.First(); node != nil; node = node.Next() {
-		if !visitor(node.key, node.value) {
-			break
-		}
-	}
-}
-
-// IsRbTree is a function use to test whether t is a RbTree or not
-func (tree *RbTree) IsRbTree() (bool, error) {
-	// Properties:
-	// 1. Each node is either red or black.
-	// 2. The root is black.
-	// 3. All leaves (NIL) are black.
-	// 4. If a node is red, then both its children are black.
-	// 5. Every path from a given node to any of its descendant NIL nodes contains the same number of black nodes.
-	_, property, ok := tree.test(tree.root)
-	if !ok {
-		return false, fmt.Errorf("violate property %v", property)
-	}
-	return true, nil
-}
-
-func (tree *RbTree) test(n *Node) (int, int, bool) {
-
-	if n == nil { // property 3:
-		return 1, 0, true
-	}
-
-	if n == tree.root && n.color != BLACK { // property 2:
-		return 1, 2, false
-	}
-	leftBlackCount, property, ok := tree.test(n.left)
-	if !ok {
-		return leftBlackCount, property, ok
-	}
-	rightBlackCount, property, ok := tree.test(n.right)
-	if !ok {
-		return rightBlackCount, property, ok
-	}
-
-	if rightBlackCount != leftBlackCount { // property 5:
-		return leftBlackCount, 5, false
-	}
-	blackCount := leftBlackCount
-
-	if n.color == RED {
-		if getColor(n.left) != BLACK || getColor(n.right) != BLACK { // property 4:
-			return 0, 4, false
-		}
-	} else {
-		blackCount++
-	}
-
-	if n == tree.root {
-		//fmt.Printf("blackCount:%v \n", blackCount)
-	}
-	return blackCount, 0, true
-}
-
-// getColor returns the node's color
-func getColor(n *Node) Color {
-	if n == nil {
-		return BLACK
-	}
-	return n.color
-}

+ 0 - 180
comm/ds/rbtree/rbtree_test.go

@@ -1,180 +0,0 @@
-package rbtree
-
-import (
-	"github.com/stretchr/testify/assert"
-	"math/rand"
-	"testing"
-	"time"
-	"ylink/comm/utils/comparator"
-)
-
-func TestRbTeeFind(t *testing.T) {
-	tree := New()
-	for i := 0; i < 10; i++ {
-		tree.Insert(i, i+10000)
-	}
-	assert.False(t, tree.Empty())
-	assert.Equal(t, 10, tree.Size())
-
-	for i := 0; i < 10; i++ {
-		val := tree.Find(i)
-		assert.Equal(t, i+10000, val)
-	}
-	for i := 0; i < 10; i++ {
-		iter := tree.FindLowerBoundNode(i)
-		assert.Equal(t, i+10000, iter.Value())
-
-		iter2 := tree.FindUpperBoundNode(i - 1)
-		assert.Equal(t, i+10000, iter2.Value())
-	}
-	for i := 0; i < 10; i++ {
-		tree.Insert(i, i+20000)
-	}
-
-	for i := 0; i < 10; i++ {
-		iter := tree.FindLowerBoundNode(i)
-		count := 0
-		for n := iter; n != nil; n = n.Next() {
-			if n.key != i {
-				break
-			}
-			count++
-			//t.Logf("travesal: %v = %v ", n.key, n.value)
-		}
-		assert.Equal(t, 2, count)
-	}
-
-	for i := 0; i < 10; i++ {
-		iter := tree.FindUpperBoundNode(i - 1)
-		count := 0
-		for n := iter; n != nil; n = n.Next() {
-			if n.key != i {
-				break
-			}
-			count++
-			//t.Logf("travesal: %v = %v ", n.key, n.value)
-		}
-		assert.Equal(t, 2, count)
-	}
-}
-
-func TestRbTeeDelete(t *testing.T) {
-	tree := New()
-	m := make(map[int]int)
-	for i := 0; i < 1000; i++ {
-		tree.Insert(i, i)
-		m[i] = i
-	}
-	count := 1000
-	for k, v := range m {
-		//t.Logf("%v", k)
-		node := tree.FindNode(k)
-		assert.Equal(t, v, node.Value())
-		tree.Delete(node)
-		assert.Nil(t, tree.FindNode(k))
-		count--
-		assert.Equal(t, count, tree.Size())
-	}
-}
-
-func TestTraversal(t *testing.T) {
-	tree := New()
-	for i := 0; i < 10; i++ {
-		tree.Insert(i, i+100)
-	}
-	i := 0
-	tree.Traversal(func(key, value interface{}) bool {
-		assert.Equal(t, i, key.(int))
-		assert.Equal(t, i+100, value.(int))
-		i++
-		return true
-	})
-}
-
-func TestInsertDelete(t *testing.T) {
-	tree := New()
-	m := make(map[int]int)
-	rand.Seed(time.Now().Unix())
-	for i := 0; i < 10000; i++ {
-		key := rand.Int() % 1000
-		val := rand.Int()
-		if v, ok := m[key]; ok {
-			n := tree.findNode(key)
-			assert.Equal(t, v, n.Value())
-			delete(m, key)
-			tree.Delete(n)
-		} else {
-			n := tree.findNode(key)
-			assert.Nil(t, n)
-
-			m[key] = val
-			tree.Insert(key, val)
-		}
-		assert.Equal(t, len(m), tree.Size())
-		b, _ := tree.IsRbTree()
-		assert.True(t, b)
-	}
-	tree.Clear()
-	assert.Equal(t, 0, tree.Size())
-}
-
-func TestIterator(t *testing.T) {
-	tree := New(WithKeyComparator(comparator.IntComparator))
-	for i := 0; i < 10; i++ {
-		tree.Insert(i, i+100)
-	}
-
-	i := 0
-	for iter := tree.IterFirst().Clone().(*RbTreeIterator); iter.IsValid(); iter.Next() {
-		assert.Equal(t, i, iter.Key())
-		assert.Equal(t, i+100, iter.Value())
-		i++
-	}
-
-	i = 9
-	for iter := tree.IterLast(); iter.IsValid(); iter.Prev() {
-		assert.Equal(t, i, iter.Key())
-		assert.Equal(t, i+100, iter.Value())
-		iter.SetValue(i * 2)
-		i--
-	}
-
-	i = 0
-	for iter := tree.IterFirst(); iter.IsValid(); iter.Next() {
-		assert.Equal(t, i, iter.Key())
-		assert.Equal(t, i*2, iter.Value())
-		i++
-	}
-	assert.True(t, tree.IterFirst().Equal(tree.IterFirst().Clone()))
-	assert.False(t, tree.IterFirst().Equal(nil))
-	assert.False(t, tree.IterFirst().Equal(tree.IterLast()))
-}
-
-func TestNode(t *testing.T) {
-	tree := New()
-	for i := 0; i < 10; i++ {
-		tree.Insert(i, i+100)
-	}
-
-	i := 0
-	for n := tree.Begin(); n != nil; n = n.Next() {
-		assert.Equal(t, i, n.Key())
-		assert.Equal(t, i+100, n.Value())
-		i++
-	}
-
-	i = 9
-	for n := tree.RBegin(); n != nil; n = n.Prev() {
-		assert.Equal(t, i, n.Key())
-		assert.Equal(t, i+100, n.Value())
-		n.SetValue(i * 2)
-		i--
-	}
-
-	i = 0
-	for n := tree.Begin(); n != nil; n = n.Next() {
-		assert.Equal(t, i, n.Key())
-		assert.Equal(t, i*2, n.Value())
-		i++
-	}
-}

+ 0 - 70
comm/ds/treemap/iterator.go

@@ -1,70 +0,0 @@
-//@File     iterator.go
-//@Time     2022/05/12
-//@Author   #Suyghur,
-
-package treemap
-
-import (
-	"ylink/comm/ds/rbtree"
-	"ylink/comm/utils/iterator"
-)
-
-type MapIterator struct {
-	node *rbtree.Node
-}
-
-// IsValid returns true if the iterator is valid, otherwise returns false
-func (iter *MapIterator) IsValid() bool {
-	if iter.node != nil {
-		return true
-	}
-	return false
-}
-
-// Next moves the pointer of the iterator to the next node, and returns itself
-func (iter *MapIterator) Next() iterator.ConstIterator {
-	if iter.IsValid() {
-		iter.node = iter.node.Next()
-	}
-	return iter
-}
-
-// Prev moves the pointer of the iterator to the previous node, and returns itseft
-func (iter *MapIterator) Prev() iterator.ConstBidIterator {
-	if iter.IsValid() {
-		iter.node = iter.node.Prev()
-	}
-	return iter
-}
-
-// Key returns the node's key of the iterator point to
-func (iter *MapIterator) Key() interface{} {
-	return iter.node.Key()
-}
-
-// Value returns the node's value of the iterator point to
-func (iter *MapIterator) Value() interface{} {
-	return iter.node.Value()
-}
-
-// SetValue sets the node's value of the iterator point to
-func (iter *MapIterator) SetValue(val interface{}) {
-	iter.node.SetValue(val)
-}
-
-// Clone clones the iterator to a new MapIterator
-func (iter *MapIterator) Clone() iterator.ConstIterator {
-	return &MapIterator{iter.node}
-}
-
-// Equal returns true if the iterator is equal to the passed iterator, otherwise returns false
-func (iter *MapIterator) Equal(other iterator.ConstIterator) bool {
-	otherIter, ok := other.(*MapIterator)
-	if !ok {
-		return false
-	}
-	if otherIter.node == iter.node {
-		return true
-	}
-	return false
-}

+ 0 - 193
comm/ds/treemap/map.go

@@ -1,193 +0,0 @@
-//@File     map.go
-//@Time     2022/05/12
-//@Author   #Suyghur,
-
-package treemap
-
-import (
-	gosync "sync"
-	"ylink/comm/ds/rbtree"
-	"ylink/comm/utils/comparator"
-	"ylink/comm/utils/iterator"
-	"ylink/comm/utils/sync"
-	"ylink/comm/utils/visitor"
-)
-
-var (
-	defaultKeyComparator = comparator.BuiltinTypeComparator
-	defaultLocker        sync.FakeLocker
-)
-
-type Options struct {
-	keyCmp comparator.Comparator
-	locker sync.Locker
-}
-
-// Option is a function type used to set Options
-type Option func(option *Options)
-
-// WithKeyComparator is used to set the key comparator of map
-func WithKeyComparator(cmp comparator.Comparator) Option {
-	return func(option *Options) {
-		option.keyCmp = cmp
-	}
-}
-
-func WithGoroutineSafe() Option {
-	return func(option *Options) {
-		option.locker = &gosync.RWMutex{}
-	}
-}
-
-// Map uses RbTress for internal data structure, and every key can must bee unique.
-type Map struct {
-	tree   *rbtree.RbTree
-	locker sync.Locker
-}
-
-// New creates a new map
-func New(opts ...Option) *Map {
-	option := Options{
-		keyCmp: defaultKeyComparator,
-		locker: defaultLocker,
-	}
-	for _, opt := range opts {
-		opt(&option)
-	}
-	return &Map{tree: rbtree.New(rbtree.WithKeyComparator(option.keyCmp)),
-		locker: option.locker,
-	}
-}
-
-//Insert inserts a key-value to the map
-func (m *Map) Insert(key, value interface{}) {
-	m.locker.Lock()
-	defer m.locker.Unlock()
-
-	node := m.tree.FindNode(key)
-	if node != nil {
-		node.SetValue(value)
-		return
-	}
-	m.tree.Insert(key, value)
-}
-
-//Get returns the value of the passed key if the key is in the map, otherwise returns nil
-func (m *Map) Get(key interface{}) interface{} {
-	m.locker.RLock()
-	defer m.locker.RUnlock()
-
-	node := m.tree.FindNode(key)
-	if node != nil {
-		return node.Value()
-	}
-	return nil
-}
-
-//Erase erases the node by the passed key from the map if the key in the Map
-func (m *Map) Erase(key interface{}) {
-	m.locker.Lock()
-	defer m.locker.Unlock()
-
-	node := m.tree.FindNode(key)
-	if node != nil {
-		m.tree.Delete(node)
-	}
-}
-
-//EraseIter erases the node that iterator iter point to from the map
-func (m *Map) EraseIter(iter iterator.ConstKvIterator) {
-	m.locker.Lock()
-	defer m.locker.Unlock()
-
-	mpIter, ok := iter.(*MapIterator)
-	if ok {
-		m.tree.Delete(mpIter.node)
-	}
-}
-
-//Find finds a node by the passed key and returns its iterator
-func (m *Map) Find(key interface{}) *MapIterator {
-	m.locker.RLock()
-	defer m.locker.RUnlock()
-
-	node := m.tree.FindNode(key)
-	return &MapIterator{node: node}
-}
-
-//LowerBound finds a node that its key is equal or greater than the passed key and returns its iterator
-func (m *Map) LowerBound(key interface{}) *MapIterator {
-	m.locker.RLock()
-	defer m.locker.RUnlock()
-
-	node := m.tree.FindLowerBoundNode(key)
-	return &MapIterator{node: node}
-}
-
-//UpperBound finds a node that its key is greater than the passed key and returns its iterator
-func (m *Map) UpperBound(key interface{}) *MapIterator {
-	m.locker.RLock()
-	defer m.locker.RUnlock()
-
-	node := m.tree.FindUpperBoundNode(key)
-	return &MapIterator{node: node}
-}
-
-//Begin returns the first node's iterator
-func (m *Map) Begin() *MapIterator {
-	m.locker.RLock()
-	defer m.locker.RUnlock()
-
-	return &MapIterator{node: m.tree.First()}
-}
-
-//First returns the first node's iterator
-func (m *Map) First() *MapIterator {
-	m.locker.RLock()
-	defer m.locker.RUnlock()
-
-	return &MapIterator{node: m.tree.First()}
-}
-
-//Last returns the last node's iterator
-func (m *Map) Last() *MapIterator {
-	m.locker.RLock()
-	defer m.locker.RUnlock()
-
-	return &MapIterator{node: m.tree.Last()}
-}
-
-//Clear clears the map
-func (m *Map) Clear() {
-	m.locker.Lock()
-	defer m.locker.Unlock()
-
-	m.tree.Clear()
-}
-
-// Contains returns true if the key is in the map. otherwise returns false.
-func (m *Map) Contains(key interface{}) bool {
-	m.locker.RLock()
-	defer m.locker.RUnlock()
-
-	if m.tree.Find(key) != nil {
-		return true
-	}
-	return false
-}
-
-// Size returns the amount of elements in the map
-func (m *Map) Size() int {
-	m.locker.RLock()
-	defer m.locker.RUnlock()
-
-	return m.tree.Size()
-}
-
-// Traversal traversals elements in the map, it will not stop until to the end or the visitor returns false
-func (m *Map) Traversal(visitor visitor.KvVisitor) {
-	m.locker.RLock()
-	defer m.locker.RUnlock()
-
-	m.tree.Traversal(visitor)
-}

+ 0 - 94
comm/ds/treemap/map_test.go

@@ -1,94 +0,0 @@
-package treemap
-
-import (
-	"github.com/stretchr/testify/assert"
-	"testing"
-)
-
-func TestMap(t *testing.T) {
-	m := New()
-
-	assert.Equal(t, 0, m.Size())
-	assert.False(t, m.Contains(5))
-	assert.Equal(t, nil, m.Get(3))
-
-	for i := 9; i >= 0; i-- {
-		m.Insert(i, i+1000)
-	}
-
-	assert.Equal(t, 10, m.Size())
-	assert.True(t, m.Contains(5))
-	assert.Equal(t, 3+1000, m.Get(3))
-	m.Erase(3)
-	assert.Equal(t, nil, m.Get(3))
-	m.Clear()
-	assert.False(t, m.Contains(50))
-	assert.Equal(t, 0, m.Size())
-}
-
-func TestMapIterator(t *testing.T) {
-	m := New(WithGoroutineSafe())
-
-	for i := 1; i <= 10; i++ {
-		m.Insert(i, i)
-	}
-
-	i := 1
-	for iter := m.First(); iter.IsValid(); iter.Next() {
-		assert.Equal(t, i, iter.Value().(int))
-		i++
-	}
-
-	i = 10
-	for iter := m.Last().Clone().(*MapIterator); iter.IsValid(); iter.Prev() {
-		assert.Equal(t, i, iter.Value().(int))
-		i--
-	}
-
-	assert.True(t, m.Begin().Equal(m.First()))
-
-	iter := m.Find(8)
-	assert.Equal(t, 8, iter.Key().(int))
-	assert.Equal(t, 8, iter.Value().(int))
-
-	iter = m.LowerBound(8)
-	assert.Equal(t, 8, iter.Value().(int))
-
-	iter = m.UpperBound(6)
-	assert.Equal(t, 7, iter.Value().(int))
-
-	m.EraseIter(iter)
-	assert.False(t, m.Contains(7))
-}
-
-func TestMapIteratorSetValue(t *testing.T) {
-	m := New(WithGoroutineSafe())
-	m.Insert(1, "aaa")
-	m.Insert(2, "bbb")
-	m.Insert(3, "hhh")
-
-	assert.Equal(t, "aaa", m.Get(1))
-
-	iter := m.Find(1)
-
-	assert.Equal(t, "aaa", iter.Value())
-
-	iter.SetValue("ccc")
-	assert.Equal(t, "ccc", m.Get(1))
-}
-
-func TestMap_Traversal(t *testing.T) {
-	m := New()
-
-	for i := 1; i <= 5; i++ {
-		m.Insert(i, i+1000)
-	}
-
-	i := 1
-	m.Traversal(func(key, value interface{}) bool {
-		assert.Equal(t, i, key)
-		assert.Equal(t, i+1000, value)
-		i++
-		return true
-	})
-}

+ 0 - 153
comm/ds/treemap/multimap.go

@@ -1,153 +0,0 @@
-//@File     multimap.go
-//@Time     2022/05/12
-//@Author   #Suyghur,
-package treemap
-
-import (
-	"ylink/comm/ds/rbtree"
-	"ylink/comm/utils/comparator"
-	"ylink/comm/utils/sync"
-	"ylink/comm/utils/visitor"
-)
-
-// MultiMap uses RbTress for internal data structure, and keys can bee repeated.
-type MultiMap struct {
-	tree   *rbtree.RbTree
-	keyCmp comparator.Comparator
-	locker sync.Locker
-}
-
-//NewMultiMap creates a new MultiMap
-func NewMultiMap(opts ...Option) *MultiMap {
-	option := Options{
-		keyCmp: defaultKeyComparator,
-		locker: defaultLocker,
-	}
-	for _, opt := range opts {
-		opt(&option)
-	}
-	return &MultiMap{tree: rbtree.New(rbtree.WithKeyComparator(option.keyCmp)),
-		keyCmp: option.keyCmp,
-		locker: option.locker,
-	}
-}
-
-//Insert inserts a key-value to the MultiMap
-func (mm *MultiMap) Insert(key, value interface{}) {
-	mm.locker.Lock()
-	defer mm.locker.Unlock()
-
-	mm.tree.Insert(key, value)
-}
-
-//Get returns the first node's value by the passed key if the key is in the MultiMap, otherwise returns nil
-func (mm *MultiMap) Get(key interface{}) interface{} {
-	mm.locker.RLock()
-	defer mm.locker.RUnlock()
-
-	node := mm.tree.FindNode(key)
-	if node != nil {
-		return node.Value()
-	}
-	return nil
-}
-
-//Erase erases the key in the MultiMap
-func (mm *MultiMap) Erase(key interface{}) {
-	mm.locker.Lock()
-	defer mm.locker.Unlock()
-
-	for {
-		node := mm.tree.FindNode(key)
-		if node == nil {
-			break
-		}
-		mm.tree.Delete(node)
-	}
-}
-
-//Find finds the node by the passed key in the MultiMap and returns its iterator
-func (mm *MultiMap) Find(key interface{}) *MapIterator {
-	mm.locker.RLock()
-	defer mm.locker.RUnlock()
-
-	node := mm.tree.FindNode(key)
-	return &MapIterator{node: node}
-}
-
-//LowerBound find the first node that its key is equal or greater than the passed key in the MultiMap, and returns its iterator
-func (mm *MultiMap) LowerBound(key interface{}) *MapIterator {
-	mm.locker.RLock()
-	defer mm.locker.RUnlock()
-
-	node := mm.tree.FindLowerBoundNode(key)
-	return &MapIterator{node: node}
-}
-
-//UpperBound find the first node that its key is greater than the passed key in the MultiMap, and returns its iterator
-func (mm *MultiMap) UpperBound(key interface{}) *MapIterator {
-	mm.locker.RLock()
-	defer mm.locker.RUnlock()
-
-	node := mm.tree.FindUpperBoundNode(key)
-	return &MapIterator{node: node}
-}
-
-//Begin returns the first node's iterator
-func (mm *MultiMap) Begin() *MapIterator {
-	mm.locker.RLock()
-	defer mm.locker.RUnlock()
-
-	return &MapIterator{node: mm.tree.First()}
-}
-
-//First returns the first node's iterator
-func (mm *MultiMap) First() *MapIterator {
-	mm.locker.RLock()
-	defer mm.locker.RUnlock()
-
-	return &MapIterator{node: mm.tree.First()}
-}
-
-//Last returns the last node's iterator
-func (mm *MultiMap) Last() *MapIterator {
-	mm.locker.RLock()
-	defer mm.locker.RUnlock()
-
-	return &MapIterator{node: mm.tree.Last()}
-}
-
-//Clear clears the MultiMap
-func (mm *MultiMap) Clear() {
-	mm.locker.Lock()
-	defer mm.locker.Unlock()
-
-	mm.tree.Clear()
-}
-
-// Contains returns true if the passed value is in the MultiMap. otherwise returns false.
-func (mm *MultiMap) Contains(value interface{}) bool {
-	mm.locker.RLock()
-	defer mm.locker.RUnlock()
-
-	if mm.tree.Find(value) != nil {
-		return true
-	}
-	return false
-}
-
-// Size returns the amount of elements in the MultiMap
-func (mm *MultiMap) Size() int {
-	mm.locker.RLock()
-	defer mm.locker.RUnlock()
-
-	return mm.tree.Size()
-}
-
-// Traversal traversals elements in the MultiMap, it will not stop until to the end of the MultiMap or the visitor returns false
-func (mm *MultiMap) Traversal(visitor visitor.KvVisitor) {
-	mm.locker.RLock()
-	defer mm.locker.RUnlock()
-
-	mm.tree.Traversal(visitor)
-}

+ 0 - 82
comm/ds/treemap/multimap_test.go

@@ -1,82 +0,0 @@
-package treemap
-
-import (
-	"github.com/stretchr/testify/assert"
-	"testing"
-)
-
-func TestMultiMap(t *testing.T) {
-	m := NewMultiMap()
-
-	assert.Equal(t, 0, m.Size())
-	assert.False(t, m.Contains(5))
-	assert.Equal(t, nil, m.Get(3))
-
-	for i := 9; i >= 0; i-- {
-		m.Insert(i, i+1000)
-	}
-
-	assert.Equal(t, 10, m.Size())
-	assert.True(t, m.Contains(5))
-	assert.Equal(t, 3+1000, m.Get(3))
-	m.Erase(3)
-	assert.Equal(t, nil, m.Get(3))
-	m.Clear()
-	assert.False(t, m.Contains(50))
-	assert.Equal(t, 0, m.Size())
-}
-
-func TestMultiMapIterator(t *testing.T) {
-	m := NewMultiMap(WithGoroutineSafe())
-
-	for i := 1; i <= 10; i++ {
-		m.Insert(i, i)
-	}
-
-	i := 1
-	for iter := m.First(); iter.IsValid(); iter.Next() {
-		assert.Equal(t, i, iter.Value().(int))
-		i++
-	}
-
-	i = 10
-	for iter := m.Last(); iter.IsValid(); iter.Prev() {
-		assert.Equal(t, i, iter.Value().(int))
-		i--
-	}
-
-	assert.True(t, m.Begin().Equal(m.First()))
-
-	iter := m.Find(8)
-	assert.Equal(t, 8, iter.Value().(int))
-
-	iter = m.LowerBound(8)
-	assert.Equal(t, 8, iter.Value().(int))
-
-	iter = m.UpperBound(5)
-	assert.Equal(t, 6, iter.Value().(int))
-}
-
-func TestMultiMap_Traversal(t *testing.T) {
-	m := NewMultiMap()
-
-	for i := 1; i <= 5; i++ {
-		m.Insert(i, i+1000)
-	}
-
-	for i := 1; i <= 5; i++ {
-		m.Insert(i, i+1000)
-	}
-
-	i := 1
-	count := 0
-	m.Traversal(func(key, value interface{}) bool {
-		assert.Equal(t, i, key)
-		assert.Equal(t, i+1000, value)
-		count++
-		if count%2 == 0 {
-			i++
-		}
-		return true
-	})
-}

+ 0 - 379
comm/utils/comparator/comparator.go

@@ -1,379 +0,0 @@
-//@File     comparator.go
-//@Time     2022/05/12
-//@Author   #Suyghur,
-
-package comparator
-
-// Comparator Should return a number:
-//    -1 , if a < b
-//    0  , if a == b
-//    1  , if a > b
-type Comparator func(a, b interface{}) int
-
-// BuiltinTypeComparator compare a with b
-//    -1 , if a < b
-//    0  , if a == b
-//    1  , if a > b
-// make sure a and b are both builtin type
-func BuiltinTypeComparator(a, b interface{}) int {
-	if a == b {
-		return 0
-	}
-	switch a.(type) {
-	case int, uint, int8, uint8, int16, uint16, int32, uint32, int64, uint64, uintptr:
-		return cmpInt(a, b)
-	case float32:
-		if a.(float32) < b.(float32) {
-			return -1
-		}
-	case float64:
-		if a.(float64) < b.(float64) {
-			return -1
-		}
-	case bool:
-		if a.(bool) == false && b.(bool) == true {
-			return -1
-		}
-	case string:
-		if a.(string) < b.(string) {
-			return -1
-		}
-	case complex64:
-		return cmpComplex64(a.(complex64), b.(complex64))
-	case complex128:
-		return cmpComplex128(a.(complex128), b.(complex128))
-	}
-	return 1
-}
-
-func cmpInt(a, b interface{}) int {
-	switch a.(type) {
-	case int:
-		return cmpInt64(int64(a.(int)), int64(b.(int)))
-	case uint:
-		return cmpUint64(uint64(a.(uint)), uint64(b.(uint)))
-	case int8:
-		return cmpInt64(int64(a.(int8)), int64(b.(int8)))
-	case uint8:
-		return cmpUint64(uint64(a.(uint8)), uint64(b.(uint8)))
-	case int16:
-		return cmpInt64(int64(a.(int16)), int64(b.(int16)))
-	case uint16:
-		return cmpUint64(uint64(a.(uint16)), uint64(b.(uint16)))
-	case int32:
-		return cmpInt64(int64(a.(int32)), int64(b.(int32)))
-	case uint32:
-		return cmpUint64(uint64(a.(uint32)), uint64(b.(uint32)))
-	case int64:
-		return cmpInt64(a.(int64), b.(int64))
-	case uint64:
-		return cmpUint64(a.(uint64), b.(uint64))
-	case uintptr:
-		return cmpUint64(uint64(a.(uintptr)), uint64(b.(uintptr)))
-	}
-
-	return 0
-}
-
-func cmpInt64(a, b int64) int {
-	if a < b {
-		return -1
-	}
-	return 1
-}
-
-func cmpUint64(a, b uint64) int {
-	if a < b {
-		return -1
-	}
-	return 1
-}
-
-func cmpFloat32(a, b float32) int {
-	if a < b {
-		return -1
-	}
-	return 1
-}
-
-func cmpFloat64(a, b float64) int {
-	if a < b {
-		return -1
-	}
-	return 1
-}
-
-func cmpComplex64(a, b complex64) int {
-	if real(a) < real(b) {
-		return -1
-	}
-	if real(a) == real(b) && imag(a) < imag(b) {
-		return -1
-	}
-	return 1
-}
-
-func cmpComplex128(a, b complex128) int {
-	if real(a) < real(b) {
-		return -1
-	}
-	if real(a) == real(b) && imag(a) < imag(b) {
-		return -1
-	}
-	return 1
-}
-
-//Reverse returns a comparator reverse to cmp
-func Reverse(cmp Comparator) Comparator {
-	return func(a, b interface{}) int {
-		return -cmp(a, b)
-	}
-}
-
-// IntComparator compare a with b
-//    -1 , if a < b
-//    0  , if a == b
-//    1  , if a > b
-func IntComparator(a, b interface{}) int {
-	if a == b {
-		return 0
-	}
-	if a.(int) < b.(int) {
-		return -1
-	}
-	return 1
-}
-
-// UintComparator compare a with b
-//    -1 , if a < b
-//    0  , if a == b
-//    1  , if a > b
-func UintComparator(a, b interface{}) int {
-	if a == b {
-		return 0
-	}
-	if a.(uint) < b.(uint) {
-		return -1
-	}
-	return 1
-}
-
-// Int8Comparator compare a with b
-//    -1 , if a < b
-//    0  , if a == b
-//    1  , if a > b
-func Int8Comparator(a, b interface{}) int {
-	if a == b {
-		return 0
-	}
-	if a.(int8) < b.(int8) {
-		return -1
-	}
-	return 1
-}
-
-// Uint8Comparator compare a with b
-//    -1 , if a < b
-//    0  , if a == b
-//    1  , if a > b
-func Uint8Comparator(a, b interface{}) int {
-	if a == b {
-		return 0
-	}
-	if a.(uint8) < b.(uint8) {
-		return -1
-	}
-	return 1
-}
-
-// Int16Comparator compare a with b
-//    -1 , if a < b
-//    0  , if a == b
-//    1  , if a > b
-func Int16Comparator(a, b interface{}) int {
-	if a == b {
-		return 0
-	}
-	if a.(int16) < b.(int16) {
-		return -1
-	}
-	return 1
-}
-
-// Uint16Comparator compare a with b
-//    -1 , if a < b
-//    0  , if a == b
-//    1  , if a > b
-func Uint16Comparator(a, b interface{}) int {
-	if a == b {
-		return 0
-	}
-	if a.(uint16) < b.(uint16) {
-		return -1
-	}
-	return 1
-}
-
-// Int32Comparator compare a with b
-//    -1 , if a < b
-//    0  , if a == b
-//    1  , if a > b
-func Int32Comparator(a, b interface{}) int {
-	if a == b {
-		return 0
-	}
-	if a.(int32) < b.(int32) {
-		return -1
-	}
-	return 1
-}
-
-// Uint32Comparator compare a with b
-//    -1 , if a < b
-//    0  , if a == b
-//    1  , if a > b
-func Uint32Comparator(a, b interface{}) int {
-	if a == b {
-		return 0
-	}
-	if a.(uint32) < b.(uint32) {
-		return -1
-	}
-	return 1
-}
-
-// Int64Comparator compare a with b
-//    -1 , if a < b
-//    0  , if a == b
-//    1  , if a > b
-func Int64Comparator(a, b interface{}) int {
-	if a == b {
-		return 0
-	}
-	if a.(int64) < b.(int64) {
-		return -1
-	}
-	return 1
-}
-
-// Uint64Comparator compare a with b
-//    -1 , if a < b
-//    0  , if a == b
-//    1  , if a > b
-func Uint64Comparator(a, b interface{}) int {
-	if a == b {
-		return 0
-	}
-	if a.(uint64) < b.(uint64) {
-		return -1
-	}
-	return 1
-}
-
-// Float32Comparator compare a with b
-//    -1 , if a < b
-//    0  , if a == b
-//    1  , if a > b
-func Float32Comparator(a, b interface{}) int {
-	if a == b {
-		return 0
-	}
-	if a.(float32) < b.(float32) {
-		return -1
-	}
-	return 1
-}
-
-// Float64Comparator compare a with b
-//    -1 , if a < b
-//    0  , if a == b
-//    1  , if a > b
-func Float64Comparator(a, b interface{}) int {
-	if a == b {
-		return 0
-	}
-	if a.(float64) < b.(float64) {
-		return -1
-	}
-	return 1
-}
-
-// StringComparator compare a with b
-//    -1 , if a < b
-//    0  , if a == b
-//    1  , if a > b
-func StringComparator(a, b interface{}) int {
-	if a == b {
-		return 0
-	}
-	if a.(string) < b.(string) {
-		return -1
-	}
-	return 1
-}
-
-// UintptrComparator compare a with b
-//    -1 , if a < b
-//    0  , if a == b
-//    1  , if a > b
-func UintptrComparator(a, b interface{}) int {
-	if a == b {
-		return 0
-	}
-	if a.(uintptr) < b.(uintptr) {
-		return -1
-	}
-	return 1
-}
-
-// BoolComparator compare a with b
-//    -1 , if a < b
-//    0  , if a == b
-//    1  , if a > b
-func BoolComparator(a, b interface{}) int {
-	if a == b {
-		return 0
-	}
-	if a.(bool) == false && b.(bool) == true {
-		return -1
-	}
-	return 1
-}
-
-// Complex64Comparator compare a with b
-//    -1 , if a < b
-//    0  , if a == b
-//    1  , if a > b
-func Complex64Comparator(a, b interface{}) int {
-	if a == b {
-		return 0
-	}
-	comA := a.(complex64)
-	comB := b.(complex64)
-	if real(comA) < real(comB) {
-		return -1
-	}
-	if real(comA) == real(comB) && imag(comA) < imag(comB) {
-		return -1
-	}
-	return 1
-}
-
-// Complex128Comparator compare a with b
-//    -1 , if a < b
-//    0  , if a == b
-//    1  , if a > b
-func Complex128Comparator(a, b interface{}) int {
-	if a == b {
-		return 0
-	}
-	comA := a.(complex128)
-	comB := b.(complex128)
-	if real(comA) < real(comB) {
-		return -1
-	}
-	if real(comA) == real(comB) && imag(comA) < imag(comB) {
-		return -1
-	}
-	return 1
-}

+ 0 - 64
comm/utils/iterator/iterator.go

@@ -1,64 +0,0 @@
-//@File     iterator.go
-//@Time     2022/05/12
-//@Author   #Suyghur,
-
-package iterator
-
-type ConstIterator interface {
-	IsValid() bool
-	Next() ConstIterator
-	Value() interface{}
-	Clone() ConstIterator
-	Equal(other ConstIterator) bool
-}
-
-// Iterator is an interface of mutable iterator
-type Iterator interface {
-	ConstIterator
-	SetValue(value interface{})
-}
-
-// ConstKvIterator is an interface of const key-value type iterator
-type ConstKvIterator interface {
-	ConstIterator
-	Key() interface{}
-}
-
-// KvIterator is an interface of mutable key-value type iterator
-type KvIterator interface {
-	ConstKvIterator
-	SetValue(value interface{})
-}
-
-// ConstBidIterator is an interface of const bidirectional iterator
-type ConstBidIterator interface {
-	ConstIterator
-	Prev() ConstBidIterator
-}
-
-// BidIterator is an interface of mutable bidirectional iterator
-type BidIterator interface {
-	ConstBidIterator
-	SetValue(value interface{})
-}
-
-// ConstKvBidIterator is an interface of const key-value type bidirectional iterator
-type ConstKvBidIterator interface {
-	ConstKvIterator
-	Prev() ConstBidIterator
-}
-
-// KvBidIterator is an interface of mutable key-value type bidirectional iterator
-type KvBidIterator interface {
-	ConstKvIterator
-	Prev() ConstBidIterator
-	SetValue(value interface{})
-}
-
-// RandomAccessIterator is an interface of mutable random access iterator
-type RandomAccessIterator interface {
-	BidIterator
-	//IteratorAt returns a new iterator at position
-	IteratorAt(position int) RandomAccessIterator
-	Position() int
-}

+ 0 - 39
comm/utils/sync/locker.go

@@ -1,39 +0,0 @@
-//@File     locker.go
-//@Time     2022/05/12
-//@Author   #Suyghur,
-
-package sync
-
-import gosync "sync"
-
-type Locker interface {
-	Lock()
-	Unlock()
-	RLock()
-	RUnlock()
-}
-
-var _ Locker = (*gosync.RWMutex)(nil)
-
-type FakeLocker struct {
-}
-
-// Lock does nothing
-func (l FakeLocker) Lock() {
-
-}
-
-// Unlock does nothing
-func (l FakeLocker) Unlock() {
-
-}
-
-// RLock does nothing
-func (l FakeLocker) RLock() {
-
-}
-
-// RUnlock does nothing
-func (l FakeLocker) RUnlock() {
-
-}

+ 0 - 9
comm/utils/visitor/visitor.go

@@ -1,9 +0,0 @@
-//@File     visitor.go
-//@Time     2022/05/12
-//@Author   #Suyghur,
-
-package visitor
-
-type Visitor func(value interface{}) bool
-
-type KvVisitor func(key, value interface{}) bool

+ 8 - 0
core/inner/rpc/inner/inner.go

@@ -21,12 +21,15 @@ type (
 	InnerPlayerDisconnectResp   = pb.InnerPlayerDisconnectResp
 	InnerPlayerFetchCsInfoReq   = pb.InnerPlayerFetchCsInfoReq
 	InnerPlayerFetchCsInfoResp  = pb.InnerPlayerFetchCsInfoResp
+	UpdateUserStatusReq         = pb.UpdateUserStatusReq
+	UpdateUserStatusResp        = pb.UpdateUserStatusResp
 
 	Inner interface {
 		PlayerFetchCsInfo(ctx context.Context, in *InnerPlayerFetchCsInfoReq, opts ...grpc.CallOption) (*InnerPlayerFetchCsInfoResp, error)
 		PlayerDisconnect(ctx context.Context, in *InnerPlayerDisconnectReq, opts ...grpc.CallOption) (*InnerPlayerDisconnectResp, error)
 		CsFetchPlayerQueue(ctx context.Context, in *InnerCsFetchPlayerQueueReq, opts ...grpc.CallOption) (*InnerCsFetchPlayerQueueResp, error)
 		CsConnectPlayer(ctx context.Context, in *InnerCsConnectPlayerReq, opts ...grpc.CallOption) (*InnerCsConnectPlayerResp, error)
+		UpdateUserStatus(ctx context.Context, in *UpdateUserStatusReq, opts ...grpc.CallOption) (*UpdateUserStatusResp, error)
 	}
 
 	defaultInner struct {
@@ -59,3 +62,8 @@ func (m *defaultInner) CsConnectPlayer(ctx context.Context, in *InnerCsConnectPl
 	client := pb.NewInnerClient(m.cli.Conn())
 	return client.CsConnectPlayer(ctx, in, opts...)
 }
+
+func (m *defaultInner) UpdateUserStatus(ctx context.Context, in *UpdateUserStatusReq, opts ...grpc.CallOption) (*UpdateUserStatusResp, error) {
+	client := pb.NewInnerClient(m.cli.Conn())
+	return client.UpdateUserStatus(ctx, in, opts...)
+}

+ 8 - 4
core/inner/rpc/internal/ext/global.go

@@ -4,10 +4,14 @@
 
 package ext
 
-import "ylink/comm/ds/treemap"
+import (
+	treemap "github.com/liyue201/gostl/ds/map"
+	"github.com/liyue201/gostl/ds/set"
+)
 
 var (
-	IdMap *treemap.Map
-	CsMap *treemap.Map
-	// PlayerStatMap
+	Game2PlayerMap     *treemap.Map
+	CsMap              *treemap.Map
+	Game2PlayerStatMap *treemap.Map
+	CsStatSet          *set.Set
 )

+ 61 - 0
core/inner/rpc/internal/logic/updateuserstatuslogic.go

@@ -0,0 +1,61 @@
+package logic
+
+import (
+	"context"
+	"github.com/liyue201/gostl/ds/set"
+	"github.com/pkg/errors"
+	"ylink/comm/globalkey"
+	"ylink/comm/result"
+	"ylink/core/inner/rpc/internal/ext"
+
+	"ylink/core/inner/rpc/internal/svc"
+	"ylink/core/inner/rpc/pb"
+
+	"github.com/zeromicro/go-zero/core/logx"
+)
+
+type UpdateUserStatusLogic struct {
+	ctx    context.Context
+	svcCtx *svc.ServiceContext
+	logx.Logger
+}
+
+func NewUpdateUserStatusLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UpdateUserStatusLogic {
+	return &UpdateUserStatusLogic{
+		ctx:    ctx,
+		svcCtx: svcCtx,
+		Logger: logx.WithContext(ctx),
+	}
+}
+
+func (l *UpdateUserStatusLogic) UpdateUserStatus(in *pb.UpdateUserStatusReq) (*pb.UpdateUserStatusResp, error) {
+	switch in.Type {
+	case globalkey.CONNECT_TYPE_PLAYER:
+		// 修改玩家在线状态
+		if ext.Game2PlayerStatMap.Contains(in.GameId) {
+			// 有则取出玩家的set
+			playerStatSet := ext.Game2PlayerStatMap.Get(in.GameId).(*set.Set)
+			if playerStatSet.Contains(in.Uid) {
+				// 有则清除,代表下线
+				playerStatSet.Erase(in.Uid)
+			} else {
+				playerStatSet.Insert(in.Uid)
+			}
+		} else {
+			playerStatSet := set.New()
+			playerStatSet.Insert(in.Uid)
+			ext.Game2PlayerStatMap.Insert(in.GameId, playerStatSet)
+		}
+	case globalkey.CONNECT_TYPE_CS:
+		// 修改客服在线状态
+		if ext.CsStatSet.Contains(in.Uid) {
+			// 有则清除,代表下线
+			ext.CsStatSet.Erase(in.Uid)
+		} else {
+			ext.CsStatSet.Insert(in.Uid)
+		}
+	default:
+		return nil, errors.Wrap(result.NewErrMsg("no such user type"), "")
+	}
+	return &pb.UpdateUserStatusResp{}, nil
+}

+ 5 - 105
core/inner/rpc/internal/server/innerserver.go

@@ -5,21 +5,7 @@ package server
 
 import (
 	"context"
-	"encoding/json"
-	"github.com/Shopify/sarama"
-	"github.com/zeromicro/go-zero/core/logx"
-	gozerotrace "github.com/zeromicro/go-zero/core/trace"
-	"go.opentelemetry.io/otel"
-	"go.opentelemetry.io/otel/attribute"
-	"go.opentelemetry.io/otel/propagation"
-	oteltrace "go.opentelemetry.io/otel/trace"
-	"net/http"
-	"ylink/comm/ds/treemap"
-	"ylink/comm/kafka"
-	"ylink/comm/model"
-	"ylink/comm/trace"
-	"ylink/comm/utils"
-	"ylink/core/inner/rpc/internal/ext"
+
 	"ylink/core/inner/rpc/internal/logic"
 	"ylink/core/inner/rpc/internal/svc"
 	"ylink/core/inner/rpc/pb"
@@ -28,23 +14,12 @@ import (
 type InnerServer struct {
 	svcCtx *svc.ServiceContext
 	pb.UnimplementedInnerServer
-	ConsumerGroup *kafka.ConsumerGroup
 }
 
 func NewInnerServer(svcCtx *svc.ServiceContext) *InnerServer {
-	server := &InnerServer{
+	return &InnerServer{
 		svcCtx: svcCtx,
-		ConsumerGroup: kafka.NewConsumerGroup(&kafka.ConsumerGroupConfig{
-			KafkaVersion:   sarama.V1_0_0_0,
-			OffsetsInitial: sarama.OffsetNewest,
-			IsReturnErr:    false,
-		},
-			svcCtx.Config.KqMsgBoxConsumerConf.Brokers,
-			[]string{svcCtx.Config.KqMsgBoxConsumerConf.Topic},
-			svcCtx.Config.KqMsgBoxConsumerConf.GroupId),
 	}
-	server.subscribe()
-	return server
 }
 
 func (s *InnerServer) PlayerFetchCsInfo(ctx context.Context, in *pb.InnerPlayerFetchCsInfoReq) (*pb.InnerPlayerFetchCsInfoResp, error) {
@@ -67,82 +42,7 @@ func (s *InnerServer) CsConnectPlayer(ctx context.Context, in *pb.InnerCsConnect
 	return l.CsConnectPlayer(in)
 }
 
-func (s *InnerServer) Setup(_ sarama.ConsumerGroupSession) error {
-	return nil
-}
-
-func (s *InnerServer) Cleanup(_ sarama.ConsumerGroupSession) error {
-	return nil
-}
-
-func (s *InnerServer) ConsumeClaim(sess sarama.ConsumerGroupSession, claim sarama.ConsumerGroupClaim) error {
-	for msg := range claim.Messages() {
-		if msg.Topic == s.svcCtx.Config.KqMsgBoxConsumerConf.Topic {
-			s.handleMessage(sess, msg)
-		}
-	}
-	return nil
-}
-
-func (s *InnerServer) runWithCtx(callback func(ctx context.Context), kv ...attribute.KeyValue) {
-	propagator := otel.GetTextMapPropagator()
-	tracer := otel.GetTracerProvider().Tracer(gozerotrace.TraceName)
-	ctx := propagator.Extract(context.Background(), propagation.HeaderCarrier(http.Header{}))
-	spanName := utils.CallerFuncName()
-	spanCtx, span := tracer.Start(ctx, spanName, oteltrace.WithSpanKind(oteltrace.SpanKindServer), oteltrace.WithAttributes(kv...))
-	defer span.End()
-	propagator.Inject(spanCtx, propagation.HeaderCarrier(http.Header{}))
-	callback(spanCtx)
-}
-
-func (s *InnerServer) handleMessage(sess sarama.ConsumerGroupSession, msg *sarama.ConsumerMessage) {
-	traceId := kafka.GetTraceFromHeader(msg.Headers)
-	if len(traceId) == 0 {
-		return
-	}
-	trace.RunOnTracing(traceId, func(ctx context.Context) {
-		var message model.KqMessage
-		if err := json.Unmarshal(msg.Value, &message); err != nil {
-			logx.WithContext(ctx).Errorf("unmarshal msg error: %v", err)
-			return
-		}
-		trace.StartTrace(ctx, "InnerServer.handleMessage.SendMessage", func(ctx context.Context) {
-			if len(message.ReceiverId) == 0 || message.ReceiverId == "" {
-				// 玩家发的消息
-				p2cMap := ext.IdMap.Get(message.GameId).(*treemap.Map)
-				message.ReceiverId = p2cMap.Get(message.SenderId).(string)
-				logx.WithContext(ctx).Infof("receiver: %s", message.ReceiverId)
-				kMsg, _ := json.Marshal(message)
-				s.svcCtx.KqMsgBoxProducer.SendMessage(ctx, string(kMsg), message.ReceiverId)
-			} else {
-				s.svcCtx.KqMsgBoxProducer.SendMessage(ctx, string(msg.Value), message.ReceiverId)
-			}
-			sess.MarkMessage(msg, "")
-		}, attribute.String("msg.key", string(msg.Key)))
-	})
-
-	//s.runWithCtx(func(ctx context.Context) {
-	//	var message model.KqCmdMessage
-	//	if err := json.Unmarshal(msg.Value, &message); err != nil {
-	//		logx.WithContext(ctx).Errorf("unmarshal msg error: %v", err)
-	//		return
-	//	}
-	//	trace.StartTrace(ctx, "InnerServer.handleMessage.SendMessage", func(ctx context.Context) {
-	//		if len(message.ReceiverId) == 0 || message.ReceiverId == "" {
-	//			// 玩家发的消息
-	//			p2cMap := ext.IdMap.Get(message.GameId).(*treemap.Map)
-	//			message.ReceiverId = p2cMap.Get(message.SenderId).(string)
-	//			logx.Infof("receiver: %s", message.ReceiverId)
-	//			b, _ := json.Marshal(message)
-	//			s.svcCtx.KqMsgBoxProducer.SendMessage(ctx, string(b), message.ReceiverId)
-	//		} else {
-	//			s.svcCtx.KqMsgBoxProducer.SendMessage(ctx, string(msg.Value), message.ReceiverId)
-	//		}
-	//		sess.MarkMessage(msg, "")
-	//	}, attribute.String("msg.key", string(msg.Key)))
-	//})
-}
-
-func (s *InnerServer) subscribe() {
-	go s.ConsumerGroup.RegisterHandleAndConsumer(s)
+func (s *InnerServer) UpdateUserStatus(ctx context.Context, in *pb.UpdateUserStatusReq) (*pb.UpdateUserStatusResp, error) {
+	l := logic.NewUpdateUserStatusLogic(ctx, s.svcCtx)
+	return l.UpdateUserStatus(in)
 }

+ 4 - 4
core/inner/rpc/internal/svc/servicecontext.go

@@ -1,7 +1,7 @@
 package svc
 
 import (
-	"ylink/comm/ds/treemap"
+	treemap "github.com/liyue201/gostl/ds/map"
 	"ylink/comm/kafka"
 	"ylink/comm/model"
 	"ylink/core/inner/rpc/internal/config"
@@ -27,7 +27,7 @@ func fetchCsCenterInfo() {
 }
 
 func mockInfo() {
-	ext.IdMap = treemap.New(treemap.WithGoroutineSafe())
+	ext.Game2PlayerMap = treemap.New(treemap.WithGoroutineSafe())
 	ext.CsMap = treemap.New(treemap.WithGoroutineSafe())
 
 	// 已连接的映射
@@ -40,8 +40,8 @@ func mockInfo() {
 	game1111P2cMap := treemap.New(treemap.WithGoroutineSafe())
 	game1111P2cMap.Insert("player1231", "cs_1111")
 
-	ext.IdMap.Insert("game1231", game1231P2cMap)
-	ext.IdMap.Insert("game1111", game1111P2cMap)
+	ext.Game2PlayerMap.Insert("game1231", game1231P2cMap)
+	ext.Game2PlayerMap.Insert("game1111", game1111P2cMap)
 
 	ext.CsMap.Insert("cs_1231", &model.CsInfo{
 		CsId:         "cs_1231",

+ 181 - 39
core/inner/rpc/pb/inner.pb.go

@@ -463,6 +463,107 @@ func (*InnerCsConnectPlayerResp) Descriptor() ([]byte, []int) {
 	return file_pb_inner_proto_rawDescGZIP(), []int{7}
 }
 
+type UpdateUserStatusReq struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	Type   int64   `protobuf:"varint,1,opt,name=type,proto3" json:"type,omitempty"`
+	Uid    string  `protobuf:"bytes,2,opt,name=uid,proto3" json:"uid,omitempty"`
+	GameId *string `protobuf:"bytes,3,opt,name=game_id,json=gameId,proto3,oneof" json:"game_id,omitempty"`
+}
+
+func (x *UpdateUserStatusReq) Reset() {
+	*x = UpdateUserStatusReq{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_pb_inner_proto_msgTypes[8]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *UpdateUserStatusReq) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*UpdateUserStatusReq) ProtoMessage() {}
+
+func (x *UpdateUserStatusReq) ProtoReflect() protoreflect.Message {
+	mi := &file_pb_inner_proto_msgTypes[8]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use UpdateUserStatusReq.ProtoReflect.Descriptor instead.
+func (*UpdateUserStatusReq) Descriptor() ([]byte, []int) {
+	return file_pb_inner_proto_rawDescGZIP(), []int{8}
+}
+
+func (x *UpdateUserStatusReq) GetType() int64 {
+	if x != nil {
+		return x.Type
+	}
+	return 0
+}
+
+func (x *UpdateUserStatusReq) GetUid() string {
+	if x != nil {
+		return x.Uid
+	}
+	return ""
+}
+
+func (x *UpdateUserStatusReq) GetGameId() string {
+	if x != nil && x.GameId != nil {
+		return *x.GameId
+	}
+	return ""
+}
+
+type UpdateUserStatusResp struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+}
+
+func (x *UpdateUserStatusResp) Reset() {
+	*x = UpdateUserStatusResp{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_pb_inner_proto_msgTypes[9]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *UpdateUserStatusResp) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*UpdateUserStatusResp) ProtoMessage() {}
+
+func (x *UpdateUserStatusResp) ProtoReflect() protoreflect.Message {
+	mi := &file_pb_inner_proto_msgTypes[9]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use UpdateUserStatusResp.ProtoReflect.Descriptor instead.
+func (*UpdateUserStatusResp) Descriptor() ([]byte, []int) {
+	return file_pb_inner_proto_rawDescGZIP(), []int{9}
+}
+
 var File_pb_inner_proto protoreflect.FileDescriptor
 
 var file_pb_inner_proto_rawDesc = []byte{
@@ -512,29 +613,41 @@ var file_pb_inner_proto_rawDesc = []byte{
 	0x12, 0x17, 0x0a, 0x07, 0x67, 0x61, 0x6d, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28,
 	0x09, 0x52, 0x06, 0x67, 0x61, 0x6d, 0x65, 0x49, 0x64, 0x22, 0x1a, 0x0a, 0x18, 0x49, 0x6e, 0x6e,
 	0x65, 0x72, 0x43, 0x73, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x50, 0x6c, 0x61, 0x79, 0x65,
-	0x72, 0x52, 0x65, 0x73, 0x70, 0x32, 0xd1, 0x02, 0x0a, 0x05, 0x49, 0x6e, 0x6e, 0x65, 0x72, 0x12,
-	0x52, 0x0a, 0x11, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x46, 0x65, 0x74, 0x63, 0x68, 0x43, 0x73,
-	0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1d, 0x2e, 0x70, 0x62, 0x2e, 0x49, 0x6e, 0x6e, 0x65, 0x72, 0x50,
-	0x6c, 0x61, 0x79, 0x65, 0x72, 0x46, 0x65, 0x74, 0x63, 0x68, 0x43, 0x73, 0x49, 0x6e, 0x66, 0x6f,
-	0x52, 0x65, 0x71, 0x1a, 0x1e, 0x2e, 0x70, 0x62, 0x2e, 0x49, 0x6e, 0x6e, 0x65, 0x72, 0x50, 0x6c,
+	0x72, 0x52, 0x65, 0x73, 0x70, 0x22, 0x65, 0x0a, 0x13, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55,
+	0x73, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x12, 0x12, 0x0a, 0x04,
+	0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65,
+	0x12, 0x10, 0x0a, 0x03, 0x75, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75,
+	0x69, 0x64, 0x12, 0x1c, 0x0a, 0x07, 0x67, 0x61, 0x6d, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20,
+	0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x06, 0x67, 0x61, 0x6d, 0x65, 0x49, 0x64, 0x88, 0x01, 0x01,
+	0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x67, 0x61, 0x6d, 0x65, 0x5f, 0x69, 0x64, 0x22, 0x16, 0x0a, 0x14,
+	0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73,
+	0x52, 0x65, 0x73, 0x70, 0x32, 0x98, 0x03, 0x0a, 0x05, 0x49, 0x6e, 0x6e, 0x65, 0x72, 0x12, 0x52,
+	0x0a, 0x11, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x46, 0x65, 0x74, 0x63, 0x68, 0x43, 0x73, 0x49,
+	0x6e, 0x66, 0x6f, 0x12, 0x1d, 0x2e, 0x70, 0x62, 0x2e, 0x49, 0x6e, 0x6e, 0x65, 0x72, 0x50, 0x6c,
 	0x61, 0x79, 0x65, 0x72, 0x46, 0x65, 0x74, 0x63, 0x68, 0x43, 0x73, 0x49, 0x6e, 0x66, 0x6f, 0x52,
-	0x65, 0x73, 0x70, 0x12, 0x4f, 0x0a, 0x10, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x44, 0x69, 0x73,
-	0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x12, 0x1c, 0x2e, 0x70, 0x62, 0x2e, 0x49, 0x6e, 0x6e,
-	0x65, 0x72, 0x50, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x6e, 0x65,
-	0x63, 0x74, 0x52, 0x65, 0x71, 0x1a, 0x1d, 0x2e, 0x70, 0x62, 0x2e, 0x49, 0x6e, 0x6e, 0x65, 0x72,
-	0x50, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74,
-	0x52, 0x65, 0x73, 0x70, 0x12, 0x55, 0x0a, 0x12, 0x63, 0x73, 0x46, 0x65, 0x74, 0x63, 0x68, 0x50,
-	0x6c, 0x61, 0x79, 0x65, 0x72, 0x51, 0x75, 0x65, 0x75, 0x65, 0x12, 0x1e, 0x2e, 0x70, 0x62, 0x2e,
-	0x49, 0x6e, 0x6e, 0x65, 0x72, 0x43, 0x73, 0x46, 0x65, 0x74, 0x63, 0x68, 0x50, 0x6c, 0x61, 0x79,
-	0x65, 0x72, 0x51, 0x75, 0x65, 0x75, 0x65, 0x52, 0x65, 0x71, 0x1a, 0x1f, 0x2e, 0x70, 0x62, 0x2e,
-	0x49, 0x6e, 0x6e, 0x65, 0x72, 0x43, 0x73, 0x46, 0x65, 0x74, 0x63, 0x68, 0x50, 0x6c, 0x61, 0x79,
-	0x65, 0x72, 0x51, 0x75, 0x65, 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, 0x12, 0x4c, 0x0a, 0x0f, 0x63,
-	0x73, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x50, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x12, 0x1b,
-	0x2e, 0x70, 0x62, 0x2e, 0x49, 0x6e, 0x6e, 0x65, 0x72, 0x43, 0x73, 0x43, 0x6f, 0x6e, 0x6e, 0x65,
-	0x63, 0x74, 0x50, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x52, 0x65, 0x71, 0x1a, 0x1c, 0x2e, 0x70, 0x62,
-	0x2e, 0x49, 0x6e, 0x6e, 0x65, 0x72, 0x43, 0x73, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x50,
-	0x6c, 0x61, 0x79, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x42, 0x06, 0x5a, 0x04, 0x2e, 0x2f, 0x70,
-	0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+	0x65, 0x71, 0x1a, 0x1e, 0x2e, 0x70, 0x62, 0x2e, 0x49, 0x6e, 0x6e, 0x65, 0x72, 0x50, 0x6c, 0x61,
+	0x79, 0x65, 0x72, 0x46, 0x65, 0x74, 0x63, 0x68, 0x43, 0x73, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65,
+	0x73, 0x70, 0x12, 0x4f, 0x0a, 0x10, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x44, 0x69, 0x73, 0x63,
+	0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x12, 0x1c, 0x2e, 0x70, 0x62, 0x2e, 0x49, 0x6e, 0x6e, 0x65,
+	0x72, 0x50, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63,
+	0x74, 0x52, 0x65, 0x71, 0x1a, 0x1d, 0x2e, 0x70, 0x62, 0x2e, 0x49, 0x6e, 0x6e, 0x65, 0x72, 0x50,
+	0x6c, 0x61, 0x79, 0x65, 0x72, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x52,
+	0x65, 0x73, 0x70, 0x12, 0x55, 0x0a, 0x12, 0x63, 0x73, 0x46, 0x65, 0x74, 0x63, 0x68, 0x50, 0x6c,
+	0x61, 0x79, 0x65, 0x72, 0x51, 0x75, 0x65, 0x75, 0x65, 0x12, 0x1e, 0x2e, 0x70, 0x62, 0x2e, 0x49,
+	0x6e, 0x6e, 0x65, 0x72, 0x43, 0x73, 0x46, 0x65, 0x74, 0x63, 0x68, 0x50, 0x6c, 0x61, 0x79, 0x65,
+	0x72, 0x51, 0x75, 0x65, 0x75, 0x65, 0x52, 0x65, 0x71, 0x1a, 0x1f, 0x2e, 0x70, 0x62, 0x2e, 0x49,
+	0x6e, 0x6e, 0x65, 0x72, 0x43, 0x73, 0x46, 0x65, 0x74, 0x63, 0x68, 0x50, 0x6c, 0x61, 0x79, 0x65,
+	0x72, 0x51, 0x75, 0x65, 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, 0x12, 0x4c, 0x0a, 0x0f, 0x63, 0x73,
+	0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x50, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x12, 0x1b, 0x2e,
+	0x70, 0x62, 0x2e, 0x49, 0x6e, 0x6e, 0x65, 0x72, 0x43, 0x73, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63,
+	0x74, 0x50, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x52, 0x65, 0x71, 0x1a, 0x1c, 0x2e, 0x70, 0x62, 0x2e,
+	0x49, 0x6e, 0x6e, 0x65, 0x72, 0x43, 0x73, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x50, 0x6c,
+	0x61, 0x79, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x12, 0x45, 0x0a, 0x10, 0x75, 0x70, 0x64, 0x61,
+	0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x17, 0x2e, 0x70,
+	0x62, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74,
+	0x75, 0x73, 0x52, 0x65, 0x71, 0x1a, 0x18, 0x2e, 0x70, 0x62, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74,
+	0x65, 0x55, 0x73, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x42,
+	0x06, 0x5a, 0x04, 0x2e, 0x2f, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
 }
 
 var (
@@ -549,7 +662,7 @@ func file_pb_inner_proto_rawDescGZIP() []byte {
 	return file_pb_inner_proto_rawDescData
 }
 
-var file_pb_inner_proto_msgTypes = make([]protoimpl.MessageInfo, 8)
+var file_pb_inner_proto_msgTypes = make([]protoimpl.MessageInfo, 10)
 var file_pb_inner_proto_goTypes = []interface{}{
 	(*InnerPlayerFetchCsInfoReq)(nil),   // 0: pb.InnerPlayerFetchCsInfoReq
 	(*InnerPlayerFetchCsInfoResp)(nil),  // 1: pb.InnerPlayerFetchCsInfoResp
@@ -559,23 +672,27 @@ var file_pb_inner_proto_goTypes = []interface{}{
 	(*InnerCsFetchPlayerQueueResp)(nil), // 5: pb.InnerCsFetchPlayerQueueResp
 	(*InnerCsConnectPlayerReq)(nil),     // 6: pb.InnerCsConnectPlayerReq
 	(*InnerCsConnectPlayerResp)(nil),    // 7: pb.InnerCsConnectPlayerResp
-	(*structpb.ListValue)(nil),          // 8: google.protobuf.ListValue
+	(*UpdateUserStatusReq)(nil),         // 8: pb.UpdateUserStatusReq
+	(*UpdateUserStatusResp)(nil),        // 9: pb.UpdateUserStatusResp
+	(*structpb.ListValue)(nil),          // 10: google.protobuf.ListValue
 }
 var file_pb_inner_proto_depIdxs = []int32{
-	8, // 0: pb.InnerCsFetchPlayerQueueResp.list:type_name -> google.protobuf.ListValue
-	0, // 1: pb.Inner.playerFetchCsInfo:input_type -> pb.InnerPlayerFetchCsInfoReq
-	2, // 2: pb.Inner.playerDisconnect:input_type -> pb.InnerPlayerDisconnectReq
-	4, // 3: pb.Inner.csFetchPlayerQueue:input_type -> pb.InnerCsFetchPlayerQueueReq
-	6, // 4: pb.Inner.csConnectPlayer:input_type -> pb.InnerCsConnectPlayerReq
-	1, // 5: pb.Inner.playerFetchCsInfo:output_type -> pb.InnerPlayerFetchCsInfoResp
-	3, // 6: pb.Inner.playerDisconnect:output_type -> pb.InnerPlayerDisconnectResp
-	5, // 7: pb.Inner.csFetchPlayerQueue:output_type -> pb.InnerCsFetchPlayerQueueResp
-	7, // 8: pb.Inner.csConnectPlayer:output_type -> pb.InnerCsConnectPlayerResp
-	5, // [5:9] is the sub-list for method output_type
-	1, // [1:5] is the sub-list for method input_type
-	1, // [1:1] is the sub-list for extension type_name
-	1, // [1:1] is the sub-list for extension extendee
-	0, // [0:1] is the sub-list for field type_name
+	10, // 0: pb.InnerCsFetchPlayerQueueResp.list:type_name -> google.protobuf.ListValue
+	0,  // 1: pb.Inner.playerFetchCsInfo:input_type -> pb.InnerPlayerFetchCsInfoReq
+	2,  // 2: pb.Inner.playerDisconnect:input_type -> pb.InnerPlayerDisconnectReq
+	4,  // 3: pb.Inner.csFetchPlayerQueue:input_type -> pb.InnerCsFetchPlayerQueueReq
+	6,  // 4: pb.Inner.csConnectPlayer:input_type -> pb.InnerCsConnectPlayerReq
+	8,  // 5: pb.Inner.updateUserStatus:input_type -> pb.UpdateUserStatusReq
+	1,  // 6: pb.Inner.playerFetchCsInfo:output_type -> pb.InnerPlayerFetchCsInfoResp
+	3,  // 7: pb.Inner.playerDisconnect:output_type -> pb.InnerPlayerDisconnectResp
+	5,  // 8: pb.Inner.csFetchPlayerQueue:output_type -> pb.InnerCsFetchPlayerQueueResp
+	7,  // 9: pb.Inner.csConnectPlayer:output_type -> pb.InnerCsConnectPlayerResp
+	9,  // 10: pb.Inner.updateUserStatus:output_type -> pb.UpdateUserStatusResp
+	6,  // [6:11] is the sub-list for method output_type
+	1,  // [1:6] is the sub-list for method input_type
+	1,  // [1:1] is the sub-list for extension type_name
+	1,  // [1:1] is the sub-list for extension extendee
+	0,  // [0:1] is the sub-list for field type_name
 }
 
 func init() { file_pb_inner_proto_init() }
@@ -680,14 +797,39 @@ func file_pb_inner_proto_init() {
 				return nil
 			}
 		}
+		file_pb_inner_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*UpdateUserStatusReq); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_pb_inner_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*UpdateUserStatusResp); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
 	}
+	file_pb_inner_proto_msgTypes[8].OneofWrappers = []interface{}{}
 	type x struct{}
 	out := protoimpl.TypeBuilder{
 		File: protoimpl.DescBuilder{
 			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
 			RawDescriptor: file_pb_inner_proto_rawDesc,
 			NumEnums:      0,
-			NumMessages:   8,
+			NumMessages:   10,
 			NumExtensions: 0,
 			NumServices:   1,
 		},

+ 10 - 2
core/inner/rpc/pb/inner.proto

@@ -50,12 +50,20 @@ message InnerCsConnectPlayerReq{
 
 message InnerCsConnectPlayerResp{}
 
+message UpdateUserStatusReq{
+  int64 type = 1;
+  string uid = 2;
+  optional string game_id = 3;
+}
+
+message UpdateUserStatusResp{}
+
 service Inner {
   rpc playerFetchCsInfo (InnerPlayerFetchCsInfoReq) returns (InnerPlayerFetchCsInfoResp);
   rpc playerDisconnect (InnerPlayerDisconnectReq) returns (InnerPlayerDisconnectResp);
 
-  //
-
   rpc csFetchPlayerQueue (InnerCsFetchPlayerQueueReq) returns (InnerCsFetchPlayerQueueResp);
   rpc csConnectPlayer (InnerCsConnectPlayerReq) returns (InnerCsConnectPlayerResp);
+
+  rpc updateUserStatus (UpdateUserStatusReq) returns (UpdateUserStatusResp);
 }

+ 36 - 0
core/inner/rpc/pb/inner_grpc.pb.go

@@ -26,6 +26,7 @@ type InnerClient interface {
 	PlayerDisconnect(ctx context.Context, in *InnerPlayerDisconnectReq, opts ...grpc.CallOption) (*InnerPlayerDisconnectResp, error)
 	CsFetchPlayerQueue(ctx context.Context, in *InnerCsFetchPlayerQueueReq, opts ...grpc.CallOption) (*InnerCsFetchPlayerQueueResp, error)
 	CsConnectPlayer(ctx context.Context, in *InnerCsConnectPlayerReq, opts ...grpc.CallOption) (*InnerCsConnectPlayerResp, error)
+	UpdateUserStatus(ctx context.Context, in *UpdateUserStatusReq, opts ...grpc.CallOption) (*UpdateUserStatusResp, error)
 }
 
 type innerClient struct {
@@ -72,6 +73,15 @@ func (c *innerClient) CsConnectPlayer(ctx context.Context, in *InnerCsConnectPla
 	return out, nil
 }
 
+func (c *innerClient) UpdateUserStatus(ctx context.Context, in *UpdateUserStatusReq, opts ...grpc.CallOption) (*UpdateUserStatusResp, error) {
+	out := new(UpdateUserStatusResp)
+	err := c.cc.Invoke(ctx, "/pb.Inner/updateUserStatus", in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
 // InnerServer is the server API for Inner service.
 // All implementations must embed UnimplementedInnerServer
 // for forward compatibility
@@ -80,6 +90,7 @@ type InnerServer interface {
 	PlayerDisconnect(context.Context, *InnerPlayerDisconnectReq) (*InnerPlayerDisconnectResp, error)
 	CsFetchPlayerQueue(context.Context, *InnerCsFetchPlayerQueueReq) (*InnerCsFetchPlayerQueueResp, error)
 	CsConnectPlayer(context.Context, *InnerCsConnectPlayerReq) (*InnerCsConnectPlayerResp, error)
+	UpdateUserStatus(context.Context, *UpdateUserStatusReq) (*UpdateUserStatusResp, error)
 	mustEmbedUnimplementedInnerServer()
 }
 
@@ -99,6 +110,9 @@ func (UnimplementedInnerServer) CsFetchPlayerQueue(context.Context, *InnerCsFetc
 func (UnimplementedInnerServer) CsConnectPlayer(context.Context, *InnerCsConnectPlayerReq) (*InnerCsConnectPlayerResp, error) {
 	return nil, status.Errorf(codes.Unimplemented, "method CsConnectPlayer not implemented")
 }
+func (UnimplementedInnerServer) UpdateUserStatus(context.Context, *UpdateUserStatusReq) (*UpdateUserStatusResp, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method UpdateUserStatus not implemented")
+}
 func (UnimplementedInnerServer) mustEmbedUnimplementedInnerServer() {}
 
 // UnsafeInnerServer may be embedded to opt out of forward compatibility for this service.
@@ -184,6 +198,24 @@ func _Inner_CsConnectPlayer_Handler(srv interface{}, ctx context.Context, dec fu
 	return interceptor(ctx, in, info, handler)
 }
 
+func _Inner_UpdateUserStatus_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(UpdateUserStatusReq)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(InnerServer).UpdateUserStatus(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: "/pb.Inner/updateUserStatus",
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(InnerServer).UpdateUserStatus(ctx, req.(*UpdateUserStatusReq))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
 // Inner_ServiceDesc is the grpc.ServiceDesc for Inner service.
 // It's only intended for direct use with grpc.RegisterService,
 // and not to be introspected or modified (even as a copy)
@@ -207,6 +239,10 @@ var Inner_ServiceDesc = grpc.ServiceDesc{
 			MethodName: "csConnectPlayer",
 			Handler:    _Inner_CsConnectPlayer_Handler,
 		},
+		{
+			MethodName: "updateUserStatus",
+			Handler:    _Inner_UpdateUserStatus_Handler,
+		},
 	},
 	Streams:  []grpc.StreamDesc{},
 	Metadata: "pb/inner.proto",

+ 1 - 2
go.mod

@@ -6,7 +6,6 @@ require (
 	github.com/Shopify/sarama v1.32.0
 	github.com/golang-jwt/jwt/v4 v4.4.1
 	github.com/pkg/errors v0.9.1
-	github.com/stretchr/testify v1.7.0
 	github.com/zeromicro/go-zero v1.3.3
 	google.golang.org/grpc v1.46.0
 	google.golang.org/protobuf v1.28.0
@@ -19,7 +18,6 @@ require (
 	github.com/coreos/go-systemd/v22 v22.3.2 // indirect
 	github.com/davecgh/go-spew v1.1.1 // indirect
 	github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
-	github.com/duke-git/lancet/v2 v2.0.6 // indirect
 	github.com/eapache/go-resiliency v1.2.0 // indirect
 	github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21 // indirect
 	github.com/eapache/queue v1.1.0 // indirect
@@ -44,6 +42,7 @@ require (
 	github.com/json-iterator/go v1.1.12 // indirect
 	github.com/justinas/alice v1.2.0 // indirect
 	github.com/klauspost/compress v1.14.4 // indirect
+	github.com/liyue201/gostl v1.0.1 // indirect
 	github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect
 	github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
 	github.com/modern-go/reflect2 v1.0.2 // indirect

+ 5 - 0
go.sum

@@ -71,6 +71,8 @@ github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+Ce
 github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
 github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
 github.com/bkaradzic/go-lz4 v1.0.0/go.mod h1:0YdlkowM3VswSROI7qDxhRvJ3sLhlFrRRwjwegp5jy4=
+github.com/bytedance/gopkg v0.0.0-20220118071334-3db87571198b h1:LTGVFpNmNHhj0vhOlfgWueFJ32eK9blaIlHR2ciXOT0=
+github.com/bytedance/gopkg v0.0.0-20220118071334-3db87571198b/go.mod h1:2ZlV9BaUH4+NXIBF0aMdKKAnHTzqH+iMU4KUjAbL23Q=
 github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
 github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
 github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
@@ -304,6 +306,8 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
 github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
 github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
 github.com/lib/pq v1.10.4/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
+github.com/liyue201/gostl v1.0.1 h1:VQdvogZ90WpCb5WdG9UxS6r5ulnYEp8VfEMEZXVtpIs=
+github.com/liyue201/gostl v1.0.1/go.mod h1:rgK+T1a0sQ1+CsAonfuD1J8C4iuGfOU9VAt9mmR/m10=
 github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
 github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
 github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
@@ -622,6 +626,7 @@ golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBc
 golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220110181412-a018aaa089fe/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220422013727-9388b58f7150 h1:xHms4gcpe1YE7A3yIllJXP16CMAGuqwO2lX1mTyyRRc=
 golang.org/x/sys v0.0.0-20220422013727-9388b58f7150/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=