Skip to content

Commit b5051ef

Browse files
committed
Merge #1724: feat(tracker-core): add PostgreSQL driver (subissue #1723)
453dd48 ci(testing): split unit checks and merge docker e2e flow (Jose Celano) 735fe19 ci(testing): normalize sqlite qBittorrent e2e invocation (Jose Celano) 245e6a3 ci(testing): collapse stable and nightly into matrix job (Jose Celano) 51998dd fix(postgres): address Copilot PR review suggestions (Jose Celano) 40ed669 chore(issues): archive closed issue specs to docs/issues/closed (Jose Celano) 33e5820 ci(testing): collapse matrix jobs into test-nightly and test-stable (Jose Celano) 661bbd9 ci(os-compatibility): extract build matrix into dedicated workflow (Jose Celano) 87d458c docs(readme): add workflow badges for db-compatibility and db-benchmarking (Jose Celano) 8fb55e9 ci(db-benchmarking): add persistence benchmark smoke workflow (Jose Celano) 517b42e ci(db-compatibility): extract database compatibility workflow (Jose Celano) 3c9264c docs(issues): mark task 9 complete in 1723 spec (Jose Celano) 3ef0707 docs(containers): document PostgreSQL runtime configuration (Jose Celano) b0a654e chore(repo): remove legacy compose file references (Jose Celano) 248df3d ci(container): isolate compose build paths from storage (Jose Celano) aee2efb docs(tracker-core): add 2026-05-01 benchmark run with PostgreSQL baseline (Jose Celano) e0d0a87 fix(tracker-core): wait for single postgres ready log in benchmark runner (Jose Celano) 74f5c8a feat(ci): extend qBittorrent E2E runner with MySQL and PostgreSQL (Jose Celano) 54210f3 ci(testing): add postgres compatibility job (Jose Celano) 15af1e0 fix(tracker-core): correct postgres key timestamp column (Jose Celano) a0f9c00 feat(tracker-core): add PostgreSQL database driver (Jose Celano) cd665bf docs(issues): update 1723-1525-08 spec with user answers and implementation summary (Jose Celano) b06ee0f docs(issues): prefix 1525-08 spec with issue number (Jose Celano) Pull request description: # PostgreSQL Driver for Torrust Tracker Implements subissue 1525-08 of the persistence overhaul (#1525): add a PostgreSQL database driver to complement the existing SQLite3 and MySQL backends. Spec: [docs/issues/1723-1525-08-add-postgresql-driver.md](docs/issues/1723-1525-08-add-postgresql-driver.md) Closes #1723. ## Summary Adds full PostgreSQL support across the tracker's persistence layer: - Configuration package (new `Driver::PostgreSQL` variant) - Internal driver implementation with connection pooling and schema migrations - Automated schema migrations using `sqlx::migrate!()` - Driver tests with testcontainers - Container deployment configs and entry script support - E2E and benchmark runner integrations - CI compatibility matrix ## Tasks - [x] Task 1 — Add `Driver::PostgreSQL` to configuration package - [x] Task 2 — Add `Driver::PostgreSQL` variant to internal driver enum and factory - [x] Task 3 — Implement PostgreSQL driver (`packages/tracker-core/src/databases/driver/postgres/mod.rs`) - [x] Task 4 — Add PostgreSQL migration files - [x] Task 5 — Extend Cargo.toml with `postgres` feature and implement driver tests - [x] Task 6 — Extend persistence benchmark runner with PostgreSQL support - [x] Task 7 — Add `--db-driver` flag and PostgreSQL support to qBittorrent E2E runner - [x] Task 8 — Extend `.github/workflows/testing.yaml` with PostgreSQL compatibility matrix - [x] Task 9 — Add container configs, update entry script, and rename/add compose files ## Status - [x] Specification written and reviewed - [x] User answers recorded - [x] Implementation plan finalized - [x] Code readiness analysis complete - [x] Implementation in progress ACKs for top commit: josecelano: ACK 453dd48 Tree-SHA512: 3f51daee0e37ba0a6405c588209412a8cd376dbb362bc42b7a9961924d356f7440068efe992d48983359e4de52aa76742986e21a2f3bc2e12ef0bc687aaabd5e
2 parents 4cb8853 + 453dd48 commit b5051ef

58 files changed

Lines changed: 2475 additions & 352 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 40 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,36 @@
11
---
22
name: cleanup-completed-issues
3-
description: Guide for cleaning up completed and closed issues in the torrust-tracker project. Covers removing issue documentation files from docs/issues/ and committing the cleanup. Supports single issue cleanup or batch cleanup. Use when cleaning up closed issues, removing issue docs, or maintaining the docs/issues/ folder. Triggers on "cleanup issue", "remove issue", "clean completed issues", "delete closed issue", or "maintain issue docs".
3+
description: Guide for cleaning up completed and closed issues in the torrust-tracker project. Covers moving closed issue documentation files from docs/issues/ to docs/issues/closed/ and eventually deleting them. Supports single issue cleanup or batch cleanup. Use when cleaning up closed issues, archiving issue docs, or maintaining the docs/issues/ folder. Triggers on "cleanup issue", "archive issue", "move closed issue", "clean completed issues", "delete closed issue", or "maintain issue docs".
44
metadata:
55
author: torrust
6-
version: "1.0"
6+
version: "1.1"
77
---
88

99
# Cleaning Up Completed Issues
1010

11-
## When to Clean Up
11+
## Two-Stage Lifecycle
1212

13-
- **After PR merge**: Remove the issue file when its PR is merged
14-
- **Batch cleanup**: Periodically clean up multiple closed issues during maintenance
15-
- **Before releases**: Tidy documentation before major releases
13+
Closed issue specs are **not deleted immediately**. They go through a two-stage lifecycle:
1614

17-
## Cleanup Approaches
15+
1. **Stage 1 — Archive**: When an issue is closed, move its spec file from `docs/issues/` to
16+
`docs/issues/closed/`. The file stays here as a reference buffer while adjacent issues are
17+
still in progress.
18+
2. **Stage 2 — Delete**: Once the spec is no longer referenced by active work (typically after
19+
the next one or two related issues are also closed), delete it permanently.
1820

19-
### Option 1: Single Issue Cleanup (Recommended)
21+
See [`docs/issues/closed/README.md`](../../../../docs/issues/closed/README.md) for the purpose
22+
of the buffer folder.
2023

21-
1. Verify the issue is closed on GitHub
22-
2. Remove the issue file from `docs/issues/`
23-
3. Commit and push changes
24+
## When to Archive (Stage 1)
2425

25-
### Option 2: Batch Cleanup
26+
- **After PR merge**: Move the issue file when its PR is merged and the issue is closed.
27+
- **Batch archive**: Periodically move multiple closed issue files during maintenance.
28+
- **Before releases**: Tidy `docs/issues/` before major releases.
2629

27-
1. List all issue files in `docs/issues/`
28-
2. Check status of each issue on GitHub
29-
3. Remove all closed issue files
30-
4. Commit and push with a descriptive message
30+
## When to Delete (Stage 2)
31+
32+
- The spec is no longer referenced by any open issue or active work.
33+
- The related issue series has progressed far enough that the context is no longer needed.
3134

3235
## Step-by-Step Process
3336

@@ -36,7 +39,7 @@ metadata:
3639
**Single issue:**
3740

3841
```bash
39-
gh issue view {issue-number} --json state --jq .state
42+
gh issue view {issue-number} --repo torrust/torrust-tracker --json state --jq .state
4043
```
4144

4245
Expected: `CLOSED`
@@ -45,44 +48,46 @@ Expected: `CLOSED`
4548

4649
```bash
4750
for issue in 21 22 23 24; do
48-
state=$(gh issue view "$issue" --json state --jq .state 2>/dev/null || echo "NOT_FOUND")
49-
echo "$issue:$state"
51+
state=$(gh issue view "$issue" --repo torrust/torrust-tracker --json state --jq .state 2>/dev/null || echo "NOT_FOUND")
52+
echo "$issue: $state"
5053
done
5154
```
5255

53-
### Step 2: Remove Issue Documentation File
56+
### Step 2: Move Issue File to `docs/issues/closed/`
5457

5558
```bash
5659
# Single issue
57-
git rm docs/issues/42-add-peer-expiry-grace-period.md
60+
git mv docs/issues/42-add-peer-expiry-grace-period.md docs/issues/closed/
5861

5962
# Batch
60-
git rm docs/issues/21-some-old-issue.md \
61-
docs/issues/22-another-old-issue.md
63+
git mv docs/issues/21-some-old-issue.md \
64+
docs/issues/22-another-old-issue.md \
65+
docs/issues/closed/
6266
```
6367

6468
### Step 3: Commit and Push
6569

6670
```bash
6771
# Single issue
68-
git commit -S -m "chore(issues): remove closed issue #42 documentation"
72+
git commit -S -m "chore(issues): archive closed issue #42 spec to docs/issues/closed"
6973

7074
# Batch
71-
git commit -S -m "chore(issues): remove documentation for closed issues #21, #22, #23"
75+
git commit -S -m "chore(issues): archive closed issue specs #21, #22, #23 to docs/issues/closed"
7276

7377
git push {your-fork-remote} {branch}
7478
```
7579

76-
## Determining If an Issue File Should Stay
77-
78-
Keep issue files when:
80+
### Step 4 (Stage 2): Delete When No Longer Needed
7981

80-
- The issue is still open
81-
- The PR is open (still being worked on)
82-
- The specification is referenced from other active docs
82+
```bash
83+
git rm docs/issues/closed/42-add-peer-expiry-grace-period.md
84+
git commit -S -m "chore(issues): remove closed issue #42 spec (no longer referenced)"
85+
```
8386

84-
Remove issue files when:
87+
## Determining File Placement
8588

86-
- The issue is **closed**
87-
- The implementing PR is **merged**
88-
- The file is no longer referenced by active work
89+
| Condition | Action |
90+
| --------------------------------------- | ----------------------------- |
91+
| Issue still open | Keep in `docs/issues/` |
92+
| Issue closed, related work still active | Move to `docs/issues/closed/` |
93+
| Issue closed, no longer referenced | Delete permanently |

.github/workflows/container.yaml

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,32 @@ jobs:
5050

5151
- id: compose
5252
name: Compose
53-
run: docker compose build
53+
run: |
54+
QBT_E2E_WORKDIR="${RUNNER_TEMP}/qbt-e2e-compose-build"
55+
mkdir -p "${QBT_E2E_WORKDIR}/tracker-storage"
56+
mkdir -p "${QBT_E2E_WORKDIR}/seeder-config"
57+
mkdir -p "${QBT_E2E_WORKDIR}/seeder-downloads"
58+
mkdir -p "${QBT_E2E_WORKDIR}/leecher-config"
59+
mkdir -p "${QBT_E2E_WORKDIR}/leecher-downloads"
60+
mkdir -p "${QBT_E2E_WORKDIR}/shared"
61+
62+
export QBT_E2E_TRACKER_IMAGE=torrust-tracker:local
63+
export QBT_E2E_QBITTORRENT_IMAGE=ghcr.io/linuxserver/qbittorrent:latest
64+
export QBT_E2E_TRACKER_CONFIG_PATH=./share/default/config/tracker.container.sqlite3.toml
65+
export QBT_E2E_TRACKER_STORAGE_PATH="${QBT_E2E_WORKDIR}/tracker-storage"
66+
export QBT_E2E_TRACKER_HTTP_TRACKER_PORT=7070
67+
export QBT_E2E_TRACKER_UDP_PORT=6969
68+
export QBT_E2E_TRACKER_HTTP_API_PORT=1212
69+
export QBT_E2E_TRACKER_HEALTH_CHECK_API_PORT=1313
70+
export QBT_E2E_SEEDER_CONFIG_PATH="${QBT_E2E_WORKDIR}/seeder-config"
71+
export QBT_E2E_SEEDER_DOWNLOADS_PATH="${QBT_E2E_WORKDIR}/seeder-downloads"
72+
export QBT_E2E_LEECHER_CONFIG_PATH="${QBT_E2E_WORKDIR}/leecher-config"
73+
export QBT_E2E_LEECHER_DOWNLOADS_PATH="${QBT_E2E_WORKDIR}/leecher-downloads"
74+
export QBT_E2E_SHARED_PATH="${QBT_E2E_WORKDIR}/shared"
75+
76+
docker compose -f compose.qbittorrent-e2e.sqlite3.yaml build
77+
docker compose -f compose.qbittorrent-e2e.mysql.yaml build
78+
docker compose -f compose.qbittorrent-e2e.postgresql.yaml build
5479
5580
context:
5681
name: Context
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
name: Database Benchmarking
2+
3+
on:
4+
push:
5+
pull_request:
6+
7+
env:
8+
CARGO_TERM_COLOR: always
9+
10+
jobs:
11+
persistence-benchmark-sqlite3:
12+
name: Persistence Benchmark SQLite3
13+
runs-on: ubuntu-latest
14+
15+
steps:
16+
- id: checkout
17+
name: Checkout Repository
18+
uses: actions/checkout@v6
19+
20+
- id: setup
21+
name: Setup Toolchain
22+
uses: dtolnay/rust-toolchain@stable
23+
with:
24+
toolchain: stable
25+
26+
- id: cache
27+
name: Enable Job Cache
28+
uses: Swatinem/rust-cache@v2
29+
30+
- id: benchmark
31+
name: Run Persistence Benchmark (SQLite3)
32+
run: cargo run -p bittorrent-tracker-core --bin persistence_benchmark_runner -- --driver sqlite3 --ops 10
33+
34+
persistence-benchmark-mysql:
35+
name: Persistence Benchmark MySQL
36+
runs-on: ubuntu-latest
37+
38+
steps:
39+
- id: checkout
40+
name: Checkout Repository
41+
uses: actions/checkout@v6
42+
43+
- id: setup
44+
name: Setup Toolchain
45+
uses: dtolnay/rust-toolchain@stable
46+
with:
47+
toolchain: stable
48+
49+
- id: cache
50+
name: Enable Job Cache
51+
uses: Swatinem/rust-cache@v2
52+
53+
- id: benchmark
54+
name: Run Persistence Benchmark (MySQL)
55+
run: cargo run -p bittorrent-tracker-core --bin persistence_benchmark_runner -- --driver mysql --db-version 8.4 --ops 10
56+
57+
persistence-benchmark-postgresql:
58+
name: Persistence Benchmark PostgreSQL
59+
runs-on: ubuntu-latest
60+
61+
steps:
62+
- id: checkout
63+
name: Checkout Repository
64+
uses: actions/checkout@v6
65+
66+
- id: setup
67+
name: Setup Toolchain
68+
uses: dtolnay/rust-toolchain@stable
69+
with:
70+
toolchain: stable
71+
72+
- id: cache
73+
name: Enable Job Cache
74+
uses: Swatinem/rust-cache@v2
75+
76+
- id: benchmark
77+
name: Run Persistence Benchmark (PostgreSQL)
78+
run: cargo run -p bittorrent-tracker-core --bin persistence_benchmark_runner -- --driver postgresql --db-version 17 --ops 10
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
name: Database Compatibility
2+
3+
on:
4+
push:
5+
pull_request:
6+
7+
env:
8+
CARGO_TERM_COLOR: always
9+
10+
jobs:
11+
database-compatibility-mysql:
12+
name: Database Compatibility MySQL (${{ matrix.mysql-version }})
13+
runs-on: ubuntu-latest
14+
15+
strategy:
16+
matrix:
17+
mysql-version: ["8.0", "8.4"]
18+
19+
steps:
20+
- id: checkout
21+
name: Checkout Repository
22+
uses: actions/checkout@v6
23+
24+
- id: setup
25+
name: Setup Toolchain
26+
uses: dtolnay/rust-toolchain@stable
27+
with:
28+
toolchain: stable
29+
30+
- id: cache
31+
name: Enable Job Cache
32+
uses: Swatinem/rust-cache@v2
33+
34+
- id: database
35+
name: Run Database Compatibility Test
36+
env:
37+
TORRUST_TRACKER_CORE_RUN_MYSQL_DRIVER_TEST: "true"
38+
TORRUST_TRACKER_CORE_MYSQL_DRIVER_IMAGE_TAG: ${{ matrix.mysql-version }}
39+
run: cargo test -p bittorrent-tracker-core --features db-compatibility-tests run_mysql_driver_tests -- --nocapture
40+
41+
database-compatibility-postgres:
42+
name: Database Compatibility PostgreSQL (${{ matrix.postgres-version }})
43+
runs-on: ubuntu-latest
44+
45+
strategy:
46+
matrix:
47+
postgres-version: ["14", "15", "16", "17"]
48+
49+
steps:
50+
- id: checkout
51+
name: Checkout Repository
52+
uses: actions/checkout@v6
53+
54+
- id: setup
55+
name: Setup Toolchain
56+
uses: dtolnay/rust-toolchain@stable
57+
with:
58+
toolchain: stable
59+
60+
- id: cache
61+
name: Enable Job Cache
62+
uses: Swatinem/rust-cache@v2
63+
64+
- id: database
65+
name: Run Database Compatibility Test
66+
env:
67+
TORRUST_TRACKER_CORE_RUN_POSTGRES_DRIVER_TEST: "true"
68+
TORRUST_TRACKER_CORE_POSTGRES_DRIVER_IMAGE_TAG: ${{ matrix.postgres-version }}
69+
run: cargo test -p bittorrent-tracker-core --features db-compatibility-tests run_postgres_driver_tests -- --nocapture
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
name: OS Compatibility
2+
3+
on:
4+
push:
5+
pull_request:
6+
7+
env:
8+
CARGO_TERM_COLOR: always
9+
10+
jobs:
11+
build:
12+
name: Build on ${{ matrix.os }} (${{ matrix.toolchain }})
13+
runs-on: ${{ matrix.os }}
14+
15+
strategy:
16+
matrix:
17+
os: [ubuntu-latest, macos-latest, windows-latest]
18+
toolchain: [nightly, stable]
19+
20+
steps:
21+
- name: Checkout code
22+
uses: actions/checkout@v6
23+
24+
- id: setup
25+
name: Setup Toolchain
26+
uses: dtolnay/rust-toolchain@stable
27+
with:
28+
toolchain: ${{ matrix.toolchain }}
29+
30+
- name: Build project
31+
run: cargo build --verbose

0 commit comments

Comments
 (0)