Documentation ¶
Overview ¶
Package snapshot manages session storage
Snapshots are session meta data (version, pending), the actual app value and the transformed/merged ops cache.
The Bolt{} type writes the snapshot to a bolt-db (taking care to to incremental writes).
Example (ClientServerUsingBoltDB) ¶
package main import ( "fmt" "log" "net/http/httptest" "os" "os/signal" "reflect" "runtime" "syscall" "github.com/dotchain/dot" "github.com/dotchain/dot/changes" "github.com/dotchain/dot/changes/types" "github.com/dotchain/dot/ops" "github.com/dotchain/dot/x/snapshot" ) func dumpCallStack() func() { c := make(chan os.Signal, 1) signal.Notify(c, os.Interrupt, syscall.SIGTERM) go func() { if sig := <-c; sig != nil { stacktrace := make([]byte, 8192) length := runtime.Stack(stacktrace, true) log.Println(string(stacktrace[:length])) os.Exit(1) } }() return func() { signal.Stop(c) close(c) } } func main() { defer dumpCallStack()() defer remove("file.bolt")() defer remove("snap.bolt")() // start server url, close := startServer("file.bolt") defer close() bolt := snapshot.Bolt{Path: "snap.bolt"} // open stream session, _, err := bolt.Load() if err != nil { fmt.Println("Error", err) } s, store := session.Stream(url, nil) // make a couple of changes c1 := changes.Replace{Before: changes.Nil, After: types.S8("hello")} c2 := changes.Replace{Before: types.S8("hello"), After: types.S8("hello2")} s = s.Append(c1).Append(c2) // flsuh if err := s.Push(); err != nil { fmt.Println("Error", err) } if err := s.Pull(); err != nil { fmt.Println("Error", err) } store.Close() // write out session and confirm it matches if err := bolt.Save(session, c2.After); err != nil { fmt.Println("Error", err) } sess, v2, err := bolt.Load() if err != nil { fmt.Println("Error", err) } // Validate if sess.Version != 0 || v2 != c2.After { fmt.Println("Mismatch", sess.Version, v2, c2.After) } if !reflect.DeepEqual(session.OpCache, sess.OpCache) { fmt.Println("Mismatch", session.OpCache, sess.OpCache) } if !reflect.DeepEqual(session.MergeCache, sess.MergeCache) { fmt.Println("Mismatch", session.MergeCache, sess.MergeCache) } if !nilCheck(session.Pending, sess.Pending) { fmt.Println("Mismatch", session.Pending, sess.Pending) } if !nilCheck(session.Merge, sess.Merge) { fmt.Println("Mismatch", session.Merge, sess.Merge) } } func remove(fname string) func() { if err := os.Remove(fname); err != nil { log.Println("Couldnt remove file", fname) } return func() { if err := os.Remove(fname); err != nil { log.Println("Couldnt remove file", fname) } } } func startServer(fname string) (url string, close func()) { logger := log.New(os.Stderr, "", log.LstdFlags|log.Lshortfile) srv := dot.WithLogger(dot.BoltServer("file.bolt"), logger) httpSrv := httptest.NewServer(srv) return httpSrv.URL, func() { dot.CloseServer(srv) httpSrv.Close() } } func nilCheck(l, r []ops.Op) bool { if len(l) == 0 && len(r) == 0 { return true } return reflect.DeepEqual(l, r) }
Output:
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Bolt ¶
Bolt represents a local file (bolt db) storage
Path is the path to the file to write snapshots ¶
Initial is the initial app state. This can be nil if the app starts from scratch (in which case it is mapped to changes.Nil)
Codec is the codec to use. If not specified, the default codec is used
Click to show internal directories.
Click to hide internal directories.