Skip to content

Commit

Permalink
message: add Clock.AsTime() conversion to time.Time
Browse files Browse the repository at this point in the history
  • Loading branch information
jgraettinger committed Aug 16, 2023
1 parent 6fa41ac commit 5330246
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 6 deletions.
22 changes: 16 additions & 6 deletions message/uuid.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,12 @@ import (
// Instead, Gazette uses clock sequence bits of UUIDs it generates in the
// following way:
//
// * The first 2 bits are reserved to represent the variant, as per RFC 4122.
// * The next 4 bits extend the 60 bit timestamp with a counter, which allows
// for a per-producer UUID generation rate of 160M UUIDs / second before
// running ahead of wall-clock time. The timestamp and counter are monotonic,
// and together provide a total ordering of UUIDs from each ProducerID.
// * The remaining 10 bits are flags, eg for representing transaction semantics.
// - The first 2 bits are reserved to represent the variant, as per RFC 4122.
// - The next 4 bits extend the 60 bit timestamp with a counter, which allows
// for a per-producer UUID generation rate of 160M UUIDs / second before
// running ahead of wall-clock time. The timestamp and counter are monotonic,
// and together provide a total ordering of UUIDs from each ProducerID.
// - The remaining 10 bits are flags, eg for representing transaction semantics.
type UUID = uuid.UUID

// ProducerID is the unique node identifier portion of a v1 UUID.
Expand Down Expand Up @@ -89,6 +89,16 @@ func (c *Clock) Tick() Clock {
return Clock(atomic.AddUint64((*uint64)(c), 1))
}

// AsTime maps the Clock into an equivalent time.Time.
func (c Clock) AsTime() time.Time {
var (
ticks = int64((c >> 4) - g1582ns100) // Each tick is 100ns relative to unix epoch.
seconds = ticks / 10_000_000
nanos = (ticks % 10_000_000) * 100
)
return time.Unix(seconds, nanos)
}

// GetClock returns the clock timestamp and sequence as a Clock.
func GetClock(uuid UUID) Clock {
var t = uint64(binary.BigEndian.Uint32(uuid[0:4])) << 4 // Clock low bits.
Expand Down
3 changes: 3 additions & 0 deletions message/uuid_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ func TestUUIDClock(t *testing.T) {

// Clock representation is precise to 100ns.
require.Equal(t, clock, NewClock(time.Unix(12, 399)))
require.Equal(t, clock.AsTime(), time.Unix(12, 300))
require.True(t, clock < NewClock(time.Unix(12, 400)))
require.True(t, clock > NewClock(time.Unix(12, 299)))

Expand All @@ -45,6 +46,7 @@ func TestUUIDClock(t *testing.T) {
}
clock.Tick() // 16th tick.
require.Equal(t, clock, NewClock(time.Unix(12, 400)))
require.Equal(t, clock.AsTime(), time.Unix(12, 400))

// Update must never decrease the clock value.
clock.Update(time.Unix(11, 100))
Expand All @@ -58,6 +60,7 @@ func TestUUIDClock(t *testing.T) {
// Sequence bits are reset if the clock timestamp is updated.
clock.Update(time.Unix(12, 500))
require.Equal(t, clock, NewClock(time.Unix(12, 500)))
require.Equal(t, clock.AsTime(), time.Unix(12, 500))
}

func TestUUIDBuilding(t *testing.T) {
Expand Down

0 comments on commit 5330246

Please # to comment.