From 59fe74794f850d323704bd1755db6d8cae945c3f Mon Sep 17 00:00:00 2001 From: Kyren223 Date: Wed, 16 Oct 2024 11:45:53 +0300 Subject: feat: add twitter-style snowflake ID --- pkg/snowflake/snowflake.go | 109 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 pkg/snowflake/snowflake.go (limited to 'pkg/snowflake') diff --git a/pkg/snowflake/snowflake.go b/pkg/snowflake/snowflake.go new file mode 100644 index 0000000..5b58cbb --- /dev/null +++ b/pkg/snowflake/snowflake.go @@ -0,0 +1,109 @@ +package snowflake + +import ( + "fmt" + "strconv" + "sync" + "time" + + "github.com/kyren223/eko/pkg/assert" +) + +const ( + // Epoch is set to the twitter snowflake epoch of Nov 04 2010 01:42:54 UTC in milliseconds + // TODO: change this to eko epoch when eko is production ready + Epoch int64 = 1288834974657 + + nodeBits = 10 + stepBits = 12 + nodeMax = 1<> timeShift) + Epoch +} + +func (id ID) Node() int64 { + return int64(id) & nodeMask >> nodeShift +} + +func (id ID) Step() int64 { + return int64(id) & stepMask +} + +// Json marshling to avoid inprecision of json number (float64) + +func (id ID) MarshalJSON() ([]byte, error) { + buffer := make([]byte, 0, 22) // 2 quotes, 19 digits for 2^63, 1 sign + buffer = append(buffer, '"') + buffer = strconv.AppendInt(buffer, int64(id), 10) + buffer = append(buffer, '"') + return buffer, nil +} + +func (id *ID) UnmarshalJSON(data []byte) error { + if len(data) < 3 || data[0] != '"' || data[len(data)-1] != '"' { + return fmt.Errorf("invalid snowflake ID %q", string(data)) + } + + num, err := strconv.ParseInt(string(data[1:len(data)-1]), 10, 64) + if err != nil { + return err + } + + *id = ID(num) + return nil +} -- cgit v1.3.1