publish: Add '--ttl'.

* guix/scripts/publish.scm (show-help, %options): Add --ttl.
(render-narinfo): Add #:ttl and honor it.
(make-request-handler): Add #:narinfo-ttl and honor it.
(run-publish-server): Likewise.
(guix-publish): Honor --ttl, pass it to 'run-publish-server'.
master
Ludovic Courtès 2016-06-09 23:33:20 +02:00
parent 638c5b7939
commit e4c7a5f7c8
No known key found for this signature in database
GPG Key ID: 090B11993D9AEBB5
2 changed files with 38 additions and 8 deletions

View File

@ -5545,6 +5545,16 @@ accept connections from any interface.
Change privileges to @var{user} as soon as possible---i.e., once the Change privileges to @var{user} as soon as possible---i.e., once the
server socket is open and the signing key has been read. server socket is open and the signing key has been read.
@item --ttl=@var{ttl}
Produce @code{Cache-Control} HTTP headers that advertise a time-to-live
(TTL) of @var{ttl}. @var{ttl} must denote a duration: @code{5d} means 5
days, @code{1m} means 1 month, and so on.
This allows the user's Guix to keep substitute information in cache for
@var{ttl}. However, note that @code{guix publish} does not itself
guarantee that the store items it provides will indeed remain available
for as long as @var{ttl}.
@item --repl[=@var{port}] @item --repl[=@var{port}]
@itemx -r [@var{port}] @itemx -r [@var{port}]
Spawn a Guile REPL server (@pxref{REPL Servers,,, guile, GNU Guile Spawn a Guile REPL server (@pxref{REPL Servers,,, guile, GNU Guile

View File

@ -28,6 +28,7 @@
#:use-module (srfi srfi-1) #:use-module (srfi srfi-1)
#:use-module (srfi srfi-2) #:use-module (srfi srfi-2)
#:use-module (srfi srfi-9 gnu) #:use-module (srfi srfi-9 gnu)
#:use-module (srfi srfi-19)
#:use-module (srfi srfi-26) #:use-module (srfi srfi-26)
#:use-module (srfi srfi-37) #:use-module (srfi srfi-37)
#:use-module (web http) #:use-module (web http)
@ -57,6 +58,8 @@ Publish ~a over HTTP.\n") %store-directory)
--listen=HOST listen on the network interface for HOST")) --listen=HOST listen on the network interface for HOST"))
(display (_ " (display (_ "
-u, --user=USER change privileges to USER as soon as possible")) -u, --user=USER change privileges to USER as soon as possible"))
(display (_ "
--ttl=TTL announce narinfos can be cached for TTL seconds"))
(display (_ " (display (_ "
-r, --repl[=PORT] spawn REPL server on PORT")) -r, --repl[=PORT] spawn REPL server on PORT"))
(newline) (newline)
@ -99,6 +102,13 @@ Publish ~a over HTTP.\n") %store-directory)
(() (()
(leave (_ "lookup of host '~a' returned nothing") (leave (_ "lookup of host '~a' returned nothing")
name))))) name)))))
(option '("ttl") #t #f
(lambda (opt name arg result)
(let ((duration (string->duration arg)))
(unless duration
(leave (_ "~a: invalid duration~%") arg))
(alist-cons 'narinfo-ttl (time-second duration)
result))))
(option '(#\r "repl") #f #t (option '(#\r "repl") #f #t
(lambda (opt name arg result) (lambda (opt name arg result)
;; If port unspecified, use default Guile REPL port. ;; If port unspecified, use default Guile REPL port.
@ -199,12 +209,18 @@ References: ~a~%"
(format port "~a: ~a~%" key value))) (format port "~a: ~a~%" key value)))
%nix-cache-info)))) %nix-cache-info))))
(define (render-narinfo store request hash) (define* (render-narinfo store request hash #:key ttl)
"Render metadata for the store path corresponding to HASH." "Render metadata for the store path corresponding to HASH. If TTL is true,
advertise it as the maximum validity period (in seconds) via the
'Cache-Control' header. This allows 'guix substitute' to cache it for an
appropriate duration."
(let ((store-path (hash-part->path store hash))) (let ((store-path (hash-part->path store hash)))
(if (string-null? store-path) (if (string-null? store-path)
(not-found request) (not-found request)
(values '((content-type . (application/x-nix-narinfo))) (values `((content-type . (application/x-nix-narinfo))
,@(if ttl
`((cache-control (max-age . ,ttl)))
'()))
(cut display (cut display
(narinfo-string store store-path (force %private-key)) (narinfo-string store store-path (force %private-key))
<>))))) <>)))))
@ -300,7 +316,7 @@ blocking."
http-write http-write
(@@ (web server http) http-close)) (@@ (web server http) http-close))
(define (make-request-handler store) (define* (make-request-handler store #:key narinfo-ttl)
(lambda (request body) (lambda (request body)
(format #t "~a ~a~%" (format #t "~a ~a~%"
(request-method request) (request-method request)
@ -312,15 +328,18 @@ blocking."
(render-nix-cache-info)) (render-nix-cache-info))
;; /<hash>.narinfo ;; /<hash>.narinfo
(((= extract-narinfo-hash (? string? hash))) (((= extract-narinfo-hash (? string? hash)))
(render-narinfo store request hash)) ;; TODO: Register roots for HASH that will somehow remain for
;; NARINFO-TTL.
(render-narinfo store request hash #:ttl narinfo-ttl))
;; /nar/<store-item> ;; /nar/<store-item>
(("nar" store-item) (("nar" store-item)
(render-nar store request store-item)) (render-nar store request store-item))
(_ (not-found request))) (_ (not-found request)))
(not-found request)))) (not-found request))))
(define (run-publish-server socket store) (define* (run-publish-server socket store
(run-server (make-request-handler store) #:key narinfo-ttl)
(run-server (make-request-handler store #:narinfo-ttl narinfo-ttl)
concurrent-http-server concurrent-http-server
`(#:socket ,socket))) `(#:socket ,socket)))
@ -358,6 +377,7 @@ blocking."
%default-options)) %default-options))
(user (assoc-ref opts 'user)) (user (assoc-ref opts 'user))
(port (assoc-ref opts 'port)) (port (assoc-ref opts 'port))
(ttl (assoc-ref opts 'narinfo-ttl))
(address (let ((addr (assoc-ref opts 'address))) (address (let ((addr (assoc-ref opts 'address)))
(make-socket-address (sockaddr:fam addr) (make-socket-address (sockaddr:fam addr)
(sockaddr:addr addr) (sockaddr:addr addr)
@ -384,4 +404,4 @@ consider using the '--user' option!~%")))
(when repl-port (when repl-port
(repl:spawn-server (repl:make-tcp-server-socket #:port repl-port))) (repl:spawn-server (repl:make-tcp-server-socket #:port repl-port)))
(with-store store (with-store store
(run-publish-server socket store))))) (run-publish-server socket store #:narinfo-ttl ttl)))))