nixos/firefox-syncserver: fix setup failure due to duplicate key

in some circumstances, the setup service would fail with:
ERROR 1062 (23000) at line 5: Duplicate entry '1' for key 'PRIMARY'
so let's use an upsert instead of insert. This also simplifies the
script.

Besides, also fix that when the setup script changes, the corresponding
script is not restarted as it is usually not active, so we trigger a
restart of the main systemd service.
This commit is contained in:
Guillaume Girol 2022-10-30 12:00:00 +00:00 committed by pennae
parent f26896669b
commit 255ac994b8

View File

@ -32,6 +32,44 @@ let
}; };
}; };
configFile = format.generate "syncstorage.toml" (lib.recursiveUpdate settings cfg.settings); configFile = format.generate "syncstorage.toml" (lib.recursiveUpdate settings cfg.settings);
setupScript = pkgs.writeShellScript "firefox-syncserver-setup" ''
set -euo pipefail
shopt -s inherit_errexit
schema_configured() {
mysql ${cfg.database.name} -Ne 'SHOW TABLES' | grep -q services
}
update_config() {
mysql ${cfg.database.name} <<"EOF"
BEGIN;
INSERT INTO `services` (`id`, `service`, `pattern`)
VALUES (1, 'sync-1.5', '{node}/1.5/{uid}')
ON DUPLICATE KEY UPDATE service='sync-1.5', pattern='{node}/1.5/{uid}';
INSERT INTO `nodes` (`id`, `service`, `node`, `available`, `current_load`,
`capacity`, `downed`, `backoff`)
VALUES (1, 1, '${cfg.singleNode.url}', ${toString cfg.singleNode.capacity},
0, ${toString cfg.singleNode.capacity}, 0, 0)
ON DUPLICATE KEY UPDATE node = '${cfg.singleNode.url}', capacity=${toString cfg.singleNode.capacity};
COMMIT;
EOF
}
for (( try = 0; try < 60; try++ )); do
if ! schema_configured; then
sleep 2
else
update_config
exit 0
fi
done
echo "Single-node setup failed"
exit 1
'';
in in
{ {
@ -210,6 +248,7 @@ in
wantedBy = [ "multi-user.target" ]; wantedBy = [ "multi-user.target" ];
requires = lib.mkIf dbIsLocal [ "mysql.service" ]; requires = lib.mkIf dbIsLocal [ "mysql.service" ];
after = lib.mkIf dbIsLocal [ "mysql.service" ]; after = lib.mkIf dbIsLocal [ "mysql.service" ];
restartTriggers = lib.optional cfg.singleNode.enable setupScript;
environment.RUST_LOG = cfg.logLevel; environment.RUST_LOG = cfg.logLevel;
serviceConfig = { serviceConfig = {
User = defaultUser; User = defaultUser;
@ -255,56 +294,7 @@ in
requires = [ "firefox-syncserver.service" ] ++ lib.optional dbIsLocal "mysql.service"; requires = [ "firefox-syncserver.service" ] ++ lib.optional dbIsLocal "mysql.service";
after = [ "firefox-syncserver.service" ] ++ lib.optional dbIsLocal "mysql.service"; after = [ "firefox-syncserver.service" ] ++ lib.optional dbIsLocal "mysql.service";
path = [ config.services.mysql.package ]; path = [ config.services.mysql.package ];
script = '' serviceConfig.ExecStart = [ "${setupScript}" ];
set -euo pipefail
shopt -s inherit_errexit
schema_configured() {
mysql ${cfg.database.name} -Ne 'SHOW TABLES' | grep -q services
}
services_configured() {
[ 1 != $(mysql ${cfg.database.name} -Ne 'SELECT COUNT(*) < 1 FROM `services`') ]
}
create_services() {
mysql ${cfg.database.name} <<"EOF"
BEGIN;
INSERT INTO `services` (`id`, `service`, `pattern`)
VALUES (1, 'sync-1.5', '{node}/1.5/{uid}');
INSERT INTO `nodes` (`id`, `service`, `node`, `available`, `current_load`,
`capacity`, `downed`, `backoff`)
VALUES (1, 1, '${cfg.singleNode.url}', ${toString cfg.singleNode.capacity},
0, ${toString cfg.singleNode.capacity}, 0, 0);
COMMIT;
EOF
}
update_nodes() {
mysql ${cfg.database.name} <<"EOF"
UPDATE `nodes`
SET `capacity` = ${toString cfg.singleNode.capacity}
WHERE `id` = 1;
EOF
}
for (( try = 0; try < 60; try++ )); do
if ! schema_configured; then
sleep 2
elif services_configured; then
update_nodes
exit 0
else
create_services
exit 0
fi
done
echo "Single-node setup failed"
exit 1
'';
}; };
services.nginx.virtualHosts = lib.mkIf cfg.singleNode.enableNginx { services.nginx.virtualHosts = lib.mkIf cfg.singleNode.enableNginx {