Subject: [bug#50504] [PATCH] home-services: Add Mcron.

From: Xinglu Chen <[email-masked]>
Date: Fri, 10 Sep 2021 20:22:30 +0200

On Fri, Sep 10 2021, Andrew Tropin wrote:

> * gnu/home-services/mcron.scm: New file.
> * gnu/local.mk: Add this.
> * doc/guix.texi: Add documentation about Mcron Home Service.
> ---
>
> This is the last of home services I consider "must-have" for wip-guix-home.
>
> It reuses two functions from (gnu services mcron) via @@, which can be
> considered as a hack, the alternative solution is to expose those functions
> via #:export, I can do it if it's a preffered way or suggest other ideas,
> please.  The discussion on this topic: https://issues.guix.gnu.org/47238
> Included Ludovic and Xinglu in CC.

An alternative would be put it the (gnu service mcron) to share more
code between system service and home service.  This was discussed
briefly on rde-devel[1].  It might be worth discussing this issue on
guix-devel before we add too many home service.

> I took a brief look at the testing approach, seems the most relevant is
> guix-system.sh and it is just a shell script, which runs a few guix system
> subcommand and check if they fail or succeed.  Please let me know, what is a
> preferred way for writing tests and I'll try to provide some tests for Guix
> Home in the separate patch.

The ‘guix-system.sh’ script seems to only test the ‘guix system’
command, which doesn’t seem that related to the home services.  I guess
we could check the contents of the generated config files.  There is
(gnu build marionette) which creates a VM; we could then check that the
relevant process is running.  Maybe there is a better approach, though.

[1]: <https://lists.sr.ht/~abcdw/rde-devel/%3C87y2cqifpx.fsf%40yoctocell.xyz%3E>

>  doc/guix.texi               |  31 +++++++++-
>  gnu/home-services/mcron.scm | 115 ++++++++++++++++++++++++++++++++++++
>  gnu/local.mk                |   1 +
>  3 files changed, 146 insertions(+), 1 deletion(-)
>  create mode 100644 gnu/home-services/mcron.scm
>
> diff --git a/doc/guix.texi b/doc/guix.texi
> index e546fcc0d2..a7eacad762 100644
> --- a/doc/guix.texi
> +++ b/doc/guix.texi
> @@ -35685,7 +35685,36 @@ for example).
>  @cindex mcron
>  @cindex scheduling jobs
>  
> -mcron info here
> +The @code{(gnu home-services mcron)} module provides an interface to
> +GNU@tie{}mcron, a daemon to run jobs at scheduled times (@pxref{Top,,,
> +mcron, GNU@tie{}mcron}).  The information about system's mcron is
> +applicable here (@pxref{Scheduled Job Execution}), the only difference
> +for home services is that they have to be declared in
> +@code{home-envirnoment} record instead of @code{operating-system}.

“declared in a @code{home-environemnt} record instead of a
@code{operating-system} record.”

> +@defvr {Scheme Variable} home-mcron-service-type
> +This is the type of the @code{mcron} home service, whose value is an

Why @code{mcron}?  I would use “Mcron” instead.

> +@code{home-mcron-configuration} object.  It allows to manage tasks

“It allows one to manage scheduled tasks.”

> +This service type can be the target of a service extension that provides
> +it additional job specifications (@pxref{Service Composition}).  In

s/it//

> +other words, it is possible to define services that provide additional
> +mcron jobs to run.
> +@end defvr
> +
> +@deftp {Data Type} home-mcron-configuration
> +Data type representing the configuration of mcron.
> +
> +@table @asis
> +@item @code{mcron} (default: @var{mcron})
> +The mcron package to use.
> +
> +@item @code{jobs}
> +This is a list of gexps (@pxref{G-Expressions}), where each gexp
> +corresponds to an mcron job specification (@pxref{Syntax, mcron job
> +specifications,, mcron, GNU@tie{}mcron}).
> +@end table
> +@end deftp
>  
>  @node Shepherd Home Service
>  @subsection Managing User's Daemons
> diff --git a/gnu/home-services/mcron.scm b/gnu/home-services/mcron.scm
> new file mode 100644
> index 0000000000..fdfde179a5
> --- /dev/null
> +++ b/gnu/home-services/mcron.scm
> @@ -0,0 +1,115 @@
> +;;; GNU Guix --- Functional package management for GNU
> +;;; Copyright © 2021 Andrew Tropin <[email-masked]>
> +;;; Copyright © 2021 Xinglu Chen <[email-masked]>
> +;;;
> +;;; This file is part of GNU Guix.
> +;;;
> +;;; GNU Guix is free software; you can redistribute it and/or modify it
> +;;; under the terms of the GNU General Public License as published by
> +;;; the Free Software Foundation; either version 3 of the License, or (at
> +;;; your option) any later version.
> +;;;
> +;;; GNU Guix is distributed in the hope that it will be useful, but
> +;;; WITHOUT ANY WARRANTY; without even the implied warranty of
> +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +;;; GNU General Public License for more details.
> +;;;
> +;;; You should have received a copy of the GNU General Public License
> +;;; along with GNU Guix.  If not, see <http://www.gnu.org/licenses/>.
> +
> +(define-module (gnu home-services mcron)
> +  #:use-module (gnu packages guile-xyz)
> +  #:use-module (gnu home-services)
> +  #:use-module (gnu home-services shepherd)
> +  #:use-module (gnu services shepherd)
> +  #:use-module (guix records)
> +  #:use-module (guix gexp)
> +  #:use-module (srfi srfi-1)
> +  #:use-module (ice-9 match)
> +
> +  #:export (home-mcron-configuration
> +            home-mcron-service-type))
> +
> +;;; Commentary:
> +;;
> +;; Service for the GNU mcron cron job manager.
> +;;
> +;; Example configuration, the first job runs mbsync once every ten
> +;; minutes, the second one writes "Mcron service" to ~/mcron-file once
> +;; every minute.
> +;;
> +;; (service home-mcron-service-type
> +;;            (home-mcron-configuration
> +;;             (jobs (list #~(job '(next-minute
> +;;                                  (range 0 60 10))
> +;;                                (lambda ()
> +;;                                  (system* "mbsync" "--all")))
> +;;                         #~(job next-minute-from
> +;;                                (lambda ()
> +;;                                  (call-with-output-file (string-append (getenv "HOME")
> +;;                                                                        "/mcron-file")
> +;;                                    (lambda (port)
> +;;                                      (display "Mcron service" port)))))))))
> +;;
> +;;; Code:
> +
> +(define-record-type* <home-mcron-configuration> home-mcron-configuration
> +  make-home-mcron-configuration
> +  home-mcron-configuration?
> +  (package home-mcron-configuration-package ; package
> +           (default mcron))
> +  (jobs home-mcron-configuration-jobs   ; list of jobs
> +        (default '())))
> +
> +(define job-files (@@ (gnu services mcron) job-files))
> +(define shepherd-schedule-action
> +  (@@ (gnu services mcron) shepherd-schedule-action))
> +
> +(define home-mcron-shepherd-services
> +  (match-lambda
> +    (($ <home-mcron-configuration> mcron '()) ; no jobs to run
> +     '())
> +    (($ <home-mcron-configuration> mcron jobs)
> +     (let ((files (job-files mcron jobs)))
> +       (list (shepherd-service
> +              (documentation "User cron jobs.")
> +              (provision '(mcron))
> +              (modules `((srfi srfi-1)
> +                         (srfi srfi-26)
> +                         (ice-9 popen)            ; for the 'schedule' action
> +                         (ice-9 rdelim)
> +                         (ice-9 match)
> +                         ,@%default-modules))
> +              (start #~(make-forkexec-constructor
> +                        (list #$(file-append mcron "/bin/mcron") #$@files)
> +                        #:log-file (string-append
> +                                    (or (getenv "XDG_LOG_HOME")
> +                                        (format #f "~a/.local/var/log"
> +                                                (getenv "HOME")))
> +                                    "/mcron.log")))
> +              (stop #~(make-kill-destructor))
> +              (actions
> +               (list (shepherd-schedule-action mcron files)))))))))
> +
> +(define home-mcron-profile (compose list home-mcron-configuration-package))
> +
> +(define (home-mcron-extend config jobs)
> +  (home-mcron-configuration
> +   (inherit config)
> +   (jobs (append (home-mcron-configuration-jobs config)
> +                 jobs))))
> +
> +(define home-mcron-service-type
> +  (service-type (name 'home-mcron)
> +                (extensions
> +                 (list (service-extension
> +                        home-shepherd-service-type
> +                        home-mcron-shepherd-services)
> +                       (service-extension
> +                        home-profile-service-type
> +                        home-mcron-profile)))
> +                (compose concatenate)
> +                (extend home-mcron-extend)
> +                (default-value (home-mcron-configuration))
> +                (description
> +                 "Install and configure the GNU mcron cron job manager.")))
> diff --git a/gnu/local.mk b/gnu/local.mk
> index 31ad1a43db..8212bc5391 100644
> --- a/gnu/local.mk
> +++ b/gnu/local.mk
> @@ -80,6 +80,7 @@ GNU_SYSTEM_MODULES =				\
>    %D%/home-services/configuration.scm		\
>    %D%/home-services/shells.scm			\
>    %D%/home-services/shepherd.scm		\
> +  %D%/home-services/mcron.scm			\
>    %D%/home-services/utils.scm			\
>    %D%/home-services/xdg.scm			\
>    %D%/image.scm					\
> -- 
> 2.33.0