File: examples.md

package info (click to toggle)
docker-libkv 0.2.1-3
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, bookworm-proposed-updates
  • size: 352 kB
  • sloc: sh: 85; makefile: 5
file content (157 lines) | stat: -rw-r--r-- 4,233 bytes parent folder | download | duplicates (4)
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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
#Examples

This document contains useful example of usage for `libkv`. It might not be complete but provides with general informations on how to use the client.

##Create a store and use Put/Get/Delete

```go
package main

import (
    "fmt"
    "time"
    "log"

    "github.com/docker/libkv"
    "github.com/docker/libkv/store"
    "github.com/docker/libkv/store/consul"
)

func init() {
    // Register consul store to libkv
    consul.Register()

    // We can register as many backends that are supported by libkv
    etcd.Register()
    zookeeper.Register()
    boltdb.Register()
}

func main() {
    client := "localhost:8500"

    // Initialize a new store with consul
    kv, err := libkv.NewStore(
        store.CONSUL, // or "consul"
        []string{client},
        &store.Config{
            ConnectionTimeout: 10*time.Second,
        },
    )
    if err != nil {
        log.Fatal("Cannot create store consul")
    }

    key := "foo"
    err = kv.Put(key, []byte("bar"), nil)
    if err != nil {
        fmt.Errorf("Error trying to put value at key: %v", key)
    }

    pair, err := kv.Get(key)
    if err != nil {
        fmt.Errorf("Error trying accessing value at key: %v", key)
    }

    err = kv.Delete(key)
    if err != nil {
        fmt.Errorf("Error trying to delete key %v", key)
    }

    log.Info("value: ", string(pair.Value))
}
```

##List keys

```go
// List will list all the keys under `key` if it contains a set of child keys/values
entries, err := kv.List(key)
for _, pair := range entries {
    fmt.Printf("key=%v - value=%v", pair.Key, string(pair.Value))
}

```

##Watching for events on a single key (Watch)

You can use watches to watch modifications on a key. First you need to check if the key exists. If this is not the case, we need to create it using the `Put` function.

```go
// Checking on the key before watching
if !kv.Exists(key) {
    err := kv.Put(key, []byte("bar"), nil)
    if err != nil {
        fmt.Errorf("Something went wrong when initializing key %v", key)
    }
}

stopCh := make(<-chan struct{})
events, err := kv.Watch(key, stopCh)

select {
    case pair := <-events:
        // Do something with events
        fmt.Printf("value changed on key %v: new value=%v", key, pair.Value)
}

```

##Watching for events happening on child keys (WatchTree)

You can use watches to watch modifications on a key. First you need to check if the key exists. If this is not the case, we need to create it using the `Put` function. There is a special step here though if you want your code to work across backends. Because `etcd` is a special case and it makes the distinction between directories and keys, we need to make sure that the created key is considered as a directory by enforcing `IsDir` at `true`.

```go
// Checking on the key before watching
if !kv.Exists(key) {
    // Don't forget IsDir:true if the code is used cross-backend
    err := kv.Put(key, []byte("bar"), &store.WriteOptions{IsDir:true})
    if err != nil {
        fmt.Errorf("Something went wrong when initializing key %v", key)
    }
}

stopCh := make(<-chan struct{})
events, err := kv.WatchTree(key, stopCh)

select {
    case pairs := <-events:
        // Do something with events
        for _, pair := range pairs {
            fmt.Printf("value changed on key %v: new value=%v", key, pair.Value)
        }
}

```

## Distributed Locking, using Lock/Unlock

```go
key := "lockKey"
value := []byte("bar")

// Initialize a distributed lock. TTL is optional, it is here to make sure that
// the lock is released after the program that is holding the lock ends or crashes
lock, err := kv.NewLock(key, &store.LockOptions{Value: value, TTL: 2 * time.Second})
if err != nil {
    fmt.Errorf("something went wrong when trying to initialize the Lock")
}

// Try to lock the key, the call to Lock() is blocking
_, err := lock.Lock(nil)
if err != nil {
    fmt.Errorf("something went wrong when trying to lock key %v", key)
}

// Get should work because we are holding the key
pair, err := kv.Get(key)
if err != nil {
    fmt.Errorf("key %v has value %v", key, pair.Value)
}

// Unlock the key
err = lock.Unlock()
if err != nil {
    fmt.Errorf("something went wrong when trying to unlock key %v", key)
}
```