cloud/bmaas/server: do not start BMDB session per RPC

Fixes https://github.com/monogon-dev/monogon/issues/198

Change-Id: Ia99b9a47bfc9ae6de0b9e12e13add891dea289a5
Reviewed-on: https://review.monogon.dev/c/monogon/+/1567
Reviewed-by: Leopold Schabel <leo@monogon.tech>
Tested-by: Jenkins CI
diff --git a/cloud/bmaas/bmdb/sessions.go b/cloud/bmaas/bmdb/sessions.go
index 3f70393..6058b92 100644
--- a/cloud/bmaas/bmdb/sessions.go
+++ b/cloud/bmaas/bmdb/sessions.go
@@ -69,6 +69,19 @@
 	ctxC context.CancelFunc
 }
 
+// Expired returns true if this session is expired and will fail all subsequent
+// transactions/work.
+func (s *Session) Expired() bool {
+	return s.ctx.Err() != nil
+}
+
+// expire is a helper which marks this session as expired and returns
+// ErrSessionExpired.
+func (s *Session) expire() error {
+	s.ctxC()
+	return ErrSessionExpired
+}
+
 var (
 	// ErrSessionExpired is returned when attempting to Transact or Work on a
 	// Session that has expired or been canceled. Once a Session starts returning
@@ -102,7 +115,7 @@
 				return fmt.Errorf("when retrieving session: %w", err)
 			}
 			if len(sessions) < 1 {
-				return ErrSessionExpired
+				return s.expire()
 			}
 			err = q.SessionPoke(ctx, s.UUID)
 			if err != nil {
@@ -147,7 +160,7 @@
 			return fmt.Errorf("when retrieving session: %w", err)
 		}
 		if len(sessions) < 1 {
-			return ErrSessionExpired
+			return s.expire()
 		}
 
 		if err := fn(qtx); err != nil {