Skip to content

Instantly share code, notes, and snippets.

@makasim
Last active April 29, 2024 17:56
Show Gist options
  • Save makasim/36f8bb33ab2dd1edba591e9d2018628d to your computer and use it in GitHub Desktop.
Save makasim/36f8bb33ab2dd1edba591e9d2018628d to your computer and use it in GitHub Desktop.
Deterministic ULID generation from int64 in #golang
package main
import (
"fmt"
"time"
"intulid"
"github.com/oklog/ulid/v2"
)
type Event struct {
id int64
createdAt time.Time
Foo string
Bar string
}
func main() {
t := time.Unix(123, 567)
uniq := make(map[string]struct{})
for i := 0; i < 1000000000; i++ {
e := Event{
id: int64(i),
createdAt: t,
Foo: "foo",
Bar: "bar",
}
id, err := intulid.New(ulid.Timestamp(e.createdAt), e.id, []byte(`foo`))
if err != nil {
panic(err)
}
fmt.Printf("%d -> %s\n", e.id, id.String())
if _, ok := uniq[id.String()]; ok {
fmt.Printf("%d -> %s\n", e.id, id.String())
panic("duplicate id")
} else {
uniq[id.String()] = struct{}{}
}
}
}
package intulid
import (
"encoding/binary"
"fmt"
"github.com/oklog/ulid/v2"
"golang.org/x/crypto/sha3"
)
type entropy []byte
func New(ms uint64, num int64, salt []byte) (ulid.ULID, error) {
if len(salt) > 120 {
return ulid.ULID{}, fmt.Errorf("salt len could not be longer than 120 bytes")
}
e := make(entropy, 8, 128)
binary.LittleEndian.PutUint64(e[:8], uint64(num))
e = append(e, salt...)
return ulid.New(ms, e)
}
func (e entropy) Read(p []byte) (n int, err error) {
sha3.ShakeSum256(p, e)
return len(p), nil
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment