/
timedkey.go
125 lines (97 loc) · 2.43 KB
/
timedkey.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
package keys
import (
"encoding/json"
"errors"
"fmt"
"github.com/louisevanderlith/husk/hsk"
"strconv"
"strings"
"time"
)
//TimeKey is the Primary Key for Husk Indexes. It orders records by Timestamp
type TimeKey struct {
//Stamp is the EPOCH Creation Time
Stamp int64
//ID increments with duplicate Stamps
ID int64
}
// CrazyKey is a short-hand for NewKey(-1), returns old date
func CrazyKey() hsk.Key {
old := time.Date(1991, 8, 2, 12, 13, 57, 000, time.UTC)
return NewKeyWithTime(old.Unix(), int64(-1))
}
//NewKey creates a new key with the current time as the Stamp
func NewKey(nextID int64) hsk.Key {
if nextID == -1 {
panic("rather call CrazyKey")
}
timestamp := time.Now().Unix()
return NewKeyWithTime(timestamp, nextID)
}
func NewKeyWithTime(timestamp, nextID int64) hsk.Key {
return &TimeKey{timestamp, nextID}
}
// ParseKey tries to parse EPOCH`00 Keys.
func ParseKey(rawKey string) (hsk.Key, error) {
if len(rawKey) < 3 {
return nil, errors.New("rawKey too short")
}
if !strings.Contains(rawKey, "`") {
return nil, errors.New("key not valid format")
}
dotIndx := strings.Index(rawKey, "`")
stamp, err := strconv.ParseInt(rawKey[:dotIndx], 10, 64)
if err != nil {
return nil, err
}
id, err := strconv.ParseInt(rawKey[dotIndx+1:], 10, 64)
if err != nil {
return nil, err
}
return &TimeKey{stamp, id}, nil
}
//String returns the string representation for a Key, also makes is easier to parse.
func (k TimeKey) String() string {
return fmt.Sprintf("%d`%d", k.Stamp, k.ID)
}
//GetTimestamp returns the creation time of the record
func (k TimeKey) GetTimestamp() time.Time {
return time.Unix(k.Stamp, 0)
}
//Compare returns -1 (smaller), 0 (equal), 1 (larger)
func (k *TimeKey) Compare(obj interface{}) int8 {
k2 := obj.(*TimeKey)
//Stamps are checked before ID
if k.Stamp < k2.Stamp {
return -1
}
if k.Stamp > k2.Stamp {
return 1
}
if k.ID < k2.ID {
return -1
}
if k.ID > k2.ID {
return 1
}
return 0
}
//MarshalJSON will return a Key as {stamp}`{key}
func (k TimeKey) MarshalJSON() ([]byte, error) {
return json.Marshal(k.String())
}
//UnmarshalJSON will return {stamp}`{key} as a Key
func (k *TimeKey) UnmarshalJSON(b []byte) error {
stripEsc := strings.Replace(string(b), "\"", "", -1)
tmpK, err := ParseKey(stripEsc)
if err != nil {
return err
}
tmKey, ok := tmpK.(*TimeKey)
if !ok {
return errors.New("invalid key type")
}
k.Stamp = tmKey.Stamp
k.ID = tmKey.ID
return nil
}