about summary refs log tree commit diff
path: root/monzo_ynab
diff options
context:
space:
mode:
authorWilliam Carroll <wpcarro@gmail.com>2020-02-09T13·53+0000
committerWilliam Carroll <wpcarro@gmail.com>2020-02-10T10·06+0000
commitaba0cd7b9d14335e49207fb79323bc7827686263 (patch)
tree7b27a99a5276674be911bdfac940045ed8f094cb /monzo_ynab
parent0f914d8aa09ba30415931367043dab74d29022bb (diff)
Gracefully shutdown server
Listen for SIGINT and SIGTERM signals and write the current state to the
key-value store before shutting down.
Diffstat (limited to 'monzo_ynab')
-rw-r--r--monzo_ynab/tokens.go33
1 files changed, 33 insertions, 0 deletions
diff --git a/monzo_ynab/tokens.go b/monzo_ynab/tokens.go
index 4617595bf55a..d969ce6e43b4 100644
--- a/monzo_ynab/tokens.go
+++ b/monzo_ynab/tokens.go
@@ -17,6 +17,8 @@ import (
 	"os"
 	"time"
 	"kv"
+	"os/signal"
+	"syscall"
 )
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -118,6 +120,34 @@ func refreshTokens(refreshToken string) (string, string) {
 	return payload.AccessToken, payload.RefreshToken
 }
 
+// Listen for SIGINT and SIGTERM signals. When received, persist the access and
+// refresh tokens and shutdown the server.
+func handleInterrupts() {
+	// Gracefully handle interruptions.
+	sigs := make(chan os.Signal)
+	done := make(chan bool)
+
+	signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
+
+	go func() {
+		sig := <-sigs
+		log.Printf("Received signal to shutdown. %v\n", sig)
+		// Persist existing tokens
+		log.Println("Persisting existing credentials...")
+		msg := readMsg{make(chan state)}
+		chans.reads <- msg
+		state := <-msg.sender
+		kv.Set("monzoAccessToken", state.accessToken)
+		kv.Set("monzoRefreshToken", state.refreshToken)
+		log.Println("Credentials persisted.")
+		done <- true
+	}()
+
+	<-done
+	log.Println("Received signal to shutdown. Exiting...")
+	os.Exit(0)
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // Main
 ////////////////////////////////////////////////////////////////////////////////
@@ -135,6 +165,9 @@ func main() {
 		log.Fatal("Cannot start server without access or refresh tokens.")
 	}
 
+	// Gracefully shutdown.
+	go handleInterrupts()
+
 	// Manage application state.
 	go func() {
 		state := &state{accessToken, refreshToken}