Skip to content

Commit e651ed3

Browse files
authored
Faster reading from and writing to disk (#207)
1 parent 4664af3 commit e651ed3

File tree

10 files changed

+387
-280
lines changed

10 files changed

+387
-280
lines changed

.github/workflows/main.yml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ jobs:
7171
nix-env --uninstall codd
7272
7373
- name: Run tests
74-
run: nix develop .#shellWithRunfile.x86_64-linux -c run ci-tests
74+
run: nix develop .#shellWithRunfile -c run ci-tests
7575

7676
- name: Run benchmarks
7777
run: nix run ".#x86_64-unknown-linux-musl:codd:bench:codd-bench"
@@ -121,6 +121,12 @@ jobs:
121121
- name: Build codd without static linking
122122
run: nix build --no-link ".#codd:exe:codd"
123123

124+
- name: Build codd's tests
125+
run: nix build --no-link ".#codd:test:codd-test"
126+
127+
- name: Run tests
128+
run: nix develop .#shellWithRunfile -c run test-no-db --nix
129+
124130
- name: Create macOS app bundle
125131
run: |
126132
nix build .#coddDarwinAppBundle.aarch64-darwin

README.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -113,8 +113,8 @@ Automatic merge failed; fix conflicts and then commit the result.
113113

114114
</table>
115115

116-
¹ Some SQL must run without explicit transactions; single-transaction application only works when none of that is present.
117-
² There can be false positives and false negatives in some cases.
116+
¹ Postgresql itself requires some SQL to run without explicit transactions; single-transaction application only works when that is not present.
117+
² There can be false positives and false negatives in some cases.
118118

119119
## Installing Codd
120120

@@ -158,7 +158,7 @@ Create this file and save it as `bootstrap-db.sql`:
158158
CREATE DATABASE codd_experiments;
159159
````
160160
161-
That's a lot to take in. codd handles pure SQL migrations but also has some special header comments defined that can make it do special things.
161+
That's a lot to take in. Codd handles pure SQL migrations but also has some special header comments defined that can make it do special things.
162162

163163
- The `-- codd: no-txn` header comment specifies that this migration can't run inside a transaction. Postgres doesn't allow us to create databases (plus a few other statements) inside transactions, after all.
164164
- The `-- codd-connection` header comment specifies that this specific migration will run with its own connection string, not with the default one.
@@ -214,10 +214,10 @@ We recommend following these instructions closely to catch as many possible issu
214214
## Frequently Asked Questions
215215
216216
1. ### Why does taking and restoring a database dump affect my expected codd schema?
217-
`pg_dump` does not dump all of the schema state that codd checks. A few examples include (at least with PG 13) role related state, the database's default transaction isolation level and deferredness, among possibly others. So check that it isn't the case that you get different schemas when that happens. If you've checked with `psql` and everything looks to be the same please report a bug in codd.
217+
`pg_dump` does not dump all of the schema state that codd checks. A few examples include role related state, the database's default transaction isolation level and deferredness, among other settings. So check that it isn't the case that you get different schemas when that happens. If you've checked with `psql` and everything looks to be the same please report a bug in codd.
218218

219219
2. ### Will codd run out of memory or system resources if my migration files are too large or too many?
220-
Most likely not. Codd reads migrations from disk in streaming fashion and keeps in memory only a single statement at a time. For `COPY` statements, codd uses a constant-size buffer to stream-read the contents and achieve bounded memory usage while staying fast. Also, codd does not open more than one migration file simultaneously to stay well below typical file handle limits imposed by the shell or operating system, and that is also assured through an automated test that runs in CI with `strace`. Codd does keep metadata about all pending migrations in memory, but that should be fairly small.
220+
Most likely not. Codd reads migrations from disk in streaming fashion and keeps in memory only a single statement at a time. For `COPY` statements, codd uses a constant-size buffer to stream-read the contents and achieve bounded memory usage while staying fast. Also, codd does not open more than one migration file simultaneously to stay well below typical file handle limits imposed by the shell or operating system, and that is also assured through an automated test that runs in CI with `strace`. Codd does keep metadata about all pending migrations and the expected schema in memory, but those should be fairly small.
221221

222222
3. ### Will codd handle SQL errors nicely?
223-
Codd tries to do the "best possible thing" even in rather unusual situations. It will retry sets of consecutive in-txn migrations atomically so as not to leave your database in an intermediary state. Even for no-txn migrations, codd will retry the failing statement instead of entire migrations, and _even_ if you write explicit `BEGIN..COMMIT` sections in no-txn migrations, codd will be smart enough to retry from the `BEGIN` if a statement inside that section fails. See the [retry examples](/docs/SQL-MIGRATIONS.md#examples) if you're interested. What codd currently cannot handle well is having its connection killed by an external agent while it's applying a _no-txn_ migration, a scenario which should be extremely rare. Basically, we hope you should be able to write your migrations however you want and rely comfortably on the fact that codd should do the reasonable thing when handling errors.
223+
Codd tries to do the "best possible thing" even in rather unusual situations. It will retry sets of consecutive in-txn migrations atomically so as not to leave your database in an intermediary state. Even for no-txn migrations, codd will retry the failing statement instead of entire migrations, and _even_ if you write explicit `BEGIN..COMMIT` sections in no-txn migrations, codd will be smart enough to retry from the `BEGIN` if a statement inside that section fails. See the [retry examples](/docs/SQL-MIGRATIONS.md#examples) if you're interested. Basically, we hope you should be able to write your migrations however you want and rely comfortably on the fact that codd should do the reasonable thing when handling errors.

Runfile

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,9 @@ test-no-db:
6868
# This Run command is used insire pure Nix shells where `nix` is not available. That's why
6969
# this option is useful.
7070
if [ -z "$NONIXBUILD" ]; then
71-
nix build ".#x86_64-unknown-linux-musl:codd:test:codd-test" -o local/codd-test
71+
TARGET=".#x86_64-unknown-linux-musl:codd:test:codd-test"
72+
[[ "$(uname -s)" == *"Darwin"* ]] && TARGET=".#codd:test:codd-test"
73+
nix build "$TARGET" -o local/codd-test
7274
fi
7375

7476
"${STRACECMD[@]}" ./local/codd-test/bin/codd-test "${TARGS[@]}"
@@ -92,12 +94,14 @@ test-with-db:
9294

9395
# Build the test executable only once with Nix
9496
if [ -n "$NIX" ]; then
95-
nix build ".#x86_64-unknown-linux-musl:codd:test:codd-test" -o local/codd-test
97+
TARGET=".#x86_64-unknown-linux-musl:codd:test:codd-test"
98+
[[ "$(uname -s)" == *"Darwin"* ]] && TARGET=".#codd:test:codd-test"
99+
nix build "$TARGET" -o local/codd-test
96100
fi
97101

98102
for pg in "${PG[@]}"; do
99103
echo "Running tests on Postgres $pg"
100-
nix develop ".#testShells.x86_64-linux.pg${pg}" "${NIXDEVARGS[@]}" -c run test-with-db-internal "${NIXA[@]}" -- "${TARGS[@]}"
104+
nix develop ".#pg${pg}" "${NIXDEVARGS[@]}" -c run test-with-db-internal "${NIXA[@]}" -- "${TARGS[@]}"
101105
done
102106

103107
##
@@ -130,9 +134,9 @@ test-system-resources:
130134

131135
if [ -n "$NIX" ]; then
132136
nix build ".#x86_64-unknown-linux-musl:codd:test:codd-test" -o local/codd-test
133-
nix develop ".#testShells.x86_64-linux.pg16" -i -c run test-with-db-internal --strace --nix -- --match "/SystemResourcesSpecs/RUNNING"
134-
nix develop ".#testShells.x86_64-linux.pg16" -i -c run test-with-db-internal --nix -- --match "/SystemResourcesSpecs/CHECKING"
137+
nix develop ".#pg16" -i -c run test-with-db-internal --strace --nix -- --match "/SystemResourcesSpecs/RUNNING"
138+
nix develop ".#pg16" -i -c run test-with-db-internal --nix -- --match "/SystemResourcesSpecs/CHECKING"
135139
else
136-
nix develop ".#testShells.x86_64-linux.pg16" -c run test-with-db-internal --strace -- --match "/SystemResourcesSpecs/RUNNING"
137-
nix develop ".#testShells.x86_64-linux.pg16" -c run test-with-db-internal -- --match "/SystemResourcesSpecs/CHECKING"
140+
nix develop ".#pg16" -c run test-with-db-internal --strace -- --match "/SystemResourcesSpecs/RUNNING"
141+
nix develop ".#pg16" -c run test-with-db-internal -- --match "/SystemResourcesSpecs/CHECKING"
138142
fi

codd.cabal

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ library
8989
, bytestring
9090
, clock
9191
, containers
92+
, deepseq
9293
, dlist
9394
, filepath
9495
, formatting
@@ -263,6 +264,7 @@ test-suite codd-test
263264
, base
264265
, codd
265266
, containers
267+
, filepath
266268
, hashable
267269
, hspec
268270
, hspec-core
@@ -277,4 +279,5 @@ test-suite codd-test
277279
, time
278280
, typed-process
279281
, unliftio
282+
, uuid
280283
default-language: Haskell2010

flake.lock

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

flake.nix

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@
104104
cacert
105105
ghcid
106106
glibcLocales
107+
hyperfine
107108
postgres-service
108109
postgresql_16
109110
run
@@ -144,17 +145,16 @@
144145
# Built by `nix build .`
145146
defaultPackage = flakeDefault.packages."codd:exe:codd";
146147

147-
testShells = {
148+
devShells = flakeDefault.devShells // {
148149
pg12 = import ./nix/test-shell-pg12.nix { inherit pkgs; };
149150
pg13 = import ./nix/test-shell-pg13.nix { inherit pkgs; };
150151
pg14 = import ./nix/test-shell-pg14.nix { inherit pkgs; };
151152
pg15 = import ./nix/test-shell-pg15.nix { inherit pkgs; };
152153
pg16 = import ./nix/test-shell-pg16.nix { inherit pkgs; };
154+
shellWithRunfile =
155+
pkgs.mkShell { buildInputs = [ pkgs.run pkgs.shellcheck ]; };
153156
};
154157

155-
shellWithRunfile =
156-
pkgs.mkShell { buildInputs = [ pkgs.run pkgs.shellcheck ]; };
157-
158158
# Having pkgs helps debug musl builds with `nix repl`. We can e.g.
159159
# build musl packages statically to see if their "normal" builds pass
160160
inherit pkgs;

0 commit comments

Comments
 (0)