delete sonyflake
This commit is contained in:
@@ -1,113 +0,0 @@
|
||||
// Package ws is to define a websocket server and client connect.
|
||||
// Author: Arthur Zhang
|
||||
// Create Date: 20190101
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
)
|
||||
|
||||
// ClientManager is a websocket manager
|
||||
type ClientManager struct {
|
||||
Clients map[*Client]bool
|
||||
Broadcast chan []byte
|
||||
Register chan *Client
|
||||
Unregister chan *Client
|
||||
}
|
||||
|
||||
// Client is a websocket client
|
||||
type Client struct {
|
||||
ID string
|
||||
Socket *websocket.Conn
|
||||
Send chan []byte
|
||||
}
|
||||
|
||||
// Message is an object for websocket message which is mapped to json type
|
||||
type Message struct {
|
||||
Sender string `json:"sender,omitempty"`
|
||||
Recipient string `json:"recipient,omitempty"`
|
||||
Content string `json:"content,omitempty"`
|
||||
}
|
||||
|
||||
// Manager define a ws server manager
|
||||
var Manager = ClientManager{
|
||||
Broadcast: make(chan []byte),
|
||||
Register: make(chan *Client),
|
||||
Unregister: make(chan *Client),
|
||||
Clients: make(map[*Client]bool),
|
||||
}
|
||||
|
||||
// Start is to start a ws server
|
||||
func (manager *ClientManager) Start() {
|
||||
for {
|
||||
select {
|
||||
case conn := <-manager.Register:
|
||||
manager.Clients[conn] = true
|
||||
jsonMessage, _ := json.Marshal(&Message{Content: "/A new socket has connected."})
|
||||
manager.Send(jsonMessage, conn)
|
||||
case conn := <-manager.Unregister:
|
||||
if _, ok := manager.Clients[conn]; ok {
|
||||
close(conn.Send)
|
||||
delete(manager.Clients, conn)
|
||||
jsonMessage, _ := json.Marshal(&Message{Content: "/A socket has disconnected."})
|
||||
manager.Send(jsonMessage, conn)
|
||||
}
|
||||
case message := <-manager.Broadcast:
|
||||
for conn := range manager.Clients {
|
||||
select {
|
||||
case conn.Send <- message:
|
||||
default:
|
||||
close(conn.Send)
|
||||
delete(manager.Clients, conn)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Send is to send ws message to ws client
|
||||
func (manager *ClientManager) Send(message []byte, ignore *Client) {
|
||||
for conn := range manager.Clients {
|
||||
if conn != ignore {
|
||||
conn.Send <- message
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Client) Read() {
|
||||
defer func() {
|
||||
Manager.Unregister <- c
|
||||
c.Socket.Close()
|
||||
}()
|
||||
|
||||
for {
|
||||
_, message, err := c.Socket.ReadMessage()
|
||||
if err != nil {
|
||||
Manager.Unregister <- c
|
||||
c.Socket.Close()
|
||||
break
|
||||
}
|
||||
jsonMessage, _ := json.Marshal(&Message{Sender: c.ID, Content: string(message)})
|
||||
Manager.Broadcast <- jsonMessage
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Client) Write() {
|
||||
defer func() {
|
||||
c.Socket.Close()
|
||||
}()
|
||||
|
||||
for {
|
||||
select {
|
||||
case message, ok := <-c.Send:
|
||||
if !ok {
|
||||
c.Socket.WriteMessage(websocket.CloseMessage, []byte{})
|
||||
return
|
||||
}
|
||||
|
||||
c.Socket.WriteMessage(websocket.TextMessage, message)
|
||||
}
|
||||
}
|
||||
}
|
||||
1
go.mod
1
go.mod
@@ -9,6 +9,7 @@ require (
|
||||
github.com/gin-contrib/sessions v1.0.4
|
||||
github.com/gin-gonic/gin v1.10.1
|
||||
github.com/gorilla/websocket v1.5.1
|
||||
github.com/sony/sonyflake v1.2.1
|
||||
golang.org/x/crypto v0.37.0
|
||||
gorm.io/driver/mysql v1.5.6
|
||||
gorm.io/driver/postgres v1.6.0
|
||||
|
||||
2
go.sum
2
go.sum
@@ -97,6 +97,8 @@ github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6ke
|
||||
github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4=
|
||||
github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE=
|
||||
github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ=
|
||||
github.com/sony/sonyflake v1.2.1 h1:Jzo4abS84qVNbYamXZdrZF1/6TzNJjEogRfXv7TsG48=
|
||||
github.com/sony/sonyflake v1.2.1/go.mod h1:LORtCywH/cq10ZbyfhKrHYgAUGH7mOBa76enV9txy/Y=
|
||||
github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
|
||||
github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0=
|
||||
github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8=
|
||||
|
||||
@@ -1,183 +0,0 @@
|
||||
// Package sonyflake implements Sonyflake, a distributed unique ID generator inspired by Twitter's Snowflake.
|
||||
//
|
||||
// A Sonyflake ID is composed of
|
||||
// 39 bits for time in units of 10 msec
|
||||
// 8 bits for a sequence number
|
||||
// 16 bits for a machine id
|
||||
package util
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// These constants are the bit lengths of Sonyflake ID parts.
|
||||
const (
|
||||
BitLenTime = 41 // bit length of time
|
||||
BitLenSequence = 10 // bit length of sequence number
|
||||
BitLenMachineID = 53 - BitLenTime - BitLenSequence // bit length of machine id
|
||||
)
|
||||
|
||||
// Settings configures Sonyflake:
|
||||
//
|
||||
// StartTime is the time since which the Sonyflake time is defined as the elapsed time.
|
||||
// If StartTime is 0, the start time of the Sonyflake is set to "2014-09-01 00:00:00 +0000 UTC".
|
||||
// If StartTime is ahead of the current time, Sonyflake is not created.
|
||||
//
|
||||
// MachineID returns the unique ID of the Sonyflake instance.
|
||||
// If MachineID returns an error, Sonyflake is not created.
|
||||
// If MachineID is nil, default MachineID is used.
|
||||
// Default MachineID returns the lower 16 bits of the private IP address.
|
||||
//
|
||||
// CheckMachineID validates the uniqueness of the machine ID.
|
||||
// If CheckMachineID returns false, Sonyflake is not created.
|
||||
// If CheckMachineID is nil, no validation is done.
|
||||
type Settings struct {
|
||||
StartTime time.Time
|
||||
MachineID func() (uint16, error)
|
||||
CheckMachineID func(uint16) bool
|
||||
}
|
||||
|
||||
// Sonyflake is a distributed unique ID generator.
|
||||
type Sonyflake struct {
|
||||
mutex *sync.Mutex
|
||||
startTime int64
|
||||
elapsedTime int64
|
||||
sequence uint16
|
||||
machineID uint16
|
||||
}
|
||||
|
||||
// NewSonyflake returns a new Sonyflake configured with the given Settings.
|
||||
// NewSonyflake returns nil in the following cases:
|
||||
// - Settings.StartTime is ahead of the current time.
|
||||
// - Settings.MachineID returns an error.
|
||||
// - Settings.CheckMachineID returns false.
|
||||
func NewSonyflake(st Settings) *Sonyflake {
|
||||
sf := new(Sonyflake)
|
||||
sf.mutex = new(sync.Mutex)
|
||||
sf.sequence = uint16(1<<BitLenSequence - 1)
|
||||
|
||||
if st.StartTime.After(time.Now()) {
|
||||
return nil
|
||||
}
|
||||
if st.StartTime.IsZero() {
|
||||
sf.startTime = toSonyflakeTime(time.Date(2014, 9, 1, 0, 0, 0, 0, time.UTC))
|
||||
} else {
|
||||
sf.startTime = toSonyflakeTime(st.StartTime)
|
||||
}
|
||||
|
||||
var err error
|
||||
if st.MachineID == nil {
|
||||
sf.machineID, err = lower16BitPrivateIP()
|
||||
} else {
|
||||
sf.machineID, err = st.MachineID()
|
||||
}
|
||||
if err != nil || (st.CheckMachineID != nil && !st.CheckMachineID(sf.machineID)) {
|
||||
return nil
|
||||
}
|
||||
|
||||
return sf
|
||||
}
|
||||
|
||||
// NextID generates a next unique ID.
|
||||
// After the Sonyflake time overflows, NextID returns an error.
|
||||
func (sf *Sonyflake) NextID() (uint64, error) {
|
||||
const maskSequence = uint16(1<<BitLenSequence - 1)
|
||||
|
||||
sf.mutex.Lock()
|
||||
defer sf.mutex.Unlock()
|
||||
|
||||
current := currentElapsedTime(sf.startTime)
|
||||
if sf.elapsedTime < current {
|
||||
sf.elapsedTime = current
|
||||
sf.sequence = 0
|
||||
} else { // sf.elapsedTime >= current
|
||||
sf.sequence = (sf.sequence + 1) & maskSequence
|
||||
if sf.sequence == 0 {
|
||||
sf.elapsedTime++
|
||||
overtime := sf.elapsedTime - current
|
||||
time.Sleep(sleepTime((overtime)))
|
||||
}
|
||||
}
|
||||
|
||||
return sf.toID()
|
||||
}
|
||||
|
||||
const sonyflakeTimeUnit = 1e7 // nsec, i.e. 10 msec
|
||||
|
||||
func toSonyflakeTime(t time.Time) int64 {
|
||||
return t.UTC().UnixNano() / sonyflakeTimeUnit
|
||||
}
|
||||
|
||||
func currentElapsedTime(startTime int64) int64 {
|
||||
return toSonyflakeTime(time.Now()) - startTime
|
||||
}
|
||||
|
||||
func sleepTime(overtime int64) time.Duration {
|
||||
return time.Duration(overtime)*10*time.Millisecond -
|
||||
time.Duration(time.Now().UTC().UnixNano()%sonyflakeTimeUnit)*time.Nanosecond
|
||||
}
|
||||
|
||||
func (sf *Sonyflake) toID() (uint64, error) {
|
||||
if sf.elapsedTime >= 1<<BitLenTime {
|
||||
return 0, errors.New("over the time limit")
|
||||
}
|
||||
|
||||
return uint64(sf.elapsedTime)<<(BitLenSequence+BitLenMachineID) |
|
||||
uint64(sf.sequence)<<BitLenMachineID |
|
||||
uint64(sf.machineID), nil
|
||||
}
|
||||
|
||||
func privateIPv4() (net.IP, error) {
|
||||
as, err := net.InterfaceAddrs()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, a := range as {
|
||||
ipnet, ok := a.(*net.IPNet)
|
||||
if !ok || ipnet.IP.IsLoopback() {
|
||||
continue
|
||||
}
|
||||
|
||||
ip := ipnet.IP.To4()
|
||||
if isPrivateIPv4(ip) {
|
||||
return ip, nil
|
||||
}
|
||||
}
|
||||
return nil, errors.New("no private ip address")
|
||||
}
|
||||
|
||||
func isPrivateIPv4(ip net.IP) bool {
|
||||
return ip != nil &&
|
||||
(ip[0] == 10 || ip[0] == 172 && (ip[1] >= 16 && ip[1] < 32) || ip[0] == 192 && ip[1] == 168)
|
||||
}
|
||||
|
||||
func lower16BitPrivateIP() (uint16, error) {
|
||||
ip, err := privateIPv4()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return uint16(ip[2])<<8 + uint16(ip[3]), nil
|
||||
}
|
||||
|
||||
// Decompose returns a set of Sonyflake ID parts.
|
||||
func Decompose(id uint64) map[string]uint64 {
|
||||
const maskSequence = uint64((1<<BitLenSequence - 1) << BitLenMachineID)
|
||||
const maskMachineID = uint64(1<<BitLenMachineID - 1)
|
||||
|
||||
msb := id >> 63
|
||||
time := id >> (BitLenSequence + BitLenMachineID)
|
||||
sequence := id & maskSequence >> BitLenMachineID
|
||||
machineID := id & maskMachineID
|
||||
return map[string]uint64{
|
||||
"id": id,
|
||||
"msb": msb,
|
||||
"time": time,
|
||||
"sequence": sequence,
|
||||
"machine-id": machineID,
|
||||
}
|
||||
}
|
||||
@@ -3,17 +3,21 @@ package util
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/sony/sonyflake"
|
||||
)
|
||||
var t = time.Unix(1594909810, 0)
|
||||
|
||||
var flake = NewSonyflake(Settings{
|
||||
var t = time.Unix(1594909810, 0) // 基准时间
|
||||
|
||||
var flake = sonyflake.NewSonyflake(sonyflake.Settings{
|
||||
StartTime: t, // 必须设置基准时间,否则Sonyflake无法正常初始化
|
||||
})
|
||||
|
||||
func GenSonyFlakeId() uint64 {
|
||||
uuid, err := flake.NextID()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
fmt.Printf("生成SonyFlake ID失败: %v\n", err) // 明确错误信息
|
||||
return 0 // 返回0表示生成失败(根据业务需求可调整)
|
||||
}
|
||||
return uuid
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user