services-flake/nix/clickhouse/default.nix

183 lines
6.8 KiB
Nix
Raw Normal View History

# Based on: https://github.com/cachix/devenv/blob/main/src/modules/services/clickhouse.nix
{ pkgs, lib, name, config, ... }:
let
inherit (lib) types;
yamlFormat = pkgs.formats.yaml { };
in
{
options = {
enable = lib.mkEnableOption name;
package = lib.mkOption {
type = types.package;
description = "Which package of clickhouse to use";
default = pkgs.clickhouse;
defaultText = lib.literalExpression "pkgs.clickhouse";
};
port = lib.mkOption {
type = types.int;
description = "Which port to run clickhouse on. This port is for `clickhouse-client` program";
default = 9000;
};
dataDir = lib.mkOption {
type = types.str;
default = "./data/${name}";
description = "The clickhouse data directory";
};
defaultExtraConfig = lib.mkOption {
type = yamlFormat.type;
internal = true;
readOnly = true;
default = {
logger.level = "warning";
logger.console = 1;
default_profile = "default";
default_database = "default";
tcp_port = toString config.port;
path = "${config.dataDir}/clickhouse";
tmp_path = "${config.dataDir}/clickhouse/tmp";
user_files_path = "${config.dataDir}/clickhouse/user_files";
format_schema_path = "${config.dataDir}/clickhouse/format_schemas";
user_directories = {
users_xml = {
path = "${config.package}/etc/clickhouse-server/users.xml";
};
};
};
};
extraConfig = lib.mkOption {
type = yamlFormat.type;
description = "Additional configuration to be appended to `clickhouse-config.yaml`.";
default = { };
};
initialDatabases = lib.mkOption {
type = types.listOf (types.submodule {
options = {
name = lib.mkOption {
type = types.str;
description = ''
The name of the database to create.
'';
};
schemas = lib.mkOption {
type = types.nullOr (types.listOf types.path);
default = null;
description = ''
The initial list of schemas for the database; if null (the default),
an empty database is created.
'';
};
};
});
default = [ ];
description = ''
List of database names and their initial schemas that should be used to create databases on the first startup
of Postgres. The schema attribute is optional: If not specified, an empty database is created.
'';
example = lib.literalExpression ''
[
{
name = "foodatabase";
schemas = [ ./fooschemas ./bar.sql ];
}
{ name = "bardatabase"; }
]
'';
};
outputs.settings = lib.mkOption {
type = types.deferredModule;
internal = true;
readOnly = true;
default = {
processes =
let
clickhouseConfig = yamlFormat.generate "clickhouse-config.yaml" (
lib.recursiveUpdate config.defaultExtraConfig config.extraConfig
);
in
{
# DB initialization
"${name}-init" =
let
# https://github.com/ClickHouse/ClickHouse/issues/4491
setupInitialSchema = schema: '' < ${schema} tr -s '\r\n' ' ' | clickhouse-client -mn --port ${builtins.toString config.port}; '';
setupInitialDatabases =
lib.concatMapStrings
(database: ''
echo "Creating database: ${database.name}"
clickhouse-client --port ${builtins.toString config.port} --query "CREATE DATABASE iF NOT EXISTS ${database.name}"
echo "Database successfully created: ${database.name}"
${lib.optionalString (database.schemas != null)
(lib.concatMapStrings (schema: setupInitialSchema schema) database.schemas)}
'')
config.initialDatabases;
setupScript = pkgs.writeShellApplication {
name = "setup-clickhouse";
runtimeInputs = with pkgs; [ config.package coreutils gnugrep gawk ];
# TODO: Find a better way to start clickhouse-server than waiting for 5 seconds: https://github.com/juspay/services-flake/pull/91#discussion_r1481710799
text = ''
if test -d ${config.dataDir}
then echo "Clickhouse database directory ${config.dataDir} appears to contain a database; Skipping initialization"
else
echo "Clickhouse is setting up the initial database."
set -m
clickhouse-server --config-file=${clickhouseConfig} &
sleep 5s
echo "Clickhouse server started."
${setupInitialDatabases}
echo "Clickhouse db setting is done."
kill %1
echo "Clickhouse server stopped."
fi
'';
};
in
{
command = setupScript;
namespace = name;
};
# DB process
"${name}" =
let
startScript = pkgs.writeShellApplication {
name = "start-clickhouse";
runtimeInputs = [ config.package ];
text = ''
clickhouse-server --config-file=${clickhouseConfig}
'';
};
in
{
command = startScript;
readiness_probe = {
2024-02-27 17:05:08 +03:00
# FIXME: revert back to clickhouse-client readiness_probe once CI is moved out of github public runners
# See: https://github.com/juspay/services-flake/issues/100
# exec.command = ''${config.package}/bin/clickhouse-client --query "SELECT 1" --port ${builtins.toString config.port}'';
http_get = {
host = "localhost";
port = if (lib.hasAttr "http_port" config.extraConfig) then config.extraConfig.http_port else 8123;
};
initial_delay_seconds = 2;
period_seconds = 10;
timeout_seconds = 4;
success_threshold = 1;
failure_threshold = 5;
};
namespace = name;
depends_on."${name}-init".condition = "process_completed_successfully";
# https://github.com/F1bonacc1/process-compose#-auto-restart-if-not-healthy
availability.restart = "on_failure";
};
};
};
};
};
}