From c6aef6b82530dbcdaf352e3ba03b6fa4d0b7be61 Mon Sep 17 00:00:00 2001 From: Robert Vollmert Date: Fri, 24 Feb 2023 20:40:46 +0100 Subject: [PATCH 1/2] test: add optional latency to postgrest-loadtest This pipes data between client/postgrest and between postgrest/database through a proxy that adds delay (github.com/robx/slocat). --- default.nix | 1 + nix/README.md | 3 ++ nix/overlays/default.nix | 1 + nix/overlays/slocat.nix | 13 +++++++ nix/tools/loadtest.nix | 2 + nix/tools/withTools.nix | 80 +++++++++++++++++++++++++++++++++++++++- 6 files changed, 98 insertions(+), 2 deletions(-) create mode 100644 nix/overlays/slocat.nix diff --git a/default.nix b/default.nix index ebad92df28..be3cb73822 100644 --- a/default.nix +++ b/default.nix @@ -41,6 +41,7 @@ let allOverlays.postgresql-legacy allOverlays.postgresql-future (allOverlays.haskell-packages { inherit compiler; }) + allOverlays.slocat ]; # Evaluated expression of the Nixpkgs repository. diff --git a/nix/README.md b/nix/README.md index de7018cafe..2f67d90b73 100644 --- a/nix/README.md +++ b/nix/README.md @@ -204,6 +204,9 @@ postgrest-loadtest # You can loadtest comparing to a different branch postgrest-loadtest-against master +# You can simulate latency client/postgrest and postgrest/database +PGRST_DELAY=5ms PGDELAY=5ms postgrest-loadtest + # Produce a markdown report to be used on CI postgrest-loadtest-report ``` diff --git a/nix/overlays/default.nix b/nix/overlays/default.nix index 43d1548688..8b0b3af4ff 100644 --- a/nix/overlays/default.nix +++ b/nix/overlays/default.nix @@ -7,4 +7,5 @@ postgresql-default = import ./postgresql-default.nix; postgresql-legacy = import ./postgresql-legacy.nix; postgresql-future = import ./postgresql-future.nix; + slocat = import ./slocat.nix; } diff --git a/nix/overlays/slocat.nix b/nix/overlays/slocat.nix new file mode 100644 index 0000000000..cb17963c0e --- /dev/null +++ b/nix/overlays/slocat.nix @@ -0,0 +1,13 @@ +final: prev: +{ + slocat = prev.buildGoModule { + name = "slocat"; + src = prev.fetchFromGitHub { + owner = "robx"; + repo = "slocat"; + rev = "52e7512c6029fd00483e41ccce260a3b4b9b3b64"; + sha256 = "sha256-qn6luuh5wqREu3s8RfuMCP5PKdS2WdwPrujRYTpfzQ8="; + }; + vendorSha256 = "sha256-pQpattmS9VmO3ZIQUFn66az8GSmB4IvYhTTCFn6SUmo="; + }; +} diff --git a/nix/tools/loadtest.nix b/nix/tools/loadtest.nix index 4c9e964e67..4444999044 100644 --- a/nix/tools/loadtest.nix +++ b/nix/tools/loadtest.nix @@ -60,7 +60,9 @@ let # shellcheck disable=SC2145 ${withTools.withPg} --fixtures "$_arg_testdir"/fixtures.sql \ + ${withTools.withSlowPg} \ ${withTools.withPgrst} \ + ${withTools.withSlowPgrst} \ sh -c "cd \"$_arg_testdir\" && ${runner} -targets targets.http -output \"$abs_output\" \"''${_arg_leftovers[@]}\"" ${vegeta}/bin/vegeta report -type=text "$_arg_output" ''; diff --git a/nix/tools/withTools.nix b/nix/tools/withTools.nix index 7c7b2753e6..c7dceb49b1 100644 --- a/nix/tools/withTools.nix +++ b/nix/tools/withTools.nix @@ -8,6 +8,7 @@ , lib , postgresqlVersions , postgrest +, slocat , writeText }: let @@ -137,6 +138,81 @@ let withPg = builtins.head withPgVersions; + withSlowPg = + checkedShellScript + { + name = "postgrest-with-slow-pg"; + docs = "Run the given command with simulated high latency postgresql"; + args = + [ + "ARG_POSITIONAL_SINGLE([command], [Command to run])" + "ARG_LEFTOVERS([command arguments])" + "ARG_USE_ENV([PGHOST], [], [PG host (socket name)])" + "ARG_USE_ENV([PGDELAY], [0ms], [extra PG latency (duration)])" + ]; + positionalCompletion = "_command"; + inRootDir = true; + redirectTixFiles = false; + withTmpDir = true; + } + '' + delay="''${PGDELAY:-0ms}" + echo "delaying data to/from postgres by $delay" + + REALPGHOST="$PGHOST" + export PGHOST="$tmpdir/socket" + mkdir -p "$PGHOST" + + ${slocat}/bin/slocat -delay "$delay" -src "$PGHOST/.s.PGSQL.5432" -dst "$REALPGHOST/.s.PGSQL.5432" & + SLOCAT_PID=$! + # shellcheck disable=SC2317 + stop_slocat() { + kill "$SLOCAT_PID" || true + wait "$SLOCAT_PID" || true + } + trap stop_slocat EXIT + sleep 1 # should wait for socket file to appear instead + + ("$_arg_command" "''${_arg_leftovers[@]}") + ''; + + withSlowPgrst = + checkedShellScript + { + name = "postgrest-with-slow-postgrest"; + docs = "Run the given command with simulated high latency postgrest"; + args = + [ + "ARG_POSITIONAL_SINGLE([command], [Command to run])" + "ARG_LEFTOVERS([command arguments])" + "ARG_USE_ENV([PGRST_SERVER_UNIX_SOCKET], [], [PostgREST host (socket name)])" + "ARG_USE_ENV([PGRST_DELAY], [0ms], [extra PostgREST latency (duration)])" + ]; + positionalCompletion = "_command"; + inRootDir = true; + redirectTixFiles = false; + withTmpDir = true; + } + '' + delay="''${PGRST_DELAY:-0ms}" + echo "delaying data to/from PostgREST by $delay" + + REAL_PGRST_SERVER_UNIX_SOCKET="$PGRST_SERVER_UNIX_SOCKET" + export PGRST_SERVER_UNIX_SOCKET="$tmpdir/postgrest.socket" + + ${slocat}/bin/slocat -delay "$delay" -src "$PGRST_SERVER_UNIX_SOCKET" -dst "$REAL_PGRST_SERVER_UNIX_SOCKET" & + SLOCAT_PID=$! + # shellcheck disable=SC2317 + stop_slocat() { + kill "$SLOCAT_PID" || true + wait "$SLOCAT_PID" || true + } + trap stop_slocat EXIT + sleep 1 # should wait for socket file to appear instead + + ("$_arg_command" "''${_arg_leftovers[@]}") + ''; + withGit = let name = "postgrest-with-git"; @@ -288,7 +364,7 @@ in buildToolbox { name = "postgrest-with"; - tools = [ withPgAll withGit withPgrst ] ++ withPgVersions; + tools = [ withPgAll withGit withPgrst withSlowPg withSlowPgrst ] ++ withPgVersions; # make withTools available for other nix files - extra = { inherit withGit withPg withPgAll withPgrst; }; + extra = { inherit withGit withPg withPgAll withPgrst withSlowPg withSlowPgrst; }; } From 7ab10d5190b6b14d77bf0d8966eb53ce0b1dab0c Mon Sep 17 00:00:00 2001 From: Robert Vollmert Date: Thu, 16 Mar 2023 11:49:22 +0100 Subject: [PATCH 2/2] test: optionally build postgrest with cabal in postgrest-loadtest By default, postgrest-with-pgrst builds postgrest as a nix package, which means that source changes cause a full rebuild. With this change, running the loadtest as PGRST_BUILD_CABAL=1 postgrest-loadtest rebuilds directly using cabal, like postgrest-build. Note that results between nix and cabal builds aren't necessarily comparable due to differing build parameters. --- default.nix | 6 +++--- nix/README.md | 3 +++ nix/tools/cabalTools.nix | 2 +- nix/tools/withTools.nix | 22 +++++++++++++++------- 4 files changed, 22 insertions(+), 11 deletions(-) diff --git a/default.nix b/default.nix index be3cb73822..e18d5010e4 100644 --- a/default.nix +++ b/default.nix @@ -122,6 +122,9 @@ rec { cabalTools = pkgs.callPackage nix/tools/cabalTools.nix { inherit devCabalOptions postgrest; }; + withTools = + pkgs.callPackage nix/tools/withTools.nix { inherit cabalTools devCabalOptions postgresqlVersions postgrest; }; + # Development tools. devTools = pkgs.callPackage nix/tools/devTools.nix { inherit tests style devCabalOptions hsie withTools; }; @@ -154,9 +157,6 @@ rec { inherit (pkgs.haskell.packages."${compiler}") hpc-codecov; inherit (pkgs.haskell.packages."${compiler}") weeder; }; - - withTools = - pkgs.callPackage nix/tools/withTools.nix { inherit devCabalOptions postgresqlVersions postgrest; }; } // pkgs.lib.optionalAttrs pkgs.stdenv.isLinux rec { # Static executable. inherit postgrestStatic; diff --git a/nix/README.md b/nix/README.md index 2f67d90b73..a043302fdb 100644 --- a/nix/README.md +++ b/nix/README.md @@ -207,6 +207,9 @@ postgrest-loadtest-against master # You can simulate latency client/postgrest and postgrest/database PGRST_DELAY=5ms PGDELAY=5ms postgrest-loadtest +# You can build postgrest directly with cabal for faster iteration +PGRST_BUILD_CABAL=1 postgrest-loadtest + # Produce a markdown report to be used on CI postgrest-loadtest-report ``` diff --git a/nix/tools/cabalTools.nix b/nix/tools/cabalTools.nix index 4f030661e6..7557d650c5 100644 --- a/nix/tools/cabalTools.nix +++ b/nix/tools/cabalTools.nix @@ -37,7 +37,7 @@ let checkedShellScript { name = "postgrest-run"; - docs = "Run PostgREST after buidling it interactively with cabal-install"; + docs = "Run PostgREST after building it interactively with cabal-install"; args = [ "ARG_LEFTOVERS([PostgREST arguments])" ]; inRootDir = true; withEnv = postgrest.env; diff --git a/nix/tools/withTools.nix b/nix/tools/withTools.nix index c7dceb49b1..eba52d6062 100644 --- a/nix/tools/withTools.nix +++ b/nix/tools/withTools.nix @@ -1,6 +1,7 @@ { bash-completion , buildToolbox , cabal-install +, cabalTools , checkedShellScript , curl , devCabalOptions @@ -333,16 +334,23 @@ let export PGRST_SERVER_UNIX_SOCKET="$tmpdir"/postgrest.socket rm -f result - echo -n "Building postgrest... " - nix-build -A postgrestPackage > "$tmpdir"/build.log 2>&1 || { - echo "failed, output:" - cat "$tmpdir"/build.log - exit 1 - } + if [ -z "''${PGRST_BUILD_CABAL:-}" ]; then + echo -n "Building postgrest (nix)... " + nix-build -A postgrestPackage > "$tmpdir"/build.log 2>&1 || { + echo "failed, output:" + cat "$tmpdir"/build.log + exit 1 + } + PGRST_CMD=./result/bin/postgrest + else + echo -n "Building postgrest (cabal)... " + postgrest-build + PGRST_CMD=postgrest-run + fi echo "done." echo -n "Starting postgrest... " - ./result/bin/postgrest ${legacyConfig} > "$tmpdir"/run.log 2>&1 & + $PGRST_CMD ${legacyConfig} > "$tmpdir"/run.log 2>&1 & pid=$! # shellcheck disable=SC2317 cleanup() {