Skip to content

Commit

Permalink
add sql value support to timed version
Browse files Browse the repository at this point in the history
  • Loading branch information
paulwe committed Dec 30, 2023
1 parent 00aac29 commit ea15390
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 1 deletion.
50 changes: 49 additions & 1 deletion utils/timed_version.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@
package utils

import (
"database/sql/driver"
"encoding/binary"
"errors"
"fmt"
"sync"
"time"
Expand Down Expand Up @@ -110,10 +113,22 @@ func TimedVersionFromTime(t time.Time) TimedVersion {
}

func (t *TimedVersion) Update(other *TimedVersion) bool {
return t.Upgrade(other)
}

func (t *TimedVersion) Upgrade(other *TimedVersion) bool {
return t.update(other, func(ov, prev uint64) bool { return ov > prev })
}

func (t *TimedVersion) Downgrade(other *TimedVersion) bool {
return t.update(other, func(ov, prev uint64) bool { return ov < prev })
}

func (t *TimedVersion) update(other *TimedVersion, cmp func(ov, prev uint64) bool) bool {
ov := other.v.Load()
for {
prev := t.v.Load()
if ov <= prev {
if !cmp(ov, prev) {
return false
}
if t.v.CompareAndSwap(prev, ov) {
Expand Down Expand Up @@ -167,3 +182,36 @@ func (t *TimedVersion) String() string {
ts, ticks := timedVersionComponents(t.v.Load())
return fmt.Sprintf("%d.%d", ts, ticks)
}

func (t TimedVersion) Value() (driver.Value, error) {
if t.IsZero() {
return nil, nil
}

ts, ticks := timedVersionComponents(t.v.Load())
b := make([]byte, 0, 12)
b = binary.BigEndian.AppendUint64(b, uint64(ts))
b = binary.BigEndian.AppendUint32(b, uint32(ticks))
return b, nil
}

func (t *TimedVersion) Scan(src interface{}) (err error) {
switch b := src.(type) {
case []byte:
switch len(b) {
case 0:
t.v.Store(0)
case 12:
ts := int64(binary.BigEndian.Uint64(b))
ticks := int32(binary.BigEndian.Uint32(b[8:]))
*t = timedVersionFromComponents(ts, ticks)
default:
return errors.New("(*TimedVersion).Scan: unsupported format")
}
case nil:
t.v.Store(0)
default:
return errors.New("(*TimedVersion).Scan: unsupported data type")
}
return nil
}
4 changes: 4 additions & 0 deletions utils/timed_version_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,4 +64,8 @@ func TestTimedVersion(t *testing.T) {
require.Equal(t, ts1, ts2)
require.Equal(t, tv1.v.Load(), tv2.v.Load())
})

t.Run("timed version from nil is zero", func(t *testing.T) {
require.True(t, NewTimedVersionFromProto(nil).IsZero())
})
}

0 comments on commit ea15390

Please sign in to comment.