Skip to content

Instantly share code, notes, and snippets.

@artyom
Created June 5, 2017 16:07
Show Gist options
  • Save artyom/0e0b36da42fc3fe3248e8a66a5485376 to your computer and use it in GitHub Desktop.
Save artyom/0e0b36da42fc3fe3248e8a66a5485376 to your computer and use it in GitHub Desktop.
Patch for https://github.com/Doist/bitmapist-server/ allowing one to disable autmated periodic saving and initiate save by SIGUSR2
diff --git i/bitmapist.go w/bitmapist.go
index 0e22f2c..345ae31 100644
--- i/bitmapist.go
+++ w/bitmapist.go
@@ -18,10 +18,11 @@ import (
func main() {
args := struct {
- Addr string `flag:"addr,address to listen"`
- File string `flag:"db,path to database file"`
- Bak string `flag:"bak,file to save backup to on SIGUSR1"`
- Dbg bool `flag:"debug,log incoming commands"`
+ Addr string `flag:"addr,address to listen"`
+ File string `flag:"db,path to database file"`
+ Bak string `flag:"bak,file to save backup to on SIGUSR1"`
+ Dbg bool `flag:"debug,log incoming commands"`
+ Nosave bool `flag:"noautosave,disable automated periodic saving, force saving by sending SIGUSR2"`
}{
Addr: "localhost:6379",
File: "bitmapist.db",
@@ -38,6 +39,16 @@ func main() {
}
log.Println("loaded in", time.Since(begin))
s.WithLogger(log)
+ if args.Nosave {
+ s.WithoutAutosave()
+ go func() {
+ sigCh := make(chan os.Signal, 1)
+ signal.Notify(sigCh, syscall.SIGUSR2)
+ for range sigCh {
+ s.Save()
+ }
+ }()
+ }
srv := red.NewServer()
srv.WithLogger(log)
diff --git i/internal/bitmapist/bitmapist.go w/internal/bitmapist/bitmapist.go
index 4c8eb23..7404876 100644
--- i/internal/bitmapist/bitmapist.go
+++ w/internal/bitmapist/bitmapist.go
@@ -34,9 +34,10 @@ func New(dbFile string) (*Server, error) {
rm: make(map[string]struct{}),
cache: make(map[string]cacheItem),
- done: make(chan struct{}),
- doneAck: make(chan struct{}),
- save: make(chan struct{}),
+ done: make(chan struct{}),
+ doneAck: make(chan struct{}),
+ save: make(chan struct{}),
+ noautosave: make(chan struct{}, 1),
}
err = s.db.View(func(tx *bolt.Tx) error {
if bkt := tx.Bucket([]byte("aux")); bkt != nil {
@@ -107,6 +108,8 @@ type Server struct {
doneAck chan struct{}
save chan struct{}
+ noautosave chan struct{}
+
mu sync.Mutex
keys map[string]struct{} // all known keys
rm map[string]struct{} // removed but not yet purged
@@ -202,6 +205,9 @@ func (s *Server) loop() {
case <-s.done:
fn("final saving...", s.persist)
return
+ case <-s.noautosave:
+ ticker.Stop()
+ s.log.Println("periodic saving disabled")
}
}
}
@@ -294,6 +300,24 @@ func (s *Server) persist() error {
return err
}
+// Save has the same effect as issuing BGSAVE command over connected client
+func (s *Server) Save() {
+ select {
+ case s.save <- struct{}{}:
+ default:
+ }
+}
+
+// WithoutAutosave disables automated periodic state saving. State is only
+// persisted when explicitly told calling Save() method or issuing BGSAVE
+// command over connected client.
+func (s *Server) WithoutAutosave() {
+ select {
+ case s.noautosave <- struct{}{}:
+ default:
+ }
+}
+
func (s *Server) handleSlurp(req red.Request) (interface{}, error) {
if len(req.Args) != 1 {
return nil, red.ErrWrongArgs
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment