Documentation
¶
Overview ¶
Package kvt offers a simple Key|Value|Timestamp store.
You can merge multiple Stores and the resulting Store will have the newest Key|Value|Timestamp triplets.
This store might be useful where you have a small set of metadata and want to allow updates to it on multiple machines to sync up later.
It offers a Hash to quickly identify if there are any changes, and offers JSON marshaling and unmarshaling for persistence.
Example (Overview) ¶
package main
import (
"fmt"
"github.com/gholt/kvt"
)
func main() {
// Create store with a few items.
store1 := kvt.Store{}
store1.Set("A", "one")
store1.Set("B", "two")
store1.Set("C", "three")
// Create another store with other items, some overlapping, some deleting,
// some new.
store2 := kvt.Store{}
store2.Delete("B")
store2.Set("C", "four")
store2.Set("D", "five")
store2.Set("E", "six")
store2.Set("F", "seven")
// For extra effort, update and delete items on the first store.
store1.Set("E", "eight")
store1.Delete("F")
// Here they are prior to merging.
fmt.Println("Store1:", store1.SimpleString())
fmt.Println("Store2:", store2.SimpleString())
// Now we merge store2 into store1.
store1.Absorb(store2)
fmt.Println()
fmt.Println("Store1:", store1.SimpleString())
}
Output: Store1: A=one,B=two,C=three,E=eight,F/deleted Store2: B/deleted,C=four,D=five,E=six,F=seven Store1: A=one,B/deleted,C=four,D=five,E=eight,F/deleted
Index ¶
- type Store
- func (store Store) Absorb(store2 Store)
- func (store Store) Delete(key string)
- func (store Store) DeleteTimestamped(key string, timestamp int64)
- func (store Store) Get(key string) string
- func (store Store) Hash() string
- func (store Store) Purge(cutoff int64)
- func (store Store) Set(key string, value string)
- func (store Store) SetTimestamped(key string, value string, timestamp int64)
- func (store Store) SimpleString() string
- func (store Store) String() string
- type ValueTimestamp
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Store ¶
type Store map[string]*ValueTimestamp
Store is a Key|Value|Timestamp simple store.
Example ¶
package main
import (
"fmt"
"github.com/gholt/kvt"
)
func main() {
// Create store with a few items.
store1 := kvt.Store{}
store1.Set("A", "one")
store1.Set("B", "two")
store1.Set("C", "three")
// Create another store with other items, some overlapping, some deleting,
// some new.
store2 := kvt.Store{}
store2.Delete("B")
store2.Set("C", "four")
store2.Set("D", "five")
store2.Set("E", "six")
store2.Set("F", "seven")
// For extra effort, update and delete items on the first store.
store1.Set("E", "eight")
store1.Delete("F")
// Here they are prior to merging.
fmt.Println("Store1:", store1.SimpleString())
fmt.Println("Store2:", store2.SimpleString())
// Now we merge store2 into store1.
store1.Absorb(store2)
fmt.Println()
fmt.Println("Store1:", store1.SimpleString())
}
Output: Store1: A=one,B=two,C=three,E=eight,F/deleted Store2: B/deleted,C=four,D=five,E=six,F=seven Store1: A=one,B/deleted,C=four,D=five,E=eight,F/deleted
func (Store) Absorb ¶
Absorb will update store with any newer items from store2; after Absorb, you should no longer use store2.
Example ¶
package main
import (
"fmt"
"github.com/gholt/kvt"
)
func main() {
// Create store with a few items.
store1 := kvt.Store{}
store1.Set("A", "one")
store1.Set("B", "two")
store1.Set("C", "three")
// Create another store with other items, some overlapping, some deleting,
// some new.
store2 := kvt.Store{}
store2.Delete("B")
store2.Set("C", "four")
store2.Set("D", "five")
store2.Set("E", "six")
store2.Set("F", "seven")
// For extra effort, update and delete items on the first store.
store1.Set("E", "eight")
store1.Delete("F")
// Here they are prior to merging.
fmt.Println("Store1:", store1.SimpleString())
fmt.Println("Store2:", store2.SimpleString())
// Now we merge store2 into store1.
store1.Absorb(store2)
fmt.Println()
fmt.Println("Store1:", store1.SimpleString())
}
Output: Store1: A=one,B=two,C=three,E=eight,F/deleted Store2: B/deleted,C=four,D=five,E=six,F=seven Store1: A=one,B/deleted,C=four,D=five,E=eight,F/deleted
func (Store) Delete ¶
Delete is equivalent to DeleteTimestamped(key, time.Now().UnixNano()).
Example ¶
package main
import (
"fmt"
"github.com/gholt/kvt"
)
func main() {
store := kvt.Store{}
store.Delete("A")
fmt.Println(store.SimpleString())
}
Output: A/deleted
func (Store) DeleteTimestamped ¶
DeleteTimestamped records a deletion marker for the key as long as there isn't already a value for that key with a newer or equal timestamp.
Example ¶
package main
import (
"fmt"
"time"
"github.com/gholt/kvt"
)
func main() {
store := kvt.Store{}
store.DeleteTimestamped("A", time.Date(2017, 1, 2, 3, 4, 5, 6, time.UTC).UnixNano())
store.DeleteTimestamped("A", 1) // Discarded as old
store.SetTimestamped("B", "two", 2)
store.DeleteTimestamped("B", 1) // Discarded as old
store.SetTimestamped("C", "three", 3)
store.DeleteTimestamped("C", 4)
fmt.Println(store)
}
Output: {"A":[null,1483326245000000006],"B":["two",2],"C":[null,4]}
func (Store) Get ¶
Get returns the value for a key; if the key does not exist or is marked deleted, an empty string is returned.
Example ¶
package main
import (
"fmt"
"github.com/gholt/kvt"
)
func main() {
store := kvt.Store{}
store.Set("A", "one")
store.Delete("B")
for _, k := range []string{"A", "B", "C"} {
fmt.Printf("Get(%q): %q\n", k, store.Get(k))
}
}
Output: Get("A"): "one" Get("B"): "" Get("C"): ""
func (Store) Hash ¶
Hash returns a computed hash string that can be used to quickly detect if two stores are in sync.
Example ¶
package main
import (
"fmt"
"time"
"github.com/gholt/kvt"
)
func main() {
store1 := kvt.Store{}
now := time.Date(2017, 1, 2, 3, 4, 5, 6, time.UTC).UnixNano()
store1.SetTimestamped("A", "one", now)
store1.SetTimestamped("B", "two", now)
store1.SetTimestamped("C", "three", now)
fmt.Println("store1 has hash", store1.Hash())
store2 := kvt.Store{}
store2.SetTimestamped("A", "one", now)
store2.SetTimestamped("B", "two", now)
store2.SetTimestamped("C", "three", now)
fmt.Println("store2 has hash", store2.Hash())
store2.SetTimestamped("C", "three", now+1)
fmt.Println("store2 now has hash", store2.Hash())
}
Output: store1 has hash 3d6a6976bcf5dfb9 store2 has hash 3d6a6976bcf5dfb9 store2 now has hash 3d670f76bcf310f4
func (Store) Purge ¶
Purge discards any deletion markers older than the cutoff timestamp given.
Example ¶
package main
import (
"fmt"
"time"
"github.com/gholt/kvt"
)
func main() {
store := kvt.Store{}
now := time.Date(2017, 1, 2, 3, 4, 5, 6, time.UTC)
store.DeleteTimestamped("A", now.Add(-1001*time.Hour).UnixNano())
store.DeleteTimestamped("B", now.Add(-1000*time.Hour).UnixNano())
store.DeleteTimestamped("C", now.Add(-999*time.Hour).UnixNano())
fmt.Println("Before:", store)
store.Purge(now.Add(-1000 * time.Hour).UnixNano())
fmt.Println("After:", store)
}
Output: Before: {"A":[null,1479722645000000006],"B":[null,1479726245000000006],"C":[null,1479729845000000006]} After: {"B":[null,1479726245000000006],"C":[null,1479729845000000006]}
func (Store) Set ¶
Set is equivalent to SetTimestamped(key, value, time.Now().UnixNano()).
Example ¶
package main
import (
"fmt"
"github.com/gholt/kvt"
)
func main() {
store := kvt.Store{}
store.Set("A", "one")
fmt.Println(store.SimpleString())
}
Output: A=one
func (Store) SetTimestamped ¶
SetTimestamped stores the value for the key as long as there isn't already a value for that key with a newer or equal timestamp.
Example ¶
package main
import (
"fmt"
"time"
"github.com/gholt/kvt"
)
func main() {
store := kvt.Store{}
store.SetTimestamped("A", "one", time.Date(2017, 1, 2, 3, 4, 5, 6, time.UTC).UnixNano())
fmt.Println(store)
}
Output: {"A":["one",1483326245000000006]}
func (Store) SimpleString ¶
SimpleString returns a simple key=value[,key=value] string form of the store contents; useful in tests when you want to omit the timestamps.
Example ¶
package main
import (
"fmt"
"time"
"github.com/gholt/kvt"
)
func main() {
store := kvt.Store{}
now := time.Date(2017, 1, 2, 3, 4, 5, 6, time.UTC).UnixNano()
store.SetTimestamped("A", "one", now)
store.DeleteTimestamped("B", now)
fmt.Println(store.SimpleString())
}
Output: A=one,B/deleted
func (Store) String ¶
String returns the JSON encoded string representation of the store contents.
Example ¶
package main
import (
"fmt"
"time"
"github.com/gholt/kvt"
)
func main() {
store := kvt.Store{}
now := time.Date(2017, 1, 2, 3, 4, 5, 6, time.UTC).UnixNano()
store.SetTimestamped("A", "one", now)
store.DeleteTimestamped("B", now)
fmt.Println(store.String())
fmt.Println(store)
}
Output: {"A":["one",1483326245000000006],"B":[null,1483326245000000006]} {"A":["one",1483326245000000006],"B":[null,1483326245000000006]}
type ValueTimestamp ¶
ValueTimestamp is the Value|Timestamp pair stored for each Key. If Value is nil, it indicates a deletion marker. These deletion markers are usually purged after some time using Store.Purge.
Example ¶
package main
import (
"fmt"
"github.com/gholt/kvt"
)
func main() {
one := "one"
vtA := &kvt.ValueTimestamp{Value: &one, Timestamp: 1}
vtB := &kvt.ValueTimestamp{Value: nil, Timestamp: 2}
store := kvt.Store{"A": vtA, "B": vtB}
fmt.Println(store)
// A bit simpler:
store = kvt.Store{"A": {&one, 1}, "B": {nil, 2}}
fmt.Println(store)
}
Output: {"A":["one",1],"B":[null,2]} {"A":["one",1],"B":[null,2]}
func (*ValueTimestamp) MarshalJSON ¶
func (valueTimestamp *ValueTimestamp) MarshalJSON() ([]byte, error)
MarshalJSON returns the JSON encoded version of valueTimestamp or an error.
Example ¶
package main
import (
"fmt"
"github.com/gholt/kvt"
)
func main() {
one := "one"
b, err := (&kvt.ValueTimestamp{Value: &one, Timestamp: 1}).MarshalJSON()
fmt.Println(string(b), err)
b, err = (&kvt.ValueTimestamp{Value: nil, Timestamp: 2}).MarshalJSON()
fmt.Println(string(b), err)
}
Output: ["one",1] <nil> [null,2] <nil>
func (*ValueTimestamp) String ¶
func (valueTimestamp *ValueTimestamp) String() string
String returns a quick string representation of valueTimestamp.
Example ¶
package main
import (
"fmt"
"github.com/gholt/kvt"
)
func main() {
one := "one"
vt1 := &kvt.ValueTimestamp{Value: &one, Timestamp: 1}
vt2 := &kvt.ValueTimestamp{Value: nil, Timestamp: 2}
fmt.Println(vt1.String(), vt2.String())
fmt.Println(vt1, vt2)
}
Output: one,1 nil,2 one,1 nil,2
func (*ValueTimestamp) UnmarshalJSON ¶
func (valueTimestamp *ValueTimestamp) UnmarshalJSON(b []byte) error
MarshalJSON loads valueTimestamp with data from the JSON encoded b or returns an error.
Example ¶
package main
import (
"fmt"
"github.com/gholt/kvt"
)
func main() {
vt := &kvt.ValueTimestamp{}
err := vt.UnmarshalJSON([]byte(`["one",1]`))
fmt.Println(vt, err)
vt = &kvt.ValueTimestamp{}
err = vt.UnmarshalJSON([]byte(`[null,2]`))
fmt.Println(vt, err)
}
Output: one,1 <nil> nil,2 <nil>