aboutsummaryrefslogtreecommitdiff
path: root/guix-data-service
diff options
context:
space:
mode:
authorChristopher Baines <mail@cbaines.net>2022-10-23 11:28:37 +0100
committerChristopher Baines <mail@cbaines.net>2022-10-23 11:28:37 +0100
commitd06230fcf4fbea966966479795d5d781a156df6f (patch)
tree6f9cbb3e16382a7dff087c86357666e1ad55fbb1 /guix-data-service
parentaaec813cba86240d5e9e6751e1743ee4f540d998 (diff)
downloaddata-service-d06230fcf4fbea966966479795d5d781a156df6f.tar
data-service-d06230fcf4fbea966966479795d5d781a156df6f.tar.gz
Close postgresql connections when the thread pool thread is idle
I think the idle connections associated with idle threads are still taking up memory, so especially now that you can configure an arbitrary number of threads (and thus connections), I think it's good to close them regularly.
Diffstat (limited to 'guix-data-service')
-rw-r--r--guix-data-service/database.scm10
-rw-r--r--guix-data-service/utils.scm36
2 files changed, 45 insertions, 1 deletions
diff --git a/guix-data-service/database.scm b/guix-data-service/database.scm
index 1204bb4..3a39798 100644
--- a/guix-data-service/database.scm
+++ b/guix-data-service/database.scm
@@ -27,6 +27,7 @@
with-postgresql-connection-per-thread
with-thread-postgresql-connection
+ close-thread-postgresql-connection
with-postgresql-transaction
@@ -146,6 +147,15 @@
(f conn)))))
+(define (close-thread-postgresql-connection)
+ (let ((conn (fluid-ref %thread-postgresql-connection)))
+ (when conn
+ (pg-conn-finish conn)
+ (hash-remove! (%postgresql-connections-hash-table)
+ (current-thread))
+ (fluid-set! %thread-postgresql-connection
+ conn))))
+
(define* (with-postgresql-transaction conn f
#:key always-rollback?)
(exec-query conn "BEGIN;")
diff --git a/guix-data-service/utils.scm b/guix-data-service/utils.scm
index 20ac3c0..2527cf4 100644
--- a/guix-data-service/utils.scm
+++ b/guix-data-service/utils.scm
@@ -23,6 +23,8 @@
#:use-module (ice-9 threads)
#:use-module (fibers)
#:use-module (fibers channels)
+ #:use-module (fibers operations)
+ #:use-module (fibers timers)
#:use-module (fibers conditions)
#:use-module (prometheus)
#:export (call-with-time-logging
@@ -30,6 +32,8 @@
prevent-inlining-for-tests
%thread-pool-threads
+ %thread-pool-idle-seconds
+ %thread-pool-idle-thunk
parallel-via-thread-pool-channel
par-map&
letpar&
@@ -62,6 +66,12 @@
(define %thread-pool-threads
(make-parameter 8))
+(define %thread-pool-idle-seconds
+ (make-parameter #f))
+
+(define %thread-pool-idle-thunk
+ (make-parameter #f))
+
(define* (make-thread-pool-channel threads)
(define (delay-logger seconds-delayed)
(when (> seconds-delayed 1)
@@ -70,13 +80,37 @@
"warning: thread pool delayed by ~1,2f seconds~%"
seconds-delayed)))
+ (define idle-thunk
+ (%thread-pool-idle-thunk))
+
+ (define idle-seconds
+ (%thread-pool-idle-seconds))
+
(let ((channel (make-channel)))
(for-each
(lambda _
(call-with-new-thread
(lambda ()
(let loop ()
- (match (get-message channel)
+ (match (if idle-seconds
+ (perform-operation
+ (choice-operation
+ (get-operation channel)
+ (wrap-operation (sleep-operation idle-seconds)
+ (const 'timeout))))
+ (get-message channel))
+ ('timeout
+ (when idle-thunk
+ (with-exception-handler
+ (lambda (exn)
+ (simple-format (current-error-port)
+ "worker thread idle thunk exception: ~A\n"
+ exn))
+ idle-thunk
+ #:unwind? #t))
+
+ (loop))
+
(((? channel? reply) sent-time (? procedure? proc))
(let ((time-delay
(- (get-internal-real-time)