rails: Add the ability to schedule services with a systemd timer

This commit is contained in:
Peter Jones 2019-01-07 14:05:12 -07:00
parent 48e5035383
commit 14d701b388
No known key found for this signature in database
GPG key ID: 9DAFAA8D01941E49
2 changed files with 34 additions and 2 deletions

View file

@ -16,6 +16,7 @@ let
# The main Rails service: # The main Rails service:
mainService = app: { mainService = app: {
name = "main"; name = "main";
schedule = null;
isMain = true; isMain = true;
script = '' script = ''
@ -98,10 +99,11 @@ let
description = "${app.name} (Ruby on Rails) ${service.name}"; description = "${app.name} (Ruby on Rails) ${service.name}";
path = appPath app; path = appPath app;
environment = appEnv app; environment = appEnv app;
wantedBy = [ "multi-user.target" ];
# Only start this service if it isn't scheduled by a timer.
wantedBy = optional (service.schedule == null) "multi-user.target";
wants = wants =
optional (!service.isMain) "rails-${app.name}-main" ++
plib.keyService app.database.passwordFile ++ plib.keyService app.database.passwordFile ++
plib.keyService app.sourcedFile; plib.keyService app.sourcedFile;
@ -166,6 +168,17 @@ let
}; };
}; };
##############################################################################
# Schedule some services with a systemd timer:
appTimer = app: service: optionalAttrs (service.schedule != null) {
"rails-${app.name}-${service.name}" = {
description = "${app.name} (Ruby on Rails) ${service.name}";
wantedBy = [ "timers.target" ];
timerConfig.OnCalendar = service.schedule;
timerConfig.Unit = "rails-${app.name}-${service.name}.service";
};
};
############################################################################## ##############################################################################
# Collect all services for a given application and turn them into # Collect all services for a given application and turn them into
# systemd services. # systemd services.
@ -173,6 +186,12 @@ let
foldr (service: set: recursiveUpdate set (appService app service)) {} foldr (service: set: recursiveUpdate set (appService app service)) {}
( [(mainService app)] ++ attrValues app.services ); ( [(mainService app)] ++ attrValues app.services );
##############################################################################
# Collect all services and turn them into systemd timers:
appTimers = app:
foldr (service: set: recursiveUpdate set (appTimer app service)) {}
(attrValues app.services);
############################################################################## ##############################################################################
# Generate a user account for a Ruby on Rails application: # Generate a user account for a Ruby on Rails application:
appUser = app: { appUser = app: {
@ -217,6 +236,7 @@ in
# Each application gets one or more systemd services to keep it # Each application gets one or more systemd services to keep it
# running. # running.
systemd.services = collectApps appServices; systemd.services = collectApps appServices;
systemd.timers = collectApps appTimers;
# Rotate all of the log files: # Rotate all of the log files:
services.logrotate = { services.logrotate = {

View file

@ -68,6 +68,18 @@ let
description = "Shell commands executed as the service's main process."; description = "Shell commands executed as the service's main process.";
}; };
schedule = mkOption {
type = types.nullOr types.str;
default = null;
example = "*-*-* *:00/5:00";
description = ''
If null (the default), run this service in the background
continuously, restarting it if it stops. However, if this
option is set, it should be a systemd calendar string and
this service will run on a scheduled timer instead.
'';
};
isMain = mkOption { isMain = mkOption {
internal = true; internal = true;
type = types.bool; type = types.bool;