Repository: gofiber/storage
Pull request #1515: chore: adopt testcontainers-go for Postgres, MySQL and MongoDB
Author: login: mdelapenya
Labels: name: ✏️ Feature
Created: 2024-08-29T12:47:23Z | Merged: 2025-03-19T07:01:09Z

## What does this PR do?

It uses testcontainers-go in the integration tests for the given stores, refactoring the tests to always consume a new test store, backed by a Docker container.

This PR also bumps testcontainers-go from v0.33.0 to v0.35.0

## Why is it important?
Reproducibility: any developer will be able to run the tests locally exactly equals as in the Github Actions.

## Related issues
For reference, please check out previous work for Couchbase and Minio (#1508) and ClickHouse (#1506)

There is more ongoing work, as defined in #1507

## Other concerns

I started updating MSSQL module, but the container's pid 1 crashes, so I'm going to postpone its addition, using a separate PR for that.

<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit

- **Tests**
  - Enhanced containerized testing across storage modules to ensure each test runs in a fresh, isolated instance.
  - Improved resource cleanup and wait strategies, leading to more robust and reliable test executions.
  - Updated underlying service configurations and images to boost overall stability during testing.
  - Introduced new test functions and constants for better clarity and resource management.
  - Streamlined error handling and resource management in test cases for improved maintainability.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->


Diff:
diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml
index 99aef2f84..91b438a16 100644
--- a/.github/workflows/benchmark.yml
+++ b/.github/workflows/benchmark.yml
@@ -81,46 +81,6 @@ jobs:
         run: |
           docker run -d -p 11211:11211 memcached:latest
 
-      - name: Install MongoDB
-        if: ${{ matrix.package == 'mongodb' }}
-        run: |
-          docker run -d -p 27017:27017 mongo:latest
-
-      - name: Install MSSQL
-        if: ${{ matrix.package == 'mssql' }}
-        run: |
-          docker run -d -p 1433:1433 \
-            -e "ACCEPT_EULA=Y" -e "SA_PASSWORD=MsSql!1234" \
-            -e "MSSQL_DB=master" -e "MSSQL_USER=sa" \
-            -e "MSSQL_PASSWORD=MsSql!1234" \
-            --health-cmd "/opt/mssql-tools/bin/sqlcmd -U sa -P $SA_PASSWORD -Q 'select 1' -b -o /dev/null" \
-            --health-interval 1s \
-            --health-timeout 30s \
-            --health-start-period 10s \
-            --health-retries 20 \
-            mcmoe/mssqldocker:latest
-
-      - name: Install MySQL
-        if: ${{ matrix.package == 'mysql' }}
-        run: |
-          docker run -d -p 3306:3306 \
-            -e "MYSQL_DATABASE=fiber" \
-            -e "MYSQL_USER=username" \
-            -e "MYSQL_PASSWORD=password" \
-            -e "MYSQL_ROOT_PASSWORD=password" \
-            --health-cmd "mysqladmin ping" --health-interval 10s --health-timeout 5s --health-retries 5 \
-            mysql:latest
-
-      - name: Install Postgres
-        if: ${{ matrix.package == 'postgres' }}
-        run: |
-          docker run -d -p 5432:5432 \
-            -e "POSTGRES_DB=fiber" \
-            -e "POSTGRES_USER=username" \
-            -e "POSTGRES_PASSWORD=pass#w%rd" \
-            --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5 \
-            postgres:latest
-
       - name: Install Azurite
         if: ${{ matrix.package == 'azureblob' }}
         run: |
@@ -179,21 +139,18 @@ jobs:
         run: |
           set -o pipefail
           echo "Bench dir: ${{ matrix.package }}"
-          go test ./... -benchmem -run=^$ -bench . | tee -a output.txt
+          go test ./... -timeout 900s -benchmem -run=^$ -bench . | tee -a output.txt
         shell: bash
         env:
           MSSQL_DATABASE: master
           MSSQL_USERNAME: sa
           MSSQL_PASSWORD: MsSql!1234
-          MYSQL_USERNAME: username
-          MYSQL_PASSWORD: password
-          MYSQL_DATABASE: fiber
-          POSTGRES_DATABASE: fiber
-          POSTGRES_USERNAME: username
-          POSTGRES_PASSWORD: "pass#w%rd"
           TEST_CLICKHOUSE_IMAGE: "clickhouse/clickhouse-server:23-alpine"
-          TEST_COUCHBASE_IMAGE: "couchbase:enterprise-7.1.1"
+          TEST_COUCHBASE_IMAGE: "couchbase:enterprise-7.6.5"
           TEST_MINIO_IMAGE: "docker.io/minio/minio:RELEASE.2024-08-17T01-24-54Z"
+          TEST_MONGODB_IMAGE: "docker.io/mongo:7"
+          TEST_MYSQL_IMAGE: "docker.io/mysql:9"
+          TEST_POSTGRES_IMAGE: "docker.io/postgres:16-alpine"
 
       - name: Get Previous Benchmark Results
         uses: actions/cache@v4
diff --git a/.github/workflows/test-clickhouse.yml b/.github/workflows/test-clickhouse.yml
index 928297231..24804ef00 100644
--- a/.github/workflows/test-clickhouse.yml
+++ b/.github/workflows/test-clickhouse.yml
@@ -15,8 +15,9 @@ jobs:
     strategy:
       matrix:
         go-version:
-          - 1.21.x
           - 1.22.x
+          - 1.23.x
+          - 1.24.x
     steps:
       - name: Fetch Repository
         uses: actions/checkout@v4
diff --git a/.github/workflows/test-couchbase.yml b/.github/workflows/test-couchbase.yml
index e400ec2f2..04c8f18d1 100644
--- a/.github/workflows/test-couchbase.yml
+++ b/.github/workflows/test-couchbase.yml
@@ -15,9 +15,9 @@ jobs:
     strategy:
       matrix:
         go-version:
-          - 1.21.x
           - 1.22.x
           - 1.23.x
+          - 1.24.x
     steps:
       - name: Fetch Repository
         uses: actions/checkout@v4
@@ -27,5 +27,5 @@ jobs:
             go-version: '${{ matrix.go-version }}'
       -   name: Run Test
           env:
-            TEST_COUCHBASE_IMAGE: couchbase:enterprise-7.1.1
+            TEST_COUCHBASE_IMAGE: couchbase:enterprise-7.6.5
           run: cd ./couchbase && go test ./... -v -race
diff --git a/.github/workflows/test-minio.yml b/.github/workflows/test-minio.yml
index 99cf6afb8..2e5380ef0 100644
--- a/.github/workflows/test-minio.yml
+++ b/.github/workflows/test-minio.yml
@@ -15,9 +15,9 @@ jobs:
         strategy:
             matrix:
                 go-version:
-                    - 1.21.x
                     - 1.22.x
                     - 1.23.x
+                    - 1.24.x
         steps:
             -   name: Fetch Repository
                 uses: actions/checkout@v4
diff --git a/.github/workflows/test-mongodb.yml b/.github/workflows/test-mongodb.yml
index 13eacbd96..77120f8f9 100644
--- a/.github/workflows/test-mongodb.yml
+++ b/.github/workflows/test-mongodb.yml
@@ -12,17 +12,12 @@ name: "Tests Mongodb"
 jobs:
     Tests:
         runs-on: ubuntu-latest
-        services:
-            mongo:
-                image: 'mongo:latest'
-                ports:
-                    - '27017:27017'
         strategy:
             matrix:
                 go-version:
-                    - 1.19.x
-                    - 1.20.x
-                    - 1.21.x
+                    - 1.22.x
+                    - 1.23.x
+                    - 1.24.x
         steps:
             -   name: Fetch Repository
                 uses: actions/checkout@v4
@@ -31,5 +26,7 @@ jobs:
                 with:
                     go-version: '${{ matrix.go-version }}'
             -   name: Run Test
+                env:
+                    TEST_MONGODB_IMAGE: docker.io/mongo:7
                 run: cd ./mongodb && go test ./... -v -race
 
diff --git a/.github/workflows/test-mysql.yml b/.github/workflows/test-mysql.yml
index a2c94202b..21b853889 100644
--- a/.github/workflows/test-mysql.yml
+++ b/.github/workflows/test-mysql.yml
@@ -12,25 +12,12 @@ name: "Tests MySQL"
 jobs:
     Tests:
         runs-on: ubuntu-latest
-        services:
-            mysql:
-                image: 'mysql:latest'
-                env:
-                    MYSQL_DATABASE: fiber
-                    MYSQL_USER: username
-                    MYSQL_PASSWORD: password
-                    MYSQL_ROOT_PASSWORD: password
-                ports:
-                    - '3306:3306'
-                options: >-
-                    --health-cmd "mysqladmin ping" --health-interval 10s --health-timeout
-                    5s --health-retries 5
         strategy:
             matrix:
                 go-version:
-                    - 1.19.x
-                    - 1.20.x
-                    - 1.21.x
+                    - 1.22.x
+                    - 1.23.x
+                    - 1.24.x
         steps:
             -   name: Fetch Repository
                 uses: actions/checkout@v4
@@ -39,8 +26,6 @@ jobs:
                 with:
                     go-version: '${{ matrix.go-version }}'
             -   name: Run Test
-                run: cd ./mysql && go test ./... -v -race
                 env:
-                    MYSQL_USERNAME: username
-                    MYSQL_PASSWORD: password
-                    MYSQL_DATABASE: fiber
+                    TEST_MYSQL_IMAGE: docker.io/mysql:9
+                run: cd ./mysql && go test ./... -v -race
diff --git a/.github/workflows/test-postgres.yml b/.github/workflows/test-postgres.yml
index a91a300e7..262cf73c7 100644
--- a/.github/workflows/test-postgres.yml
+++ b/.github/workflows/test-postgres.yml
@@ -12,24 +12,12 @@ name: "Tests Postgres"
 jobs:
     Tests:
         runs-on: ubuntu-latest
-        services:
-            postgres:
-                image: 'postgres:latest'
-                ports:
-                    - '5432:5432'
-                env:
-                    POSTGRES_DB: fiber
-                    POSTGRES_USER: username
-                    POSTGRES_PASSWORD: "pass#w%rd"
-                options: >-
-                    --health-cmd pg_isready --health-interval 10s --health-timeout 5s
-                    --health-retries 5
         strategy:
             matrix:
                 go-version:
-                    - 1.20.x
-                    - 1.21.x
                     - 1.22.x
+                    - 1.23.x
+                    - 1.24.x
         steps:
             -   name: Fetch Repository
                 uses: actions/checkout@v4
@@ -38,8 +26,6 @@ jobs:
                 with:
                     go-version: '${{ matrix.go-version }}'
             -   name: Run Test
-                run: cd ./postgres && go test ./... -v -race
                 env:
-                    POSTGRES_DATABASE: fiber
-                    POSTGRES_USERNAME: username
-                    POSTGRES_PASSWORD: "pass#w%rd"
+                    TEST_POSTGRES_IMAGE: "docker.io/postgres:16-alpine"
+                run: cd ./postgres && go test ./... -v -race
diff --git a/clickhouse/clickhouse_test.go b/clickhouse/clickhouse_test.go
index d9e099035..e66b75456 100644
--- a/clickhouse/clickhouse_test.go
+++ b/clickhouse/clickhouse_test.go
@@ -11,7 +11,9 @@ import (
 	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/require"
 
+	"github.com/testcontainers/testcontainers-go"
 	"github.com/testcontainers/testcontainers-go/modules/clickhouse"
+	"github.com/testcontainers/testcontainers-go/wait"
 )
 
 const (
@@ -21,6 +23,8 @@ const (
 	clickhouseUser        string = "default"
 	clickhousePass        string = "password"
 	clickhouseDB          string = "fiber"
+	clickhouseHttpPort           = "8123/tcp"
+	clickhouseSuccessCode        = 200
 )
 
 func getTestConnection(t testing.TB, cfg Config) (*Storage, error) {
@@ -38,7 +42,16 @@ func getTestConnection(t testing.TB, cfg Config) (*Storage, error) {
 		clickhouse.WithUsername(clickhouseUser),
 		clickhouse.WithPassword(clickhousePass),
 		clickhouse.WithDatabase(clickhouseDB),
+		testcontainers.WithWaitStrategy(
+			wait.ForAll(
+				wait.ForListeningPort(clickhouseHttpPort),
+				wait.NewHTTPStrategy("/").WithPort(clickhouseHttpPort).WithStatusCodeMatcher(func(status int) bool {
+					return status == clickhouseSuccessCode
+				}),
+			),
+		),
 	)
+	testcontainers.CleanupContainer(t, c)
 	if err != nil {
 		return nil, err
 	}
@@ -67,13 +80,14 @@ func getTestConnection(t testing.TB, cfg Config) (*Storage, error) {
 }
 
 func Test_Connection(t *testing.T) {
-	_, err := getTestConnection(t, Config{
+	client, err := getTestConnection(t, Config{
 		Engine: Memory,
 		Table:  "test_table",
 		Clean:  true,
 	})
-
 	require.NoError(t, err)
+
+	defer client.Close()
 }
 
 func Test_Set(t *testing.T) {
@@ -191,6 +205,17 @@ func Test_Reset(t *testing.T) {
 	assert.Equal(t, []byte{}, value)
 }
 
+func TestClose_ShouldReturn_NoError(t *testing.T) {
+	client, err := getTestConnection(t, Config{
+		Engine: Memory,
+		Table:  "test_table",
+		Clean:  true,
+	})
+	require.NoError(t, err)
+
+	require.NoError(t, client.Close())
+}
+
 func Benchmark_Clickhouse_Set(b *testing.B) {
 	b.ReportAllocs()
 	b.ResetTimer()
diff --git a/clickhouse/go.mod b/clickhouse/go.mod
index 3953db629..32a587f4d 100644
--- a/clickhouse/go.mod
+++ b/clickhouse/go.mod
@@ -1,11 +1,12 @@
 module github.com/gofiber/storage/clickhouse
 
-go 1.21
+go 1.22
 
 require (
 	github.com/ClickHouse/clickhouse-go/v2 v2.26.0
 	github.com/stretchr/testify v1.9.0
-	github.com/testcontainers/testcontainers-go/modules/clickhouse v0.33.0
+	github.com/testcontainers/testcontainers-go v0.35.0
+	github.com/testcontainers/testcontainers-go/modules/clickhouse v0.35.0
 )
 
 require (
@@ -18,7 +19,7 @@ require (
 	github.com/containerd/containerd v1.7.18 // indirect
 	github.com/containerd/log v0.1.0 // indirect
 	github.com/containerd/platforms v0.2.1 // indirect
-	github.com/cpuguy83/dockercfg v0.3.1 // indirect
+	github.com/cpuguy83/dockercfg v0.3.2 // indirect
 	github.com/davecgh/go-spew v1.1.1 // indirect
 	github.com/distribution/reference v0.6.0 // indirect
 	github.com/docker/docker v27.1.1+incompatible // indirect
@@ -53,7 +54,6 @@ require (
 	github.com/shoenig/go-m1cpu v0.1.6 // indirect
 	github.com/shopspring/decimal v1.4.0 // indirect
 	github.com/sirupsen/logrus v1.9.3 // indirect
-	github.com/testcontainers/testcontainers-go v0.33.0 // indirect
 	github.com/tklauser/go-sysconf v0.3.12 // indirect
 	github.com/tklauser/numcpus v0.6.1 // indirect
 	github.com/yusufpapurcu/wmi v1.2.3 // indirect
@@ -61,7 +61,7 @@ require (
 	go.opentelemetry.io/otel v1.28.0 // indirect
 	go.opentelemetry.io/otel/metric v1.28.0 // indirect
 	go.opentelemetry.io/otel/trace v1.28.0 // indirect
-	golang.org/x/crypto v0.24.0 // indirect
-	golang.org/x/sys v0.21.0 // indirect
+	golang.org/x/crypto v0.31.0 // indirect
+	golang.org/x/sys v0.28.0 // indirect
 	gopkg.in/yaml.v3 v3.0.1 // indirect
 )
diff --git a/clickhouse/go.sum b/clickhouse/go.sum
index a56dfad50..bc1130867 100644
--- a/clickhouse/go.sum
+++ b/clickhouse/go.sum
@@ -20,8 +20,8 @@ github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I=
 github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo=
 github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A=
 github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw=
-github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E=
-github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc=
+github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA=
+github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc=
 github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY=
 github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -122,6 +122,8 @@ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVs
 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
 github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
+github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
+github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
 github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
@@ -129,10 +131,10 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO
 github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
 github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
 github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
-github.com/testcontainers/testcontainers-go v0.33.0 h1:zJS9PfXYT5O0ZFXM2xxXfk4J5UMw/kRiISng037Gxdw=
-github.com/testcontainers/testcontainers-go v0.33.0/go.mod h1:W80YpTa8D5C3Yy16icheD01UTDu+LmXIA2Keo+jWtT8=
-github.com/testcontainers/testcontainers-go/modules/clickhouse v0.33.0 h1:YbB5DBkpgY+GlGPFqTSV1hzWPm3ZHirEyooZrj+ZXK0=
-github.com/testcontainers/testcontainers-go/modules/clickhouse v0.33.0/go.mod h1:qJuMPl9yWIWasmdBILM2uDk1Ny1kdeigcKMJ6A8PZz0=
+github.com/testcontainers/testcontainers-go v0.35.0 h1:uADsZpTKFAtp8SLK+hMwSaa+X+JiERHtd4sQAFmXeMo=
+github.com/testcontainers/testcontainers-go v0.35.0/go.mod h1:oEVBj5zrfJTrgjwONs1SsRbnBtH9OKl+IGl3UMcr2B4=
+github.com/testcontainers/testcontainers-go/modules/clickhouse v0.35.0 h1:A4NESGwof4RK+i/pjL0lAVu0JxNZIvLR35ZFB9DKgYQ=
+github.com/testcontainers/testcontainers-go/modules/clickhouse v0.35.0/go.mod h1:nT0LQ4rqTljX5Ub0Q3GdFrVXRYSrjK6p7RuJPpUE4wg=
 github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
 github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU=
 github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI=
@@ -167,8 +169,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
 golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
-golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI=
-golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM=
+golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
+golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
 golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
@@ -195,17 +197,17 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc
 golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
-golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws=
-golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
+golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
-golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA=
-golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0=
+golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q=
+golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
-golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
-golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
+golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
+golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
 golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44=
 golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
diff --git a/couchbase/couchbase_test.go b/couchbase/couchbase_test.go
index f22b71ab6..2e334daa2 100644
--- a/couchbase/couchbase_test.go
+++ b/couchbase/couchbase_test.go
@@ -7,12 +7,14 @@ import (
 	"time"
 
 	"github.com/stretchr/testify/require"
+	"github.com/testcontainers/testcontainers-go"
 	"github.com/testcontainers/testcontainers-go/modules/couchbase"
+	"github.com/testcontainers/testcontainers-go/wait"
 )
 
 const (
 	// couchbaseImage is the default image used for running couchbase in tests.
-	couchbaseImage              = "couchbase:enterprise-7.1.1"
+	couchbaseImage              = "couchbase:enterprise-7.6.5"
 	couchbaseImageEnvVar string = "TEST_COUCHBASE_IMAGE"
 	couchbaseUser        string = "default"
 	couchbasePass        string = "password"
@@ -35,7 +37,9 @@ func newTestStore(t testing.TB) (*Storage, error) {
 		img,
 		couchbase.WithAdminCredentials(couchbaseUser, couchbasePass),
 		couchbase.WithBuckets(bucket),
+		testcontainers.WithWaitStrategy(wait.ForListeningPort("8091/tcp")),
 	)
+	testcontainers.CleanupContainer(t, c)
 	if err != nil {
 		return nil, err
 	}
@@ -56,6 +60,7 @@ func newTestStore(t testing.TB) (*Storage, error) {
 func TestSetCouchbase_ShouldReturnNoError(t *testing.T) {
 	testStore, err := newTestStore(t)
 	require.NoError(t, err)
+	defer testStore.Close()
 
 	err = testStore.Set("test", []byte("test"), 0)
 
@@ -65,6 +70,7 @@ func TestSetCouchbase_ShouldReturnNoError(t *testing.T) {
 func TestGetCouchbase_ShouldReturnNil_WhenDocumentNotFound(t *testing.T) {
 	testStore, err := newTestStore(t)
 	require.NoError(t, err)
+	defer testStore.Close()
 
 	val, err := testStore.Get("not_found_key")
 
@@ -75,6 +81,7 @@ func TestGetCouchbase_ShouldReturnNil_WhenDocumentNotFound(t *testing.T) {
 func TestSetAndGet_GetShouldReturn_SetValueWithoutError(t *testing.T) {
 	testStore, err := newTestStore(t)
 	require.NoError(t, err)
+	defer testStore.Close()
 
 	err = testStore.Set("test", []byte("fiber_test_value"), 0)
 	require.NoError(t, err)
@@ -88,6 +95,7 @@ func TestSetAndGet_GetShouldReturn_SetValueWithoutError(t *testing.T) {
 func TestSetAndGet_GetShouldReturnNil_WhenTTLExpired(t *testing.T) {
 	testStore, err := newTestStore(t)
 	require.NoError(t, err)
+	defer testStore.Close()
 
 	err = testStore.Set("test", []byte("fiber_test_value"), 3*time.Second)
 	require.NoError(t, err)
@@ -103,6 +111,7 @@ func TestSetAndGet_GetShouldReturnNil_WhenTTLExpired(t *testing.T) {
 func TestSetAndDelete_DeleteShouldReturn_NoError(t *testing.T) {
 	testStore, err := newTestStore(t)
 	require.NoError(t, err)
+	defer testStore.Close()
 
 	err = testStore.Set("test", []byte("fiber_test_value"), 0)
 	require.NoError(t, err)
@@ -117,6 +126,7 @@ func TestSetAndDelete_DeleteShouldReturn_NoError(t *testing.T) {
 func TestSetAndReset_ResetShouldReturn_NoError(t *testing.T) {
 	testStore, err := newTestStore(t)
 	require.NoError(t, err)
+	defer testStore.Close()
 
 	err = testStore.Set("test", []byte("fiber_test_value"), 0)
 	require.NoError(t, err)
@@ -132,13 +142,13 @@ func TestClose_CloseShouldReturn_NoError(t *testing.T) {
 	testStore, err := newTestStore(t)
 	require.NoError(t, err)
 
-	err = testStore.Close()
-	require.NoError(t, err)
+	require.NoError(t, testStore.Close())
 }
 
 func TestGetConn_ReturnsNotNil(t *testing.T) {
 	testStore, err := newTestStore(t)
 	require.NoError(t, err)
+	defer testStore.Close()
 
 	require.True(t, testStore.Conn() != nil)
 }
@@ -146,6 +156,7 @@ func TestGetConn_ReturnsNotNil(t *testing.T) {
 func Benchmark_Couchbase_Set(b *testing.B) {
 	testStore, err := newTestStore(b)
 	require.NoError(b, err)
+	defer testStore.Close()
 
 	b.ReportAllocs()
 	b.ResetTimer()
@@ -160,6 +171,7 @@ func Benchmark_Couchbase_Set(b *testing.B) {
 func Benchmark_Couchbase_Get(b *testing.B) {
 	testStore, err := newTestStore(b)
 	require.NoError(b, err)
+	defer testStore.Close()
 
 	err = testStore.Set("john", []byte("doe"), 0)
 	require.NoError(b, err)
@@ -177,6 +189,7 @@ func Benchmark_Couchbase_Get(b *testing.B) {
 func Benchmark_Couchbase_SetAndDelete(b *testing.B) {
 	testStore, err := newTestStore(b)
 	require.NoError(b, err)
+	defer testStore.Close()
 
 	b.ReportAllocs()
 	b.ResetTimer()
diff --git a/couchbase/go.mod b/couchbase/go.mod
index 86b6507f8..57312413c 100644
--- a/couchbase/go.mod
+++ b/couchbase/go.mod
@@ -1,11 +1,12 @@
 module github.com/gofiber/storage/couchbase/v2
 
-go 1.21
+go 1.22
 
 require (
 	github.com/couchbase/gocb/v2 v2.9.1
 	github.com/stretchr/testify v1.9.0
-	github.com/testcontainers/testcontainers-go/modules/couchbase v0.33.0
+	github.com/testcontainers/testcontainers-go v0.35.0
+	github.com/testcontainers/testcontainers-go/modules/couchbase v0.35.0
 )
 
 require (
@@ -20,7 +21,7 @@ require (
 	github.com/couchbase/gocbcoreps v0.1.3 // indirect
 	github.com/couchbase/goprotostellar v1.0.2 // indirect
 	github.com/couchbaselabs/gocbconnstr/v2 v2.0.0-20240607131231-fb385523de28 // indirect
-	github.com/cpuguy83/dockercfg v0.3.1 // indirect
+	github.com/cpuguy83/dockercfg v0.3.2 // indirect
 	github.com/davecgh/go-spew v1.1.1 // indirect
 	github.com/distribution/reference v0.6.0 // indirect
 	github.com/docker/docker v27.1.1+incompatible // indirect
@@ -51,7 +52,6 @@ require (
 	github.com/shirou/gopsutil/v3 v3.23.12 // indirect
 	github.com/shoenig/go-m1cpu v0.1.6 // indirect
 	github.com/sirupsen/logrus v1.9.3 // indirect
-	github.com/testcontainers/testcontainers-go v0.33.0 // indirect
 	github.com/tidwall/gjson v1.17.1 // indirect
 	github.com/tidwall/match v1.1.1 // indirect
 	github.com/tidwall/pretty v1.2.0 // indirect
@@ -65,10 +65,10 @@ require (
 	go.opentelemetry.io/otel/trace v1.24.0 // indirect
 	go.uber.org/multierr v1.11.0 // indirect
 	go.uber.org/zap v1.27.0 // indirect
-	golang.org/x/crypto v0.24.0 // indirect
+	golang.org/x/crypto v0.31.0 // indirect
 	golang.org/x/net v0.26.0 // indirect
-	golang.org/x/sys v0.21.0 // indirect
-	golang.org/x/text v0.16.0 // indirect
+	golang.org/x/sys v0.28.0 // indirect
+	golang.org/x/text v0.21.0 // indirect
 	google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda // indirect
 	google.golang.org/grpc v1.64.1 // indirect
 	google.golang.org/protobuf v1.33.0 // indirect
diff --git a/couchbase/go.sum b/couchbase/go.sum
index 48f765764..bd4edae98 100644
--- a/couchbase/go.sum
+++ b/couchbase/go.sum
@@ -32,8 +32,8 @@ github.com/couchbaselabs/gocaves/client v0.0.0-20230404095311-05e3ba4f0259 h1:2T
 github.com/couchbaselabs/gocaves/client v0.0.0-20230404095311-05e3ba4f0259/go.mod h1:AVekAZwIY2stsJOMWLAS/0uA/+qdp7pjO8EHnl61QkY=
 github.com/couchbaselabs/gocbconnstr/v2 v2.0.0-20240607131231-fb385523de28 h1:lhGOw8rNG6RAadmmaJAF3PJ7MNt7rFuWG7BHCYMgnGE=
 github.com/couchbaselabs/gocbconnstr/v2 v2.0.0-20240607131231-fb385523de28/go.mod h1:o7T431UOfFVHDNvMBUmUxpHnhivwv7BziUao/nMl81E=
-github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E=
-github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc=
+github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA=
+github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc=
 github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY=
 github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -151,10 +151,10 @@ github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o
 github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
 github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
 github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
-github.com/testcontainers/testcontainers-go v0.33.0 h1:zJS9PfXYT5O0ZFXM2xxXfk4J5UMw/kRiISng037Gxdw=
-github.com/testcontainers/testcontainers-go v0.33.0/go.mod h1:W80YpTa8D5C3Yy16icheD01UTDu+LmXIA2Keo+jWtT8=
-github.com/testcontainers/testcontainers-go/modules/couchbase v0.33.0 h1:WiM9d0cIXwa85dL4JQ0/W1sF1WOlLCkDNALizW1kja4=
-github.com/testcontainers/testcontainers-go/modules/couchbase v0.33.0/go.mod h1:nLkg/zLCyv+/YbGdhia6naik/deLBXgxkB+lkOeb/ro=
+github.com/testcontainers/testcontainers-go v0.35.0 h1:uADsZpTKFAtp8SLK+hMwSaa+X+JiERHtd4sQAFmXeMo=
+github.com/testcontainers/testcontainers-go v0.35.0/go.mod h1:oEVBj5zrfJTrgjwONs1SsRbnBtH9OKl+IGl3UMcr2B4=
+github.com/testcontainers/testcontainers-go/modules/couchbase v0.35.0 h1:RPUOLFlhp4QuJwJ/HGkOjr/cwyj5IDlbf9yy8ZKer7Q=
+github.com/testcontainers/testcontainers-go/modules/couchbase v0.35.0/go.mod h1:F2LaVjDmcSSsUr4+1LbbTGI/ApBWPjfx2DjfC1U1Dho=
 github.com/tidwall/gjson v1.17.1 h1:wlYEnwqAHgzmhNUFfw7Xalt2JzQvsMx2Se4PcoFCT/U=
 github.com/tidwall/gjson v1.17.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
 github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
@@ -200,8 +200,8 @@ go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
-golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI=
-golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM=
+golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
+golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
 golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
 golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
@@ -238,14 +238,14 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc
 golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
-golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws=
-golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
-golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA=
-golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0=
+golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
+golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q=
+golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
-golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
+golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
+golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
 golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44=
 golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
diff --git a/minio/go.mod b/minio/go.mod
index 6bba0027e..2e5a7452a 100644
--- a/minio/go.mod
+++ b/minio/go.mod
@@ -1,11 +1,12 @@
 module github.com/gofiber/storage/minio
 
-go 1.21
+go 1.22
 
 require (
 	github.com/minio/minio-go/v7 v7.0.76
 	github.com/stretchr/testify v1.9.0
-	github.com/testcontainers/testcontainers-go/modules/minio v0.33.0
+	github.com/testcontainers/testcontainers-go v0.35.0
+	github.com/testcontainers/testcontainers-go/modules/minio v0.35.0
 	github.com/valyala/bytebufferpool v1.0.0
 )
 
@@ -17,7 +18,7 @@ require (
 	github.com/containerd/containerd v1.7.18 // indirect
 	github.com/containerd/log v0.1.0 // indirect
 	github.com/containerd/platforms v0.2.1 // indirect
-	github.com/cpuguy83/dockercfg v0.3.1 // indirect
+	github.com/cpuguy83/dockercfg v0.3.2 // indirect
 	github.com/davecgh/go-spew v1.1.1 // indirect
 	github.com/distribution/reference v0.6.0 // indirect
 	github.com/docker/docker v27.1.1+incompatible // indirect
@@ -34,7 +35,6 @@ require (
 	github.com/google/uuid v1.6.0 // indirect
 	github.com/klauspost/compress v1.17.9 // indirect
 	github.com/klauspost/cpuid/v2 v2.2.8 // indirect
-	github.com/kr/text v0.2.0 // indirect
 	github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
 	github.com/magiconair/properties v1.8.7 // indirect
 	github.com/minio/md5-simd v1.1.2 // indirect
@@ -53,7 +53,6 @@ require (
 	github.com/shirou/gopsutil/v3 v3.23.12 // indirect
 	github.com/shoenig/go-m1cpu v0.1.6 // indirect
 	github.com/sirupsen/logrus v1.9.3 // indirect
-	github.com/testcontainers/testcontainers-go v0.33.0 // indirect
 	github.com/tklauser/go-sysconf v0.3.12 // indirect
 	github.com/tklauser/numcpus v0.6.1 // indirect
 	github.com/yusufpapurcu/wmi v1.2.3 // indirect
@@ -61,9 +60,9 @@ require (
 	go.opentelemetry.io/otel v1.24.0 // indirect
 	go.opentelemetry.io/otel/metric v1.24.0 // indirect
 	go.opentelemetry.io/otel/trace v1.24.0 // indirect
-	golang.org/x/crypto v0.26.0 // indirect
+	golang.org/x/crypto v0.31.0 // indirect
 	golang.org/x/net v0.28.0 // indirect
-	golang.org/x/sys v0.24.0 // indirect
-	golang.org/x/text v0.17.0 // indirect
+	golang.org/x/sys v0.28.0 // indirect
+	golang.org/x/text v0.21.0 // indirect
 	gopkg.in/yaml.v3 v3.0.1 // indirect
 )
diff --git a/minio/go.sum b/minio/go.sum
index 6e3f253b5..f63617c29 100644
--- a/minio/go.sum
+++ b/minio/go.sum
@@ -14,9 +14,8 @@ github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I=
 github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo=
 github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A=
 github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw=
-github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E=
-github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc=
-github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
+github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA=
+github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc=
 github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY=
 github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -111,16 +110,18 @@ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVs
 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
 github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
+github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
+github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
 github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
 github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
 github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
 github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
-github.com/testcontainers/testcontainers-go v0.33.0 h1:zJS9PfXYT5O0ZFXM2xxXfk4J5UMw/kRiISng037Gxdw=
-github.com/testcontainers/testcontainers-go v0.33.0/go.mod h1:W80YpTa8D5C3Yy16icheD01UTDu+LmXIA2Keo+jWtT8=
-github.com/testcontainers/testcontainers-go/modules/minio v0.33.0 h1:lHhjYlm0Oh+PfM03NIwCqNg2zSz9VuNTwUKi4MQfYAA=
-github.com/testcontainers/testcontainers-go/modules/minio v0.33.0/go.mod h1:3WRFF6lLI3IqXb7lvOx6OpEcH1jgs59mbzZiPTJeEJg=
+github.com/testcontainers/testcontainers-go v0.35.0 h1:uADsZpTKFAtp8SLK+hMwSaa+X+JiERHtd4sQAFmXeMo=
+github.com/testcontainers/testcontainers-go v0.35.0/go.mod h1:oEVBj5zrfJTrgjwONs1SsRbnBtH9OKl+IGl3UMcr2B4=
+github.com/testcontainers/testcontainers-go/modules/minio v0.35.0 h1:oJMrfB0hIABClRsJrVJ43zTEsCVk0JTN7RdTz9r+tk4=
+github.com/testcontainers/testcontainers-go/modules/minio v0.35.0/go.mod h1:Q7gSllC2zi78e2OF6Gwn+DXyqbxdbt6PAuaZdIPh3DQ=
 github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU=
 github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI=
 github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk=
@@ -150,8 +151,8 @@ go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v8
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
-golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw=
-golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54=
+golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
+golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
 golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
@@ -174,14 +175,14 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
-golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg=
-golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
-golang.org/x/term v0.23.0 h1:F6D4vR+EHoL9/sWAWgAR1H2DcHr4PareCbAaCo1RpuU=
-golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk=
+golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
+golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q=
+golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc=
-golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
+golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
+golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
 golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44=
 golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
diff --git a/minio/minio_test.go b/minio/minio_test.go
index c26616471..c2fdc3aec 100644
--- a/minio/minio_test.go
+++ b/minio/minio_test.go
@@ -8,7 +8,9 @@ import (
 	"time"
 
 	"github.com/stretchr/testify/require"
+	"github.com/testcontainers/testcontainers-go"
 	"github.com/testcontainers/testcontainers-go/modules/minio"
+	"github.com/testcontainers/testcontainers-go/wait"
 )
 
 const (
@@ -17,6 +19,8 @@ const (
 	minioImageEnvVar string = "TEST_MINIO_IMAGE"
 	minioUser        string = "minio-user"
 	minioPass        string = "minio-password"
+	minioPort               = "9000/tcp"
+	minioHealthPath         = "/minio/health/live"
 )
 
 func newTestStore(t testing.TB) (*Storage, error) {
@@ -33,7 +37,12 @@ func newTestStore(t testing.TB) (*Storage, error) {
 		img,
 		minio.WithUsername(minioUser),
 		minio.WithPassword(minioPass),
+		testcontainers.WithWaitStrategy(
+			wait.ForListeningPort(minioPort),
+			wait.ForHTTP(minioHealthPath).WithPort(minioPort),
+		),
 	)
+	testcontainers.CleanupContainer(t, c)
 	if err != nil {
 		return nil, err
 	}
@@ -64,6 +73,7 @@ func Test_Get(t *testing.T) {
 
 	testStore, err := newTestStore(t)
 	require.NoError(t, err)
+	defer testStore.Close()
 
 	err = testStore.Set(key, val, 0)
 	require.NoError(t, err)
@@ -84,6 +94,7 @@ func Test_Get_Empty_Key(t *testing.T) {
 
 	testStore, err := newTestStore(t)
 	require.NoError(t, err)
+	defer testStore.Close()
 
 	_, err = testStore.Get(key)
 	require.Error(t, err)
@@ -97,6 +108,7 @@ func Test_Get_Not_Exists_Key(t *testing.T) {
 
 	testStore, err := newTestStore(t)
 	require.NoError(t, err)
+	defer testStore.Close()
 
 	_, err = testStore.Get(key)
 	require.Error(t, err)
@@ -110,6 +122,7 @@ func Test_Get_Not_Exists_Bucket(t *testing.T) {
 
 	testStore, err := newTestStore(t)
 	require.NoError(t, err)
+	defer testStore.Close()
 
 	// random bucket name
 	testStore.cfg.Bucket = strconv.FormatInt(time.Now().UnixMicro(), 10)
@@ -128,6 +141,7 @@ func Test_Set(t *testing.T) {
 
 	testStore, err := newTestStore(t)
 	require.NoError(t, err)
+	defer testStore.Close()
 
 	err = testStore.Set(key, val, 0)
 	require.NoError(t, err)
@@ -141,6 +155,7 @@ func Test_Set_Empty_Key(t *testing.T) {
 
 	testStore, err := newTestStore(t)
 	require.NoError(t, err)
+	defer testStore.Close()
 
 	err = testStore.Set(key, val, 0)
 
@@ -157,6 +172,7 @@ func Test_Set_Not_Exists_Bucket(t *testing.T) {
 
 	testStore, err := newTestStore(t)
 	require.NoError(t, err)
+	defer testStore.Close()
 
 	// random bucket name
 	testStore.cfg.Bucket = strconv.FormatInt(time.Now().UnixMicro(), 10)
@@ -174,6 +190,7 @@ func Test_Delete(t *testing.T) {
 
 	testStore, err := newTestStore(t)
 	require.NoError(t, err)
+	defer testStore.Close()
 
 	err = testStore.Set(key, val, 0)
 	require.NoError(t, err)
@@ -190,6 +207,7 @@ func Test_Delete_Empty_Key(t *testing.T) {
 
 	testStore, err := newTestStore(t)
 	require.NoError(t, err)
+	defer testStore.Close()
 
 	err = testStore.Set(key, val, 0)
 	require.Error(t, err)
@@ -203,6 +221,7 @@ func Test_Delete_Not_Exists_Bucket(t *testing.T) {
 
 	testStore, err := newTestStore(t)
 	require.NoError(t, err)
+	defer testStore.Close()
 
 	// random bucket name
 	testStore.cfg.Bucket = strconv.FormatInt(time.Now().UnixMicro(), 10)
@@ -220,6 +239,7 @@ func Test_Reset(t *testing.T) {
 
 	testStore, err := newTestStore(t)
 	require.NoError(t, err)
+	defer testStore.Close()
 
 	err = testStore.Set("john1", val, 0)
 	require.NoError(t, err)
@@ -248,6 +268,7 @@ func Benchmark_Minio_Set(b *testing.B) {
 
 	testStore, err := newTestStore(b)
 	require.NoError(b, err)
+	defer testStore.Close()
 
 	for i := 0; i < b.N; i++ {
 		err = testStore.Set("john", []byte("doe"), 0)
@@ -259,6 +280,7 @@ func Benchmark_Minio_Set(b *testing.B) {
 func Benchmark_Minio_Get(b *testing.B) {
 	testStore, err := newTestStore(b)
 	require.NoError(b, err)
+	defer testStore.Close()
 
 	err = testStore.Set("john", []byte("doe"), 0)
 	require.NoError(b, err)
@@ -276,6 +298,7 @@ func Benchmark_Minio_Get(b *testing.B) {
 func Benchmark_Minio_SetAndDelete(b *testing.B) {
 	testStore, err := newTestStore(b)
 	require.NoError(b, err)
+	defer testStore.Close()
 
 	b.ReportAllocs()
 	b.ResetTimer()
diff --git a/mongodb/go.mod b/mongodb/go.mod
index f76f663bc..da1c0081d 100644
--- a/mongodb/go.mod
+++ b/mongodb/go.mod
@@ -1,24 +1,67 @@
 module github.com/gofiber/storage/mongodb/v2
 
-go 1.19
+go 1.22
 
 require (
 	github.com/stretchr/testify v1.9.0
+	github.com/testcontainers/testcontainers-go v0.35.0
+	github.com/testcontainers/testcontainers-go/modules/mongodb v0.35.0
 	go.mongodb.org/mongo-driver v1.16.1
 )
 
 require (
+	dario.cat/mergo v1.0.0 // indirect
+	github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
+	github.com/Microsoft/go-winio v0.6.2 // indirect
+	github.com/cenkalti/backoff/v4 v4.2.1 // indirect
+	github.com/containerd/containerd v1.7.18 // indirect
+	github.com/containerd/log v0.1.0 // indirect
+	github.com/containerd/platforms v0.2.1 // indirect
+	github.com/cpuguy83/dockercfg v0.3.2 // indirect
 	github.com/davecgh/go-spew v1.1.1 // indirect
+	github.com/distribution/reference v0.6.0 // indirect
+	github.com/docker/docker v27.1.1+incompatible // indirect
+	github.com/docker/go-connections v0.5.0 // indirect
+	github.com/docker/go-units v0.5.0 // indirect
+	github.com/felixge/httpsnoop v1.0.4 // indirect
+	github.com/go-logr/logr v1.4.1 // indirect
+	github.com/go-logr/stdr v1.2.2 // indirect
+	github.com/go-ole/go-ole v1.2.6 // indirect
+	github.com/gogo/protobuf v1.3.2 // indirect
 	github.com/golang/snappy v0.0.4 // indirect
-	github.com/klauspost/compress v1.16.7 // indirect
+	github.com/google/uuid v1.6.0 // indirect
+	github.com/klauspost/compress v1.17.4 // indirect
+	github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
+	github.com/magiconair/properties v1.8.7 // indirect
+	github.com/moby/docker-image-spec v1.3.1 // indirect
+	github.com/moby/patternmatcher v0.6.0 // indirect
+	github.com/moby/sys/sequential v0.5.0 // indirect
+	github.com/moby/sys/user v0.1.0 // indirect
+	github.com/moby/term v0.5.0 // indirect
 	github.com/montanaflynn/stats v0.7.1 // indirect
+	github.com/morikuni/aec v1.0.0 // indirect
+	github.com/opencontainers/go-digest v1.0.0 // indirect
+	github.com/opencontainers/image-spec v1.1.0 // indirect
+	github.com/pkg/errors v0.9.1 // indirect
 	github.com/pmezard/go-difflib v1.0.0 // indirect
+	github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
+	github.com/shirou/gopsutil/v3 v3.23.12 // indirect
+	github.com/shoenig/go-m1cpu v0.1.6 // indirect
+	github.com/sirupsen/logrus v1.9.3 // indirect
+	github.com/tklauser/go-sysconf v0.3.12 // indirect
+	github.com/tklauser/numcpus v0.6.1 // indirect
 	github.com/xdg-go/pbkdf2 v1.0.0 // indirect
 	github.com/xdg-go/scram v1.1.2 // indirect
 	github.com/xdg-go/stringprep v1.0.4 // indirect
 	github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a // indirect
+	github.com/yusufpapurcu/wmi v1.2.3 // indirect
+	go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect
+	go.opentelemetry.io/otel v1.24.0 // indirect
+	go.opentelemetry.io/otel/metric v1.24.0 // indirect
+	go.opentelemetry.io/otel/trace v1.24.0 // indirect
 	golang.org/x/crypto v0.31.0 // indirect
 	golang.org/x/sync v0.10.0 // indirect
+	golang.org/x/sys v0.28.0 // indirect
 	golang.org/x/text v0.21.0 // indirect
 	gopkg.in/yaml.v3 v3.0.1 // indirect
 )
diff --git a/mongodb/go.sum b/mongodb/go.sum
index f6e73380d..dd8df37d8 100644
--- a/mongodb/go.sum
+++ b/mongodb/go.sum
@@ -1,16 +1,120 @@
+dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk=
+dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
+github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9vkmnHYOMsOr4WLk+Vo07yKIzd94sVoIqshQ4bU=
+github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8=
+github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8=
+github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
+github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
+github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
+github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM=
+github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
+github.com/containerd/containerd v1.7.18 h1:jqjZTQNfXGoEaZdW1WwPU0RqSn1Bm2Ay/KJPUuO8nao=
+github.com/containerd/containerd v1.7.18/go.mod h1:IYEk9/IO6wAPUz2bCMVUbsfXjzw5UNP5fLz4PsUygQ4=
+github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I=
+github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo=
+github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A=
+github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw=
+github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA=
+github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc=
+github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY=
+github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
+github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
+github.com/docker/docker v27.1.1+incompatible h1:hO/M4MtV36kzKldqnA37IWhebRA+LnqqcqDja6kVaKY=
+github.com/docker/docker v27.1.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
+github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c=
+github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc=
+github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
+github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
+github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
+github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
+github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
+github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=
+github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
+github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
+github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
+github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
+github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
+github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
+github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
 github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
 github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
+github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
 github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
-github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I=
-github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
+github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
+github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
+github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 h1:YBftPWNWd4WwGqtY2yeZL2ef8rHAxPBD8KFhJpmcqms=
+github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0/go.mod h1:YN5jB8ie0yfIUg6VvR9Kz84aCaG7AsGZnLjhHbUqwPg=
+github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
+github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
+github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4=
+github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM=
+github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
+github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
+github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
+github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
+github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4=
+github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
+github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
+github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
+github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0=
+github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=
+github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkVGiPk=
+github.com/moby/patternmatcher v0.6.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc=
+github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc=
+github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo=
+github.com/moby/sys/user v0.1.0 h1:WmZ93f5Ux6het5iituh9x2zAG7NFY9Aqi49jjE1PaQg=
+github.com/moby/sys/user v0.1.0/go.mod h1:fKJhFOnsCN6xZ5gSfbM6zaHGgDJMrqt9/reuj4T7MmU=
+github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0=
+github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y=
 github.com/montanaflynn/stats v0.7.1 h1:etflOAAHORrCC44V+aR6Ftzort912ZU+YLiSTuV8eaE=
 github.com/montanaflynn/stats v0.7.1/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow=
+github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
+github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
+github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
+github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
+github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug=
+github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM=
+github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
+github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
 github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw=
+github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
+github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg=
+github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o=
+github.com/shirou/gopsutil/v3 v3.23.12 h1:z90NtUkp3bMtmICZKpC4+WaknU1eXtp5vtbQ11DgpE4=
+github.com/shirou/gopsutil/v3 v3.23.12/go.mod h1:1FrWgea594Jp7qmjHUUPlJDTPgcsb9mGnXDxavtikzM=
+github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM=
+github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ=
+github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU=
+github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k=
+github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
+github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
+github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
+github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
+github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
+github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
+github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
 github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
 github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
+github.com/testcontainers/testcontainers-go v0.35.0 h1:uADsZpTKFAtp8SLK+hMwSaa+X+JiERHtd4sQAFmXeMo=
+github.com/testcontainers/testcontainers-go v0.35.0/go.mod h1:oEVBj5zrfJTrgjwONs1SsRbnBtH9OKl+IGl3UMcr2B4=
+github.com/testcontainers/testcontainers-go/modules/mongodb v0.35.0 h1:i1Kh9fmXgHG9z3uzJv5Arz7pDKVaaNpLrqyd+0xhYMA=
+github.com/testcontainers/testcontainers-go/modules/mongodb v0.35.0/go.mod h1:SD8nVMK1m7b/K2YJqYjYNzfHmZfqHtqNOlI44nfxjdg=
+github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU=
+github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI=
+github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk=
+github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY=
 github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c=
 github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
 github.com/xdg-go/scram v1.1.2 h1:FHX5I5B4i4hKRVRBCFRxq1iQRej7WO3hhBuJf+UUySY=
@@ -19,42 +123,104 @@ github.com/xdg-go/stringprep v1.0.4 h1:XLI/Ng3O1Atzq0oBs3TWm+5ZVgkq2aqdlvP9JtoZ6
 github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM=
 github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a h1:fZHgsYlfvtyqToslyjUt3VOPF4J7aK/3MPcK7xp3PDk=
 github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a/go.mod h1:ul22v+Nro/R083muKhosV54bj5niojjWZvU8xrevuH4=
+github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
+github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw=
+github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
 go.mongodb.org/mongo-driver v1.16.1 h1:rIVLL3q0IHM39dvE+z2ulZLp9ENZKThVfuvN/IiN4l8=
 go.mongodb.org/mongo-driver v1.16.1/go.mod h1:oB6AhJQvFQL4LEHyXi6aJzQJtBiTQHiAd83l0GdFaiw=
+go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 h1:jq9TW8u3so/bN+JPT166wjOI6/vQPF6Xe7nMNIltagk=
+go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0/go.mod h1:p8pYQP+m5XfbZm9fxtSKAbM6oIllS7s2AfxrChvc7iw=
+go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo=
+go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0 h1:Mne5On7VWdx7omSrSSZvM4Kw7cS7NQkOOmLcgscI51U=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0/go.mod h1:IPtUMKL4O3tH5y+iXVyAXqpAwMuzC1IrxVS81rummfE=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0 h1:IeMeyr1aBvBiPVYihXIaeIZba6b8E1bYp7lbdxK8CQg=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0/go.mod h1:oVdCUtjq9MK9BlS7TtucsQwUcXcymNiEDjgDD2jMtZU=
+go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI=
+go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco=
+go.opentelemetry.io/otel/sdk v1.19.0 h1:6USY6zH+L8uMH8L3t1enZPR3WFEmSTADlqldyHtJi3o=
+go.opentelemetry.io/otel/sdk v1.19.0/go.mod h1:NedEbbS4w3C6zElbLdPJKOpJQOrGUJ+GfzpjUvI0v1A=
+go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI=
+go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU=
+go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I=
+go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
 golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
 golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
+golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
 golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
 golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
 golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
+golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ=
+golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE=
 golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
 golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
+golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
+golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q=
+golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
 golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
 golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
 golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
+golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44=
+golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
 golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
 golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
+golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+google.golang.org/genproto v0.0.0-20230920204549-e6e6cdab5c13 h1:vlzZttNJGVqTsRFU9AmdnrcO1Znh8Ew9kCD//yjigk0=
+google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 h1:RFiFrvy37/mpSpdySBDrUdipW/dHwsRwh3J3+A9VgT4=
+google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237/go.mod h1:Z5Iiy3jtmioajWHDGFk7CeugTyHtPvMHA4UTmUkyalE=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 h1:NnYq6UN9ReLM9/Y01KWNOWyI5xQ9kbIms5GGJVwS/Yc=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY=
+google.golang.org/grpc v1.64.1 h1:LKtvyfbX3UGVPFcGqJ9ItpVWW6oN/2XqTxfAnwRRXiA=
+google.golang.org/grpc v1.64.1/go.mod h1:hiQF4LFZelK2WKaP6W0L92zGHtiQdZxk8CrSdvyjeP0=
+google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
+google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
+gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
 gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU=
+gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU=
diff --git a/mongodb/mongodb_test.go b/mongodb/mongodb_test.go
index a12d1f502..3c45c141d 100644
--- a/mongodb/mongodb_test.go
+++ b/mongodb/mongodb_test.go
@@ -1,24 +1,60 @@
 package mongodb
 
 import (
+	"context"
 	"os"
 	"testing"
 	"time"
 
 	"github.com/stretchr/testify/require"
+	"github.com/testcontainers/testcontainers-go"
+	"github.com/testcontainers/testcontainers-go/modules/mongodb"
+	"github.com/testcontainers/testcontainers-go/wait"
 )
 
-var testStore *Storage
+const (
+	// mongoDBImage is the default image used for running MongoDB in tests.
+	mongoDBImage              = "mongo:7"
+	mongoDBImageEnvVar string = "TEST_MONGODB_IMAGE"
+	mongoDBUser        string = "mongo-user"
+	mongoDBPass        string = "mongo-password"
+	mongoDBPort               = "27017/tcp"
+	mongoDBReadyLog           = "Waiting for connections"
+)
+
+func newTestStore(t testing.TB) (*Storage, error) {
+	t.Helper()
+
+	img := mongoDBImage
+	if imgFromEnv := os.Getenv(mongoDBImageEnvVar); imgFromEnv != "" {
+		img = imgFromEnv
+	}
 
-func TestMain(m *testing.M) {
-	testStore = New(Config{
-		Reset: true,
-	})
+	ctx := context.Background()
 
-	code := m.Run()
+	c, err := mongodb.Run(
+		ctx, img, mongodb.WithUsername(mongoDBUser), mongodb.WithPassword(mongoDBPass),
+		testcontainers.WithWaitStrategy(
+			wait.ForAll(
+				wait.ForListeningPort(mongoDBPort),
+				wait.ForLog(mongoDBReadyLog),
+			),
+		),
+	)
+	testcontainers.CleanupContainer(t, c)
+	if err != nil {
+		return nil, err
+	}
 
-	_ = testStore.Close()
-	os.Exit(code)
+	conn, err := c.ConnectionString(ctx)
+	if err != nil {
+		return nil, err
+	}
+
+	return New(Config{
+		ConnectionURI: conn,
+		Reset:         true,
+	}), nil
 }
 
 func Test_MongoDB_Set(t *testing.T) {
@@ -27,7 +63,11 @@ func Test_MongoDB_Set(t *testing.T) {
 		val = []byte("doe")
 	)
 
-	err := testStore.Set(key, val, 0)
+	testStore, err := newTestStore(t)
+	require.NoError(t, err)
+	defer testStore.Close()
+
+	err = testStore.Set(key, val, 0)
 	require.NoError(t, err)
 }
 
@@ -37,7 +77,11 @@ func Test_MongoDB_Set_Override(t *testing.T) {
 		val = []byte("doe")
 	)
 
-	err := testStore.Set(key, val, 0)
+	testStore, err := newTestStore(t)
+	require.NoError(t, err)
+	defer testStore.Close()
+
+	err = testStore.Set(key, val, 0)
 	require.NoError(t, err)
 
 	err = testStore.Set(key, val, 0)
@@ -50,7 +94,11 @@ func Test_MongoDB_Get(t *testing.T) {
 		val = []byte("doe")
 	)
 
-	err := testStore.Set(key, val, 0)
+	testStore, err := newTestStore(t)
+	require.NoError(t, err)
+	defer testStore.Close()
+
+	err = testStore.Set(key, val, 0)
 	require.NoError(t, err)
 
 	result, err := testStore.Get(key)
@@ -65,21 +113,37 @@ func Test_MongoDB_Set_Expiration(t *testing.T) {
 		exp = 1 * time.Second
 	)
 
-	err := testStore.Set(key, val, exp)
+	testStore, err := newTestStore(t)
+	require.NoError(t, err)
+	defer testStore.Close()
+
+	err = testStore.Set(key, val, exp)
 	require.NoError(t, err)
 
 	time.Sleep(1100 * time.Millisecond)
+
+	result, err := testStore.Get(key)
+	require.NoError(t, err)
+	require.Zero(t, len(result), "Key should have expired")
 }
 
 func Test_MongoDB_Get_Expired(t *testing.T) {
 	key := "john"
 
+	testStore, err := newTestStore(t)
+	require.NoError(t, err)
+	defer testStore.Close()
+
 	result, err := testStore.Get(key)
 	require.NoError(t, err)
 	require.Zero(t, len(result))
 }
 
 func Test_MongoDB_Get_NotExist(t *testing.T) {
+	testStore, err := newTestStore(t)
+	require.NoError(t, err)
+	defer testStore.Close()
+
 	result, err := testStore.Get("notexist")
 	require.NoError(t, err)
 	require.Zero(t, len(result))
@@ -91,7 +155,11 @@ func Test_MongoDB_Delete(t *testing.T) {
 		val = []byte("doe")
 	)
 
-	err := testStore.Set(key, val, 0)
+	testStore, err := newTestStore(t)
+	require.NoError(t, err)
+	defer testStore.Close()
+
+	err = testStore.Set(key, val, 0)
 	require.NoError(t, err)
 
 	err = testStore.Delete(key)
@@ -105,7 +173,11 @@ func Test_MongoDB_Delete(t *testing.T) {
 func Test_MongoDB_Reset(t *testing.T) {
 	val := []byte("doe")
 
-	err := testStore.Set("john1", val, 0)
+	testStore, err := newTestStore(t)
+	require.NoError(t, err)
+	defer testStore.Close()
+
+	err = testStore.Set("john1", val, 0)
 	require.NoError(t, err)
 
 	err = testStore.Set("john2", val, 0)
@@ -124,18 +196,28 @@ func Test_MongoDB_Reset(t *testing.T) {
 }
 
 func Test_MongoDB_Close(t *testing.T) {
+	testStore, err := newTestStore(t)
+	require.NoError(t, err)
+
 	require.Nil(t, testStore.Close())
 }
 
 func Test_MongoDB_Conn(t *testing.T) {
+	testStore, err := newTestStore(t)
+	require.NoError(t, err)
+	defer testStore.Close()
+
 	require.True(t, testStore.Conn() != nil)
 }
 
 func Benchmark_MongoDB_Set(b *testing.B) {
+	testStore, err := newTestStore(b)
+	require.NoError(b, err)
+	defer testStore.Close()
+
 	b.ReportAllocs()
 	b.ResetTimer()
 
-	var err error
 	for i := 0; i < b.N; i++ {
 		err = testStore.Set("john", []byte("doe"), 0)
 	}
@@ -144,7 +226,11 @@ func Benchmark_MongoDB_Set(b *testing.B) {
 }
 
 func Benchmark_MongoDB_Get(b *testing.B) {
-	err := testStore.Set("john", []byte("doe"), 0)
+	testStore, err := newTestStore(b)
+	require.NoError(b, err)
+	defer testStore.Close()
+
+	err = testStore.Set("john", []byte("doe"), 0)
 	require.NoError(b, err)
 
 	b.ReportAllocs()
@@ -158,10 +244,13 @@ func Benchmark_MongoDB_Get(b *testing.B) {
 }
 
 func Benchmark_MongoDB_SetAndDelete(b *testing.B) {
+	testStore, err := newTestStore(b)
+	require.NoError(b, err)
+	defer testStore.Close()
+
 	b.ReportAllocs()
 	b.ResetTimer()
 
-	var err error
 	for i := 0; i < b.N; i++ {
 		_ = testStore.Set("john", []byte("doe"), 0)
 		err = testStore.Delete("john")
diff --git a/mysql/go.mod b/mysql/go.mod
index 2675c20ad..1c5d9804d 100644
--- a/mysql/go.mod
+++ b/mysql/go.mod
@@ -1,15 +1,60 @@
 module github.com/gofiber/storage/mysql/v2
 
-go 1.19
+go 1.22
 
 require (
 	github.com/go-sql-driver/mysql v1.8.1
 	github.com/stretchr/testify v1.9.0
+	github.com/testcontainers/testcontainers-go v0.35.0
+	github.com/testcontainers/testcontainers-go/modules/mysql v0.35.0
 )
 
 require (
+	dario.cat/mergo v1.0.0 // indirect
 	filippo.io/edwards25519 v1.1.0 // indirect
+	github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
+	github.com/Microsoft/go-winio v0.6.2 // indirect
+	github.com/cenkalti/backoff/v4 v4.2.1 // indirect
+	github.com/containerd/containerd v1.7.18 // indirect
+	github.com/containerd/log v0.1.0 // indirect
+	github.com/containerd/platforms v0.2.1 // indirect
+	github.com/cpuguy83/dockercfg v0.3.2 // indirect
 	github.com/davecgh/go-spew v1.1.1 // indirect
+	github.com/distribution/reference v0.6.0 // indirect
+	github.com/docker/docker v27.1.1+incompatible // indirect
+	github.com/docker/go-connections v0.5.0 // indirect
+	github.com/docker/go-units v0.5.0 // indirect
+	github.com/felixge/httpsnoop v1.0.4 // indirect
+	github.com/go-logr/logr v1.4.1 // indirect
+	github.com/go-logr/stdr v1.2.2 // indirect
+	github.com/go-ole/go-ole v1.2.6 // indirect
+	github.com/gogo/protobuf v1.3.2 // indirect
+	github.com/google/uuid v1.6.0 // indirect
+	github.com/klauspost/compress v1.17.4 // indirect
+	github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
+	github.com/magiconair/properties v1.8.7 // indirect
+	github.com/moby/docker-image-spec v1.3.1 // indirect
+	github.com/moby/patternmatcher v0.6.0 // indirect
+	github.com/moby/sys/sequential v0.5.0 // indirect
+	github.com/moby/sys/user v0.1.0 // indirect
+	github.com/moby/term v0.5.0 // indirect
+	github.com/morikuni/aec v1.0.0 // indirect
+	github.com/opencontainers/go-digest v1.0.0 // indirect
+	github.com/opencontainers/image-spec v1.1.0 // indirect
+	github.com/pkg/errors v0.9.1 // indirect
 	github.com/pmezard/go-difflib v1.0.0 // indirect
+	github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
+	github.com/shirou/gopsutil/v3 v3.23.12 // indirect
+	github.com/shoenig/go-m1cpu v0.1.6 // indirect
+	github.com/sirupsen/logrus v1.9.3 // indirect
+	github.com/tklauser/go-sysconf v0.3.12 // indirect
+	github.com/tklauser/numcpus v0.6.1 // indirect
+	github.com/yusufpapurcu/wmi v1.2.3 // indirect
+	go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect
+	go.opentelemetry.io/otel v1.24.0 // indirect
+	go.opentelemetry.io/otel/metric v1.24.0 // indirect
+	go.opentelemetry.io/otel/trace v1.24.0 // indirect
+	golang.org/x/crypto v0.31.0 // indirect
+	golang.org/x/sys v0.28.0 // indirect
 	gopkg.in/yaml.v3 v3.0.1 // indirect
 )
diff --git a/mysql/go.sum b/mysql/go.sum
index 338ca322f..093246985 100644
--- a/mysql/go.sum
+++ b/mysql/go.sum
@@ -1,14 +1,198 @@
+dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk=
+dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
 filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
 filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
+github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9vkmnHYOMsOr4WLk+Vo07yKIzd94sVoIqshQ4bU=
+github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8=
+github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8=
+github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
+github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
+github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
+github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM=
+github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
+github.com/containerd/containerd v1.7.18 h1:jqjZTQNfXGoEaZdW1WwPU0RqSn1Bm2Ay/KJPUuO8nao=
+github.com/containerd/containerd v1.7.18/go.mod h1:IYEk9/IO6wAPUz2bCMVUbsfXjzw5UNP5fLz4PsUygQ4=
+github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I=
+github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo=
+github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A=
+github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw=
+github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA=
+github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc=
+github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY=
+github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
+github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
+github.com/docker/docker v27.1.1+incompatible h1:hO/M4MtV36kzKldqnA37IWhebRA+LnqqcqDja6kVaKY=
+github.com/docker/docker v27.1.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
+github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c=
+github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc=
+github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
+github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
+github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
+github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
+github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
+github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=
+github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
+github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
+github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
+github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
+github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
 github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
 github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
+github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
+github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
+github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
+github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
+github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
+github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
+github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 h1:YBftPWNWd4WwGqtY2yeZL2ef8rHAxPBD8KFhJpmcqms=
+github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0/go.mod h1:YN5jB8ie0yfIUg6VvR9Kz84aCaG7AsGZnLjhHbUqwPg=
+github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
+github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
+github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4=
+github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM=
+github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
+github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
+github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
+github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
+github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4=
+github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
+github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
+github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
+github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0=
+github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=
+github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkVGiPk=
+github.com/moby/patternmatcher v0.6.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc=
+github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc=
+github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo=
+github.com/moby/sys/user v0.1.0 h1:WmZ93f5Ux6het5iituh9x2zAG7NFY9Aqi49jjE1PaQg=
+github.com/moby/sys/user v0.1.0/go.mod h1:fKJhFOnsCN6xZ5gSfbM6zaHGgDJMrqt9/reuj4T7MmU=
+github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0=
+github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y=
+github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
+github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
+github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
+github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
+github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug=
+github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM=
+github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
+github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
 github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw=
+github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
+github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg=
+github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o=
+github.com/shirou/gopsutil/v3 v3.23.12 h1:z90NtUkp3bMtmICZKpC4+WaknU1eXtp5vtbQ11DgpE4=
+github.com/shirou/gopsutil/v3 v3.23.12/go.mod h1:1FrWgea594Jp7qmjHUUPlJDTPgcsb9mGnXDxavtikzM=
+github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM=
+github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ=
+github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU=
+github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k=
+github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
+github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
+github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
+github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
+github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
+github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
+github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
 github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
 github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
-gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
+github.com/testcontainers/testcontainers-go v0.35.0 h1:uADsZpTKFAtp8SLK+hMwSaa+X+JiERHtd4sQAFmXeMo=
+github.com/testcontainers/testcontainers-go v0.35.0/go.mod h1:oEVBj5zrfJTrgjwONs1SsRbnBtH9OKl+IGl3UMcr2B4=
+github.com/testcontainers/testcontainers-go/modules/mysql v0.35.0 h1:9voGAf+1KxC0ck/XtrC/AUrkr74SSGpQRBp0O851B3Y=
+github.com/testcontainers/testcontainers-go/modules/mysql v0.35.0/go.mod h1:rxKSkFpc5XZtG00prjqPfobuMgt5EpFEOrzZgYdOX0c=
+github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU=
+github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI=
+github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk=
+github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY=
+github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw=
+github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
+go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 h1:jq9TW8u3so/bN+JPT166wjOI6/vQPF6Xe7nMNIltagk=
+go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0/go.mod h1:p8pYQP+m5XfbZm9fxtSKAbM6oIllS7s2AfxrChvc7iw=
+go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo=
+go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0 h1:Mne5On7VWdx7omSrSSZvM4Kw7cS7NQkOOmLcgscI51U=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0/go.mod h1:IPtUMKL4O3tH5y+iXVyAXqpAwMuzC1IrxVS81rummfE=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0 h1:IeMeyr1aBvBiPVYihXIaeIZba6b8E1bYp7lbdxK8CQg=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0/go.mod h1:oVdCUtjq9MK9BlS7TtucsQwUcXcymNiEDjgDD2jMtZU=
+go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI=
+go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco=
+go.opentelemetry.io/otel/sdk v1.19.0 h1:6USY6zH+L8uMH8L3t1enZPR3WFEmSTADlqldyHtJi3o=
+go.opentelemetry.io/otel/sdk v1.19.0/go.mod h1:NedEbbS4w3C6zElbLdPJKOpJQOrGUJ+GfzpjUvI0v1A=
+go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI=
+go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU=
+go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I=
+go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
+golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
+golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
+golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ=
+golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
+golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q=
+golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
+golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
+golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44=
+golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
+golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+google.golang.org/genproto v0.0.0-20230920204549-e6e6cdab5c13 h1:vlzZttNJGVqTsRFU9AmdnrcO1Znh8Ew9kCD//yjigk0=
+google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 h1:RFiFrvy37/mpSpdySBDrUdipW/dHwsRwh3J3+A9VgT4=
+google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237/go.mod h1:Z5Iiy3jtmioajWHDGFk7CeugTyHtPvMHA4UTmUkyalE=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 h1:NnYq6UN9ReLM9/Y01KWNOWyI5xQ9kbIms5GGJVwS/Yc=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY=
+google.golang.org/grpc v1.64.1 h1:LKtvyfbX3UGVPFcGqJ9ItpVWW6oN/2XqTxfAnwRRXiA=
+google.golang.org/grpc v1.64.1/go.mod h1:hiQF4LFZelK2WKaP6W0L92zGHtiQdZxk8CrSdvyjeP0=
+google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
+google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
+gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
 gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU=
+gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU=
diff --git a/mysql/mysql_test.go b/mysql/mysql_test.go
index 6bb4eb6c1..ce9cc94d7 100644
--- a/mysql/mysql_test.go
+++ b/mysql/mysql_test.go
@@ -1,50 +1,88 @@
 package mysql
 
 import (
+	"context"
 	"database/sql"
-	"fmt"
 	"os"
 	"testing"
 	"time"
 
 	"github.com/stretchr/testify/require"
+	"github.com/testcontainers/testcontainers-go"
+	"github.com/testcontainers/testcontainers-go/modules/mysql"
+	"github.com/testcontainers/testcontainers-go/wait"
 )
 
-var testStore = New(Config{
-	Database: os.Getenv("MYSQL_DATABASE"),
-	Username: os.Getenv("MYSQL_USERNAME"),
-	Password: os.Getenv("MYSQL_PASSWORD"),
-	Reset:    true,
-})
+const (
+	// mysqlImage is the default image used for running MySQL in tests.
+	mysqlImage              = "docker.io/mysql:9"
+	mysqlImageEnvVar string = "TEST_MYSQL_IMAGE"
+	mysqlUser        string = "username"
+	mysqlPass        string = "password"
+	mysqlDatabase    string = "fiber"
+)
 
-func Test_MYSQL_New(t *testing.T) {
-	newConfigStore := New(Config{
-		Database: os.Getenv("MYSQL_DATABASE"),
-		Username: os.Getenv("MYSQL_USERNAME"),
-		Password: os.Getenv("MYSQL_PASSWORD"),
-		Reset:    true,
-	})
+func newTestStore(t testing.TB) (*Storage, error) {
+	t.Helper()
 
-	require.True(t, newConfigStore.db != nil)
-	require.NoError(t, newConfigStore.Close())
+	ctx := context.Background()
+
+	c := mustStartMySQL(t)
+
+	conn, err := c.ConnectionString(ctx)
+	if err != nil {
+		return nil, err
+	}
 
-	dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s", os.Getenv("MYSQL_USERNAME"), os.Getenv("MYSQL_PASSWORD"), "127.0.0.1", 3306, os.Getenv("MYSQL_DATABASE"))
-	newConfigStore = New(Config{
-		ConnectionURI: dsn,
+	return New(Config{
+		ConnectionURI: conn,
 		Reset:         true,
-	})
+	}), nil
+}
 
-	require.True(t, newConfigStore.db != nil)
-	newConfigStore.Close()
+func mustStartMySQL(t testing.TB) *mysql.MySQLContainer {
+	img := mysqlImage
+	if imgFromEnv := os.Getenv(mysqlImageEnvVar); imgFromEnv != "" {
+		img = imgFromEnv
+	}
+
+	ctx := context.Background()
+
+	c, err := mysql.Run(ctx, img,
+		mysql.WithPassword(mysqlPass),
+		mysql.WithUsername(mysqlUser),
+		mysql.WithDatabase(mysqlDatabase),
+		testcontainers.WithWaitStrategy(
+			wait.ForListeningPort("3306/tcp"),
+			wait.ForLog("port: 3306  MySQL Community Server"),
+		),
+	)
+	testcontainers.CleanupContainer(t, c)
+	require.NoError(t, err)
+
+	return c
+}
+
+func Test_MYSQL_New(t *testing.T) {
+	testStore, err := newTestStore(t)
+	require.NoError(t, err)
+
+	require.True(t, testStore.db != nil)
+	require.NoError(t, testStore.Close())
+
+	c := mustStartMySQL(t)
+
+	dsn, err := c.ConnectionString(context.Background())
+	require.NoError(t, err)
 
 	db, _ := sql.Open("mysql", dsn)
-	newConfigStore = New(Config{
+	newConfigStore := New(Config{
 		Db:    db,
 		Reset: true,
 	})
 
 	require.True(t, newConfigStore.db != nil)
-	newConfigStore.Close()
+	defer newConfigStore.Close()
 }
 
 func Test_MYSQL_Set(t *testing.T) {
@@ -53,7 +91,11 @@ func Test_MYSQL_Set(t *testing.T) {
 		val = []byte("doe")
 	)
 
-	err := testStore.Set(key, val, 0)
+	testStore, err := newTestStore(t)
+	require.NoError(t, err)
+	defer testStore.Close()
+
+	err = testStore.Set(key, val, 0)
 	require.NoError(t, err)
 }
 
@@ -63,7 +105,11 @@ func Test_MYSQL_Set_Override(t *testing.T) {
 		val = []byte("doe")
 	)
 
-	err := testStore.Set(key, val, 0)
+	testStore, err := newTestStore(t)
+	require.NoError(t, err)
+	defer testStore.Close()
+
+	err = testStore.Set(key, val, 0)
 	require.NoError(t, err)
 
 	err = testStore.Set(key, val, 0)
@@ -76,7 +122,11 @@ func Test_MYSQL_Get(t *testing.T) {
 		val = []byte("doe")
 	)
 
-	err := testStore.Set(key, val, 0)
+	testStore, err := newTestStore(t)
+	require.NoError(t, err)
+	defer testStore.Close()
+
+	err = testStore.Set(key, val, 0)
 	require.NoError(t, err)
 
 	result, err := testStore.Get(key)
@@ -91,21 +141,37 @@ func Test_MYSQL_Set_Expiration(t *testing.T) {
 		exp = 1 * time.Second
 	)
 
-	err := testStore.Set(key, val, exp)
+	testStore, err := newTestStore(t)
+	require.NoError(t, err)
+	defer testStore.Close()
+
+	err = testStore.Set(key, val, exp)
 	require.NoError(t, err)
 
 	time.Sleep(1100 * time.Millisecond)
+
+	result, err := testStore.Get(key)
+	require.NoError(t, err)
+	require.Zero(t, len(result), "Key should have expired")
 }
 
 func Test_MYSQL_Get_Expired(t *testing.T) {
 	key := "john"
 
+	testStore, err := newTestStore(t)
+	require.NoError(t, err)
+	defer testStore.Close()
+
 	result, err := testStore.Get(key)
 	require.NoError(t, err)
 	require.Zero(t, len(result))
 }
 
 func Test_MYSQL_Get_NotExist(t *testing.T) {
+	testStore, err := newTestStore(t)
+	require.NoError(t, err)
+	defer testStore.Close()
+
 	result, err := testStore.Get("notexist")
 	require.NoError(t, err)
 	require.Zero(t, len(result))
@@ -117,7 +183,11 @@ func Test_MYSQL_Delete(t *testing.T) {
 		val = []byte("doe")
 	)
 
-	err := testStore.Set(key, val, 0)
+	testStore, err := newTestStore(t)
+	require.NoError(t, err)
+	defer testStore.Close()
+
+	err = testStore.Set(key, val, 0)
 	require.NoError(t, err)
 
 	err = testStore.Delete(key)
@@ -131,7 +201,11 @@ func Test_MYSQL_Delete(t *testing.T) {
 func Test_MYSQL_Reset(t *testing.T) {
 	val := []byte("doe")
 
-	err := testStore.Set("john1", val, 0)
+	testStore, err := newTestStore(t)
+	require.NoError(t, err)
+	defer testStore.Close()
+
+	err = testStore.Set("john1", val, 0)
 	require.NoError(t, err)
 
 	err = testStore.Set("john2", val, 0)
@@ -153,7 +227,11 @@ func Test_MYSQL_GC(t *testing.T) {
 	testVal := []byte("doe")
 
 	// This key should expire
-	err := testStore.Set("john", testVal, time.Nanosecond)
+	testStore, err := newTestStore(t)
+	require.NoError(t, err)
+	defer testStore.Close()
+
+	err = testStore.Set("john", testVal, time.Nanosecond)
 	require.NoError(t, err)
 
 	testStore.gc(time.Now())
@@ -174,7 +252,11 @@ func Test_MYSQL_GC(t *testing.T) {
 func Test_MYSQL_Non_UTF8(t *testing.T) {
 	val := []byte("0xF5")
 
-	err := testStore.Set("0xF6", val, 0)
+	testStore, err := newTestStore(t)
+	require.NoError(t, err)
+	defer testStore.Close()
+
+	err = testStore.Set("0xF6", val, 0)
 	require.NoError(t, err)
 
 	result, err := testStore.Get("0xF6")
@@ -183,18 +265,28 @@ func Test_MYSQL_Non_UTF8(t *testing.T) {
 }
 
 func Test_MYSQL_Close(t *testing.T) {
+	testStore, err := newTestStore(t)
+	require.NoError(t, err)
+
 	require.Nil(t, testStore.Close())
 }
 
 func Test_MYSQL_Conn(t *testing.T) {
+	testStore, err := newTestStore(t)
+	require.NoError(t, err)
+	defer testStore.Close()
+
 	require.True(t, testStore.Conn() != nil)
 }
 
 func Benchmark_MYSQL_Set(b *testing.B) {
+	testStore, err := newTestStore(b)
+	require.NoError(b, err)
+	defer testStore.Close()
+
 	b.ReportAllocs()
 	b.ResetTimer()
 
-	var err error
 	for i := 0; i < b.N; i++ {
 		err = testStore.Set("john", []byte("doe"), 0)
 	}
@@ -203,7 +295,11 @@ func Benchmark_MYSQL_Set(b *testing.B) {
 }
 
 func Benchmark_MYSQL_Get(b *testing.B) {
-	err := testStore.Set("john", []byte("doe"), 0)
+	testStore, err := newTestStore(b)
+	require.NoError(b, err)
+	defer testStore.Close()
+
+	err = testStore.Set("john", []byte("doe"), 0)
 	require.NoError(b, err)
 
 	b.ReportAllocs()
@@ -217,10 +313,13 @@ func Benchmark_MYSQL_Get(b *testing.B) {
 }
 
 func Benchmark_MYSQL_SetAndDelete(b *testing.B) {
+	testStore, err := newTestStore(b)
+	require.NoError(b, err)
+	defer testStore.Close()
+
 	b.ReportAllocs()
 	b.ResetTimer()
 
-	var err error
 	for i := 0; i < b.N; i++ {
 		_ = testStore.Set("john", []byte("doe"), 0)
 		err = testStore.Delete("john")
diff --git a/neo4j/neo4j_test.go b/neo4j/neo4j_test.go
index 7a6548bff..db15c0aea 100644
--- a/neo4j/neo4j_test.go
+++ b/neo4j/neo4j_test.go
@@ -8,7 +8,15 @@ import (
 	"time"
 
 	"github.com/stretchr/testify/require"
+	"github.com/testcontainers/testcontainers-go"
 	"github.com/testcontainers/testcontainers-go/modules/neo4j"
+	"github.com/testcontainers/testcontainers-go/wait"
+)
+
+const (
+	neo4jHttpPort = "7474/tcp"
+	neo4jBoltPort = "7687/tcp"
+	neo4jReadyLog = "Bolt enabled on"
 )
 
 var testStore *Storage
@@ -21,6 +29,13 @@ func TestMain(m *testing.M) {
 	neo4jContainer, err := neo4j.Run(ctx,
 		"neo4j:5.26",
 		neo4j.WithAdminPassword("pass#w*#d"),
+		testcontainers.WithWaitStrategy(
+			wait.ForAll(
+				wait.ForListeningPort(neo4jHttpPort),
+				wait.ForListeningPort(neo4jBoltPort),
+				wait.ForLog(neo4jReadyLog),
+			),
+		),
 	)
 	if err != nil {
 		log.Fatalf("Failed to start Neo4j container: %v", err)
diff --git a/postgres/go.mod b/postgres/go.mod
index cfb0fb6c7..653c8ad01 100644
--- a/postgres/go.mod
+++ b/postgres/go.mod
@@ -1,22 +1,65 @@
 module github.com/gofiber/storage/postgres/v3
 
-go 1.20
+go 1.22
 
 require (
 	github.com/jackc/pgx/v5 v5.6.0
 	github.com/stretchr/testify v1.9.0
+	github.com/testcontainers/testcontainers-go v0.35.0
+	github.com/testcontainers/testcontainers-go/modules/postgres v0.35.0
 )
 
 require (
+	dario.cat/mergo v1.0.0 // indirect
+	github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
+	github.com/Microsoft/go-winio v0.6.2 // indirect
+	github.com/cenkalti/backoff/v4 v4.2.1 // indirect
+	github.com/containerd/containerd v1.7.18 // indirect
+	github.com/containerd/log v0.1.0 // indirect
+	github.com/containerd/platforms v0.2.1 // indirect
+	github.com/cpuguy83/dockercfg v0.3.2 // indirect
 	github.com/davecgh/go-spew v1.1.1 // indirect
+	github.com/distribution/reference v0.6.0 // indirect
+	github.com/docker/docker v27.1.1+incompatible // indirect
+	github.com/docker/go-connections v0.5.0 // indirect
+	github.com/docker/go-units v0.5.0 // indirect
+	github.com/felixge/httpsnoop v1.0.4 // indirect
+	github.com/go-logr/logr v1.4.1 // indirect
+	github.com/go-logr/stdr v1.2.2 // indirect
+	github.com/go-ole/go-ole v1.2.6 // indirect
+	github.com/gogo/protobuf v1.3.2 // indirect
+	github.com/google/uuid v1.6.0 // indirect
 	github.com/jackc/pgpassfile v1.0.0 // indirect
 	github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9 // indirect
 	github.com/jackc/puddle/v2 v2.2.1 // indirect
-	github.com/kr/text v0.2.0 // indirect
+	github.com/klauspost/compress v1.17.4 // indirect
+	github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
+	github.com/magiconair/properties v1.8.7 // indirect
+	github.com/moby/docker-image-spec v1.3.1 // indirect
+	github.com/moby/patternmatcher v0.6.0 // indirect
+	github.com/moby/sys/sequential v0.5.0 // indirect
+	github.com/moby/sys/user v0.1.0 // indirect
+	github.com/moby/term v0.5.0 // indirect
+	github.com/morikuni/aec v1.0.0 // indirect
+	github.com/opencontainers/go-digest v1.0.0 // indirect
+	github.com/opencontainers/image-spec v1.1.0 // indirect
+	github.com/pkg/errors v0.9.1 // indirect
 	github.com/pmezard/go-difflib v1.0.0 // indirect
+	github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
 	github.com/rogpeppe/go-internal v1.11.0 // indirect
-	golang.org/x/crypto v0.23.0 // indirect
-	golang.org/x/sync v0.7.0 // indirect
-	golang.org/x/text v0.15.0 // indirect
+	github.com/shirou/gopsutil/v3 v3.23.12 // indirect
+	github.com/shoenig/go-m1cpu v0.1.6 // indirect
+	github.com/sirupsen/logrus v1.9.3 // indirect
+	github.com/tklauser/go-sysconf v0.3.12 // indirect
+	github.com/tklauser/numcpus v0.6.1 // indirect
+	github.com/yusufpapurcu/wmi v1.2.3 // indirect
+	go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect
+	go.opentelemetry.io/otel v1.24.0 // indirect
+	go.opentelemetry.io/otel/metric v1.24.0 // indirect
+	go.opentelemetry.io/otel/trace v1.24.0 // indirect
+	golang.org/x/crypto v0.31.0 // indirect
+	golang.org/x/sync v0.10.0 // indirect
+	golang.org/x/sys v0.28.0 // indirect
+	golang.org/x/text v0.21.0 // indirect
 	gopkg.in/yaml.v3 v3.0.1 // indirect
 )
diff --git a/postgres/go.sum b/postgres/go.sum
index e6a2b1e68..10e34b28d 100644
--- a/postgres/go.sum
+++ b/postgres/go.sum
@@ -1,7 +1,53 @@
-github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
+dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk=
+dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
+github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9vkmnHYOMsOr4WLk+Vo07yKIzd94sVoIqshQ4bU=
+github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8=
+github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8=
+github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
+github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
+github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
+github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM=
+github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
+github.com/containerd/containerd v1.7.18 h1:jqjZTQNfXGoEaZdW1WwPU0RqSn1Bm2Ay/KJPUuO8nao=
+github.com/containerd/containerd v1.7.18/go.mod h1:IYEk9/IO6wAPUz2bCMVUbsfXjzw5UNP5fLz4PsUygQ4=
+github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I=
+github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo=
+github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A=
+github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw=
+github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA=
+github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc=
+github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY=
+github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
+github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
+github.com/docker/docker v27.1.1+incompatible h1:hO/M4MtV36kzKldqnA37IWhebRA+LnqqcqDja6kVaKY=
+github.com/docker/docker v27.1.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
+github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c=
+github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc=
+github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
+github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
+github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
+github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
+github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
+github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=
+github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
+github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
+github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
+github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
+github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
+github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
+github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
+github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
+github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
+github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
+github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
+github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 h1:YBftPWNWd4WwGqtY2yeZL2ef8rHAxPBD8KFhJpmcqms=
+github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0/go.mod h1:YN5jB8ie0yfIUg6VvR9Kz84aCaG7AsGZnLjhHbUqwPg=
 github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
 github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
 github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9 h1:L0QtFUgDarD7Fpv9jeVMgy/+Ec0mtnmYuImjTz6dtDA=
@@ -10,26 +56,154 @@ github.com/jackc/pgx/v5 v5.6.0 h1:SWJzexBzPL5jb0GEsrPMLIsi/3jOo7RHlzTjcAeDrPY=
 github.com/jackc/pgx/v5 v5.6.0/go.mod h1:DNZ/vlrUnhWCoFGxHAG8U2ljioxukquj7utPDgtQdTw=
 github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk=
 github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
+github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
+github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
+github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4=
+github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM=
 github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
+github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
 github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
 github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
+github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
+github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
+github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4=
+github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
+github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
+github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
+github.com/mdelapenya/tlscert v0.1.0 h1:YTpF579PYUX475eOL+6zyEO3ngLTOUWck78NBuJVXaM=
+github.com/mdelapenya/tlscert v0.1.0/go.mod h1:wrbyM/DwbFCeCeqdPX/8c6hNOqQgbf0rUDErE1uD+64=
+github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0=
+github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=
+github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkVGiPk=
+github.com/moby/patternmatcher v0.6.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc=
+github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc=
+github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo=
+github.com/moby/sys/user v0.1.0 h1:WmZ93f5Ux6het5iituh9x2zAG7NFY9Aqi49jjE1PaQg=
+github.com/moby/sys/user v0.1.0/go.mod h1:fKJhFOnsCN6xZ5gSfbM6zaHGgDJMrqt9/reuj4T7MmU=
+github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0=
+github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y=
+github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
+github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
+github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
+github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
+github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug=
+github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM=
+github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
+github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
 github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw=
+github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
 github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
 github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
+github.com/shirou/gopsutil/v3 v3.23.12 h1:z90NtUkp3bMtmICZKpC4+WaknU1eXtp5vtbQ11DgpE4=
+github.com/shirou/gopsutil/v3 v3.23.12/go.mod h1:1FrWgea594Jp7qmjHUUPlJDTPgcsb9mGnXDxavtikzM=
+github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM=
+github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ=
+github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU=
+github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k=
+github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
+github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
+github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
+github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
+github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
 github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
 github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
+github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
 github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
 github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
-golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI=
-golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
-golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
-golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
-golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk=
-golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
+github.com/testcontainers/testcontainers-go v0.35.0 h1:uADsZpTKFAtp8SLK+hMwSaa+X+JiERHtd4sQAFmXeMo=
+github.com/testcontainers/testcontainers-go v0.35.0/go.mod h1:oEVBj5zrfJTrgjwONs1SsRbnBtH9OKl+IGl3UMcr2B4=
+github.com/testcontainers/testcontainers-go/modules/postgres v0.35.0 h1:eEGx9kYzZb2cNhRbBrNOCL/YPOM7+RMJiy3bB+ie0/I=
+github.com/testcontainers/testcontainers-go/modules/postgres v0.35.0/go.mod h1:hfH71Mia/WWLBgMD2YctYcMlfsbnT0hflweL1dy8Q4s=
+github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU=
+github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI=
+github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk=
+github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY=
+github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw=
+github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
+go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 h1:jq9TW8u3so/bN+JPT166wjOI6/vQPF6Xe7nMNIltagk=
+go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0/go.mod h1:p8pYQP+m5XfbZm9fxtSKAbM6oIllS7s2AfxrChvc7iw=
+go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo=
+go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0 h1:Mne5On7VWdx7omSrSSZvM4Kw7cS7NQkOOmLcgscI51U=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0/go.mod h1:IPtUMKL4O3tH5y+iXVyAXqpAwMuzC1IrxVS81rummfE=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0 h1:IeMeyr1aBvBiPVYihXIaeIZba6b8E1bYp7lbdxK8CQg=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0/go.mod h1:oVdCUtjq9MK9BlS7TtucsQwUcXcymNiEDjgDD2jMtZU=
+go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI=
+go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco=
+go.opentelemetry.io/otel/sdk v1.19.0 h1:6USY6zH+L8uMH8L3t1enZPR3WFEmSTADlqldyHtJi3o=
+go.opentelemetry.io/otel/sdk v1.19.0/go.mod h1:NedEbbS4w3C6zElbLdPJKOpJQOrGUJ+GfzpjUvI0v1A=
+go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI=
+go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU=
+go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I=
+go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
+golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
+golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
+golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ=
+golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
+golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
+golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q=
+golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
+golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
+golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44=
+golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
+golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+google.golang.org/genproto v0.0.0-20230920204549-e6e6cdab5c13 h1:vlzZttNJGVqTsRFU9AmdnrcO1Znh8Ew9kCD//yjigk0=
+google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 h1:RFiFrvy37/mpSpdySBDrUdipW/dHwsRwh3J3+A9VgT4=
+google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237/go.mod h1:Z5Iiy3jtmioajWHDGFk7CeugTyHtPvMHA4UTmUkyalE=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 h1:NnYq6UN9ReLM9/Y01KWNOWyI5xQ9kbIms5GGJVwS/Yc=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY=
+google.golang.org/grpc v1.64.1 h1:LKtvyfbX3UGVPFcGqJ9ItpVWW6oN/2XqTxfAnwRRXiA=
+google.golang.org/grpc v1.64.1/go.mod h1:hiQF4LFZelK2WKaP6W0L92zGHtiQdZxk8CrSdvyjeP0=
+google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
+google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
+gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
 gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
 gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU=
+gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU=
diff --git a/postgres/postgres_test.go b/postgres/postgres_test.go
index 80c02c42e..f87006f27 100644
--- a/postgres/postgres_test.go
+++ b/postgres/postgres_test.go
@@ -4,21 +4,82 @@ import (
 	"context"
 	"os"
 	"strconv"
+	"strings"
 	"testing"
 	"time"
 
 	"github.com/jackc/pgx/v5"
 	"github.com/stretchr/testify/require"
+	"github.com/testcontainers/testcontainers-go"
+	"github.com/testcontainers/testcontainers-go/modules/postgres"
 )
 
-var testStore = New(Config{
-	Database: os.Getenv("POSTGRES_DATABASE"),
-	Username: os.Getenv("POSTGRES_USERNAME"),
-	Password: os.Getenv("POSTGRES_PASSWORD"),
-	Reset:    true,
-})
+const (
+	// postgresImage is the default image used for running Postgres in tests.
+	postgresImage              = "docker.io/postgres:16-alpine"
+	postgresImageEnvVar string = "TEST_POSTGRES_IMAGE"
+	postgresUser        string = "username"
+	postgresPass        string = "p4ssw0rd"
+	postgresDatabase    string = "fiber"
+)
+
+func newTestConfig(t testing.TB) (Config, error) {
+	t.Helper()
+
+	ctx := context.Background()
+
+	img := postgresImage
+	if imgFromEnv := os.Getenv(postgresImageEnvVar); imgFromEnv != "" {
+		img = imgFromEnv
+	}
+
+	c, err := postgres.Run(ctx, img,
+		postgres.WithUsername(postgresUser),
+		postgres.WithPassword(postgresPass),
+		postgres.WithDatabase(postgresDatabase),
+		postgres.BasicWaitStrategies(),
+	)
+	testcontainers.CleanupContainer(t, c)
+	require.NoError(t, err)
+
+	var cfg Config
+	conn, err := c.ConnectionString(ctx, "sslmode=disable")
+	if err != nil {
+		return cfg, err
+	}
+
+	cfg = Config{
+		ConnectionURI: conn,
+		Reset:         true,
+	}
+	return cfg, nil
+}
+
+func newTestStore(t testing.TB) (*Storage, error) {
+	t.Helper()
+
+	cfg, err := newTestConfig(t)
+	if err != nil {
+		return nil, err
+	}
+
+	return newTestStoreWithConfig(t, cfg)
+}
+
+func newTestStoreWithConfig(t testing.TB, cfg Config) (*Storage, error) {
+	t.Helper()
+
+	return New(cfg), nil
+}
 
 func TestNoCreateUser(t *testing.T) {
+	cfg, err := newTestConfig(t)
+	require.NoError(t, err)
+
+	testStore, err := newTestStoreWithConfig(t, cfg)
+	require.NoError(t, err)
+	defer testStore.Close()
+
 	// Create a new user
 	// give the use usage permissions to the database (but not create)
 	ctx := context.Background()
@@ -27,10 +88,10 @@ func TestNoCreateUser(t *testing.T) {
 	username := "testuser" + strconv.Itoa(int(time.Now().UnixNano()))
 	password := "testpassword"
 
-	_, err := conn.Exec(ctx, "CREATE USER "+username+" WITH PASSWORD '"+password+"'")
+	_, err = conn.Exec(ctx, "CREATE USER "+username+" WITH PASSWORD '"+password+"'")
 	require.NoError(t, err)
 
-	_, err = conn.Exec(ctx, "GRANT CONNECT ON DATABASE "+os.Getenv("POSTGRES_DATABASE")+" TO "+username)
+	_, err = conn.Exec(ctx, "GRANT CONNECT ON DATABASE "+postgresDatabase+" TO "+username)
 	require.NoError(t, err)
 
 	_, err = conn.Exec(ctx, "GRANT USAGE ON SCHEMA public TO "+username)
@@ -45,6 +106,9 @@ func TestNoCreateUser(t *testing.T) {
 	_, err = conn.Exec(ctx, "REVOKE CREATE ON SCHEMA public FROM "+username)
 	require.NoError(t, err)
 
+	// new connection with the user and password without privileges
+	unpriviledgedURI := strings.Replace(cfg.ConnectionURI, postgresUser+":"+postgresPass, username+":"+password, 1)
+
 	t.Run("should panic if limited user tries to create table", func(t *testing.T) {
 		tableThatDoesNotExist := "public.table_does_not_exists_" + strconv.Itoa(int(time.Now().UnixNano()))
 
@@ -53,23 +117,23 @@ func TestNoCreateUser(t *testing.T) {
 			require.NotNil(t, r, "Expected a panic when creating a table without permissions")
 		}()
 
+		panicCfg := Config{
+			ConnectionURI: unpriviledgedURI,
+			Reset:         true,
+			Table:         tableThatDoesNotExist,
+		}
+
 		// This should panic since the user doesn't have CREATE permissions
-		New(Config{
-			Database: os.Getenv("POSTGRES_DATABASE"),
-			Username: username,
-			Password: password,
-			Reset:    true,
-			Table:    tableThatDoesNotExist,
-		})
+		New(panicCfg)
 	})
 
+	limitedCfg := Config{
+		ConnectionURI: unpriviledgedURI,
+		Reset:         false,
+	}
+
 	// connect to an existing table using an unprivileged user
-	limitedStore := New(Config{
-		Database: os.Getenv("POSTGRES_DATABASE"),
-		Username: username,
-		Password: password,
-		Reset:    false,
-	})
+	limitedStore := New(limitedCfg)
 
 	defer func() {
 		limitedStore.Close()
@@ -149,8 +213,12 @@ func TestNoCreateUser(t *testing.T) {
 
 }
 func Test_Should_Panic_On_Wrong_Schema(t *testing.T) {
+	testStore, err := newTestStore(t)
+	require.NoError(t, err)
+	defer testStore.Close()
+
 	// Create a test table with wrong schema
-	_, err := testStore.Conn().Exec(context.Background(), `
+	_, err = testStore.Conn().Exec(context.Background(), `
 			CREATE TABLE IF NOT EXISTS test_schema_table (
 				k  VARCHAR(64) PRIMARY KEY NOT NULL DEFAULT '',
 				v  BYTEA NOT NULL,
@@ -175,7 +243,11 @@ func Test_Postgres_Set(t *testing.T) {
 		val = []byte("doe")
 	)
 
-	err := testStore.Set(key, val, 0)
+	testStore, err := newTestStore(t)
+	require.NoError(t, err)
+	defer testStore.Close()
+
+	err = testStore.Set(key, val, 0)
 	require.NoError(t, err)
 }
 
@@ -185,7 +257,11 @@ func Test_Postgres_Set_Override(t *testing.T) {
 		val = []byte("doe")
 	)
 
-	err := testStore.Set(key, val, 0)
+	testStore, err := newTestStore(t)
+	require.NoError(t, err)
+	defer testStore.Close()
+
+	err = testStore.Set(key, val, 0)
 	require.NoError(t, err)
 
 	err = testStore.Set(key, val, 0)
@@ -198,7 +274,11 @@ func Test_Postgres_Get(t *testing.T) {
 		val = []byte("doe")
 	)
 
-	err := testStore.Set(key, val, 0)
+	testStore, err := newTestStore(t)
+	require.NoError(t, err)
+	defer testStore.Close()
+
+	err = testStore.Set(key, val, 0)
 	require.NoError(t, err)
 
 	result, err := testStore.Get(key)
@@ -213,21 +293,37 @@ func Test_Postgres_Set_Expiration(t *testing.T) {
 		exp = 1 * time.Second
 	)
 
-	err := testStore.Set(key, val, exp)
+	testStore, err := newTestStore(t)
+	require.NoError(t, err)
+	defer testStore.Close()
+
+	err = testStore.Set(key, val, exp)
 	require.NoError(t, err)
 
 	time.Sleep(1100 * time.Millisecond)
+
+	result, err := testStore.Get(key)
+	require.NoError(t, err)
+	require.Zero(t, len(result), "Key should have expired")
 }
 
 func Test_Postgres_Get_Expired(t *testing.T) {
 	key := "john"
 
+	testStore, err := newTestStore(t)
+	require.NoError(t, err)
+	defer testStore.Close()
+
 	result, err := testStore.Get(key)
 	require.NoError(t, err)
 	require.Zero(t, len(result))
 }
 
 func Test_Postgres_Get_NotExist(t *testing.T) {
+	testStore, err := newTestStore(t)
+	require.NoError(t, err)
+	defer testStore.Close()
+
 	result, err := testStore.Get("notexist")
 	require.NoError(t, err)
 	require.Zero(t, len(result))
@@ -239,7 +335,11 @@ func Test_Postgres_Delete(t *testing.T) {
 		val = []byte("doe")
 	)
 
-	err := testStore.Set(key, val, 0)
+	testStore, err := newTestStore(t)
+	require.NoError(t, err)
+	defer testStore.Close()
+
+	err = testStore.Set(key, val, 0)
 	require.NoError(t, err)
 
 	err = testStore.Delete(key)
@@ -253,7 +353,11 @@ func Test_Postgres_Delete(t *testing.T) {
 func Test_Postgres_Reset(t *testing.T) {
 	val := []byte("doe")
 
-	err := testStore.Set("john1", val, 0)
+	testStore, err := newTestStore(t)
+	require.NoError(t, err)
+	defer testStore.Close()
+
+	err = testStore.Set("john1", val, 0)
 	require.NoError(t, err)
 
 	err = testStore.Set("john2", val, 0)
@@ -274,8 +378,12 @@ func Test_Postgres_Reset(t *testing.T) {
 func Test_Postgres_GC(t *testing.T) {
 	testVal := []byte("doe")
 
+	testStore, err := newTestStore(t)
+	require.NoError(t, err)
+	defer testStore.Close()
+
 	// This key should expire
-	err := testStore.Set("john", testVal, time.Nanosecond)
+	err = testStore.Set("john", testVal, time.Nanosecond)
 	require.NoError(t, err)
 
 	testStore.gc(time.Now())
@@ -296,7 +404,11 @@ func Test_Postgres_GC(t *testing.T) {
 func Test_Postgres_Non_UTF8(t *testing.T) {
 	val := []byte("0xF5")
 
-	err := testStore.Set("0xF6", val, 0)
+	testStore, err := newTestStore(t)
+	require.NoError(t, err)
+	defer testStore.Close()
+
+	err = testStore.Set("0xF6", val, 0)
 	require.NoError(t, err)
 
 	result, err := testStore.Get("0xF6")
@@ -305,29 +417,36 @@ func Test_Postgres_Non_UTF8(t *testing.T) {
 }
 
 func Test_SslRequiredMode(t *testing.T) {
-	defer func() {
-		if recover() == nil {
-			require.Equalf(t, true, nil, "Connection was established with a `require`")
-		}
-	}()
-	_ = New(Config{
-		Reset: true,
-	})
+	require.Panics(t, func() {
+		_ = New(Config{
+			Reset: true,
+		})
+	}, "Expected panic when connecting to Postgres with SSL mode set to require")
 }
 
 func Test_Postgres_Conn(t *testing.T) {
+	testStore, err := newTestStore(t)
+	require.NoError(t, err)
+	defer testStore.Close()
+
 	require.True(t, testStore.Conn() != nil)
 }
 
 func Test_Postgres_Close(t *testing.T) {
+	testStore, err := newTestStore(t)
+	require.NoError(t, err)
+
 	require.Nil(t, testStore.Close())
 }
 
 func Benchmark_Postgres_Set(b *testing.B) {
+	testStore, err := newTestStore(b)
+	require.NoError(b, err)
+	defer testStore.Close()
+
 	b.ReportAllocs()
 	b.ResetTimer()
 
-	var err error
 	for i := 0; i < b.N; i++ {
 		err = testStore.Set("john", []byte("doe"), 0)
 	}
@@ -336,7 +455,11 @@ func Benchmark_Postgres_Set(b *testing.B) {
 }
 
 func Benchmark_Postgres_Get(b *testing.B) {
-	err := testStore.Set("john", []byte("doe"), 0)
+	testStore, err := newTestStore(b)
+	require.NoError(b, err)
+	defer testStore.Close()
+
+	err = testStore.Set("john", []byte("doe"), 0)
 	require.NoError(b, err)
 
 	b.ReportAllocs()
@@ -350,10 +473,13 @@ func Benchmark_Postgres_Get(b *testing.B) {
 }
 
 func Benchmark_Postgres_SetAndDelete(b *testing.B) {
+	testStore, err := newTestStore(b)
+	require.NoError(b, err)
+	defer testStore.Close()
+
 	b.ReportAllocs()
 	b.ResetTimer()
 
-	var err error
 	for i := 0; i < b.N; i++ {
 		_ = testStore.Set("john", []byte("doe"), 0)
 		err = testStore.Delete("john")
diff --git a/s3/go.mod b/s3/go.mod
index 9aebb441a..0d9de9fda 100644
--- a/s3/go.mod
+++ b/s3/go.mod
@@ -1,6 +1,6 @@
 module github.com/gofiber/storage/s3/v2
 
-go 1.21
+go 1.22
 
 require (
 	github.com/aws/aws-sdk-go-v2 v1.34.0
@@ -10,7 +10,7 @@ require (
 	github.com/aws/aws-sdk-go-v2/service/s3 v1.58.3
 	github.com/aws/smithy-go v1.22.2
 	github.com/stretchr/testify v1.9.0
-	github.com/testcontainers/testcontainers-go/modules/minio v0.33.0
+	github.com/testcontainers/testcontainers-go/modules/minio v0.35.0
 )
 
 require (
@@ -47,7 +47,6 @@ require (
 	github.com/gogo/protobuf v1.3.2 // indirect
 	github.com/google/uuid v1.6.0 // indirect
 	github.com/klauspost/compress v1.17.6 // indirect
-	github.com/kr/text v0.2.0 // indirect
 	github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
 	github.com/magiconair/properties v1.8.7 // indirect
 	github.com/moby/docker-image-spec v1.3.1 // indirect
@@ -64,7 +63,7 @@ require (
 	github.com/shirou/gopsutil/v3 v3.23.12 // indirect
 	github.com/shoenig/go-m1cpu v0.1.6 // indirect
 	github.com/sirupsen/logrus v1.9.3 // indirect
-	github.com/testcontainers/testcontainers-go v0.33.0 // indirect
+	github.com/testcontainers/testcontainers-go v0.35.0 // indirect
 	github.com/tklauser/go-sysconf v0.3.12 // indirect
 	github.com/tklauser/numcpus v0.6.1 // indirect
 	github.com/yusufpapurcu/wmi v1.2.3 // indirect
@@ -72,7 +71,7 @@ require (
 	go.opentelemetry.io/otel v1.24.0 // indirect
 	go.opentelemetry.io/otel/metric v1.24.0 // indirect
 	go.opentelemetry.io/otel/trace v1.24.0 // indirect
-	golang.org/x/crypto v0.24.0 // indirect
-	golang.org/x/sys v0.21.0 // indirect
+	golang.org/x/crypto v0.31.0 // indirect
+	golang.org/x/sys v0.28.0 // indirect
 	gopkg.in/yaml.v3 v3.0.1 // indirect
 )
diff --git a/s3/go.sum b/s3/go.sum
index 0ddfbae66..d5452f9b1 100644
--- a/s3/go.sum
+++ b/s3/go.sum
@@ -54,7 +54,6 @@ github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpS
 github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw=
 github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA=
 github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc=
-github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
 github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY=
 github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -152,16 +151,18 @@ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVs
 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
 github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
+github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
+github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
 github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
 github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
 github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
 github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
-github.com/testcontainers/testcontainers-go v0.33.0 h1:zJS9PfXYT5O0ZFXM2xxXfk4J5UMw/kRiISng037Gxdw=
-github.com/testcontainers/testcontainers-go v0.33.0/go.mod h1:W80YpTa8D5C3Yy16icheD01UTDu+LmXIA2Keo+jWtT8=
-github.com/testcontainers/testcontainers-go/modules/minio v0.33.0 h1:lHhjYlm0Oh+PfM03NIwCqNg2zSz9VuNTwUKi4MQfYAA=
-github.com/testcontainers/testcontainers-go/modules/minio v0.33.0/go.mod h1:3WRFF6lLI3IqXb7lvOx6OpEcH1jgs59mbzZiPTJeEJg=
+github.com/testcontainers/testcontainers-go v0.35.0 h1:uADsZpTKFAtp8SLK+hMwSaa+X+JiERHtd4sQAFmXeMo=
+github.com/testcontainers/testcontainers-go v0.35.0/go.mod h1:oEVBj5zrfJTrgjwONs1SsRbnBtH9OKl+IGl3UMcr2B4=
+github.com/testcontainers/testcontainers-go/modules/minio v0.35.0 h1:oJMrfB0hIABClRsJrVJ43zTEsCVk0JTN7RdTz9r+tk4=
+github.com/testcontainers/testcontainers-go/modules/minio v0.35.0/go.mod h1:Q7gSllC2zi78e2OF6Gwn+DXyqbxdbt6PAuaZdIPh3DQ=
 github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU=
 github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI=
 github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk=
@@ -189,8 +190,8 @@ go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v8
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
-golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI=
-golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM=
+golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
+golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
 golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
@@ -212,14 +213,14 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc
 golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
-golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws=
-golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
-golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA=
-golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0=
+golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
+golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q=
+golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
-golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
+golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
+golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
 golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44=
 golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
diff --git a/s3/init_test.go b/s3/init_test.go
index 9c9176aff..f1f97771b 100644
--- a/s3/init_test.go
+++ b/s3/init_test.go
@@ -6,7 +6,9 @@ import (
 	"testing"
 	"time"
 
+	"github.com/testcontainers/testcontainers-go"
 	"github.com/testcontainers/testcontainers-go/modules/minio"
+	"github.com/testcontainers/testcontainers-go/wait"
 )
 
 const (
@@ -35,6 +37,10 @@ func TestMain(m *testing.M) {
 		img,
 		minio.WithUsername(minioUser),
 		minio.WithPassword(minioPass),
+		testcontainers.WithWaitStrategy(
+			wait.ForListeningPort("9000/tcp"),
+			wait.ForHTTP("/minio/health/live").WithPort("9000"),
+		),
 	)
 	if err != nil {
 		panic(err)


Reviews:
user: login: coderabbitai[bot]
body: **Actionable comments posted: 0**



<details>
<summary>Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**

<details>
<summary>Commits</summary>

Files that changed from the base of the PR and between 2f1c0cbba5c9e5da8d3ad3cd3bdccfc194515a1c and 2f5263ef850096b7cccb41668f8d77f5fcc2ed6d.

</details>
<details>
<summary>Files ignored due to path filters (8)</summary>

* `mongodb/go.mod` is excluded by `!**/*.mod`
* `mongodb/go.sum` is excluded by `!**/*.sum`, `!**/*.sum`
* `mssql/go.mod` is excluded by `!**/*.mod`
* `mssql/go.sum` is excluded by `!**/*.sum`, `!**/*.sum`
* `mysql/go.mod` is excluded by `!**/*.mod`
* `mysql/go.sum` is excluded by `!**/*.sum`, `!**/*.sum`
* `postgres/go.mod` is excluded by `!**/*.mod`
* `postgres/go.sum` is excluded by `!**/*.sum`, `!**/*.sum`

</details>

<details>
<summary>Files selected for processing (9)</summary>

* .github/workflows/benchmark.yml (2 hunks)
* .github/workflows/test-mongodb.yml (2 hunks)
* .github/workflows/test-mssql.yml (2 hunks)
* .github/workflows/test-mysql.yml (2 hunks)
* .github/workflows/test-postgres.yml (2 hunks)
* mongodb/mongodb_test.go (11 hunks)
* mssql/mssql_test.go (12 hunks)
* mysql/mysql_test.go (13 hunks)
* postgres/postgres_test.go (12 hunks)

</details>











<details>
<summary>Additional comments not posted (32)</summary><blockquote>

<details>
<summary>.github/workflows/test-mysql.yml (1)</summary><blockquote>

`30-31`: **LGTM!**

The introduction of the `TEST_MYSQL_IMAGE` environment variable is a good practice to ensure consistency and reliability in the testing environment.

</blockquote></details>
<details>
<summary>.github/workflows/test-mongodb.yml (2)</summary><blockquote>

`19-20`: **LGTM!**

Updating the Go version matrix to include newer versions is a good practice to ensure compatibility and performance with the latest Go versions.

---

`30-30`: **LGTM!**

The introduction of the `TEST_MONGODB_IMAGE` environment variable is a good practice to ensure consistency and reliability in the testing environment.

</blockquote></details>
<details>
<summary>.github/workflows/test-postgres.yml (1)</summary><blockquote>

`30-31`: **LGTM!**

The introduction of the `TEST_POSTGRES_IMAGE` environment variable is a good practice to ensure consistency and reliability in the testing environment.

</blockquote></details>
<details>
<summary>.github/workflows/test-mssql.yml (1)</summary><blockquote>

`30-31`: **LGTM!**


The addition of the environment variable `TEST_MSSQL_IMAGE` is correct and aligns with the PR objective.

</blockquote></details>
<details>
<summary>.github/workflows/benchmark.yml (4)</summary><blockquote>

`118-118`: **LGTM!**


The addition of the environment variable `TEST_MONGODB_IMAGE` is correct and aligns with the PR objective.

---

`119-119`: **LGTM!**


The addition of the environment variable `TEST_MSSQL_IMAGE` is correct and aligns with the PR objective.

---

`120-120`: **LGTM!**


The addition of the environment variable `TEST_MYSQL_IMAGE` is correct and aligns with the PR objective.

---

`121-121`: **LGTM!**


The addition of the environment variable `TEST_POSTGRES_IMAGE` is correct and aligns with the PR objective.

</blockquote></details>
<details>
<summary>mongodb/mongodb_test.go (10)</summary><blockquote>

`10-10`: **LGTM!**


The import statement for `testcontainers-go/modules/mongodb` is correct and necessary for using the testcontainers-go library for MongoDB.

---

`13-19`: **LGTM!**


The constant block for MongoDB image and credentials is correctly defined and aligns with the PR objective.

---

`21-44`: **LGTM!**


The `newTestStore` function is correctly implemented and improves the isolation of tests by ensuring that each test starts with a fresh instance of the MongoDB store.

---

`53-55`: **LGTM!**


The modification of the `Test_MongoDB_Set` function to use `newTestStore` is correct and aligns with the PR objective.

---

`66-68`: **LGTM!**


The modification of the `Test_MongoDB_Set_Override` function to use `newTestStore` is correct and aligns with the PR objective.

---

`82-84`: **LGTM!**


The modification of the `Test_MongoDB_Get` function to use `newTestStore` is correct and aligns with the PR objective.

---

`100-102`: **LGTM!**


The modification of the `Test_MongoDB_Set_Expiration` function to use `newTestStore` is correct and aligns with the PR objective.

---

`112-114`: **LGTM!**


The modification of the `Test_MongoDB_Get_Expired` function to use `newTestStore` is correct and aligns with the PR objective.

---

`121-123`: **LGTM!**


The modification of the `Test_MongoDB_Get_NotExist` function to use `newTestStore` is correct and aligns with the PR objective.

---

`135-137`: **LGTM!**


The modification of the `Test_MongoDB_Delete` function to use `newTestStore` is correct and aligns with the PR objective.

</blockquote></details>
<details>
<summary>mssql/mssql_test.go (4)</summary><blockquote>

`4-11`: **LGTM!**


The import statements are correct and necessary for the functionality.

---

`14-21`: **LGTM!**


The constants improve configurability and readability.

---

`23-51`: **LGTM!**


The function is correctly implemented and ensures each test runs in isolation with a fresh database connection.

---

Line range hint `59-264`: **LGTM!**


The updates ensure that each test retrieves its own instance of the storage, improving test isolation and reliability.

</blockquote></details>
<details>
<summary>mysql/mysql_test.go (5)</summary><blockquote>

`4-11`: **LGTM!**


The import statements are correct and necessary for the functionality.

---

`14-21`: **LGTM!**


The constants improve configurability and readability.

---

`23-39`: **LGTM!**


The function is correctly implemented and ensures each test runs in isolation with a fresh database connection.

---

`41-57`: **LGTM!**


The function is correctly implemented and ensures the MySQL container is properly configured and started.

---

Line range hint `59-294`: **LGTM!**


The updates ensure that each test retrieves its own instance of the storage, improving test isolation and reliability.

</blockquote></details>
<details>
<summary>postgres/postgres_test.go (4)</summary><blockquote>

Line range hint `4-13`: **LGTM!**


The import statements are correct and necessary for the functionality.

---

`16-23`: **LGTM!**


The constants improve configurability and readability.

---

`25-56`: **LGTM!**


The function is correctly implemented and ensures each test runs in isolation with a fresh database connection.

---

Line range hint `64-282`: **LGTM!**


The updates ensure that each test retrieves its own instance of the storage, improving test isolation and reliability.

</blockquote></details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2024-08-29T12:52:21Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 0**



<details>
<summary>Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**

<details>
<summary>Commits</summary>

Files that changed from the base of the PR and between 2f5263ef850096b7cccb41668f8d77f5fcc2ed6d and 689759c035b0e32e16dc26429a590b9f64329ffb.

</details>


<details>
<summary>Files selected for processing (1)</summary>

* .github/workflows/test-mongodb.yml (2 hunks)

</details>








<details>
<summary>Files skipped from review as they are similar to previous changes (1)</summary>

* .github/workflows/test-mongodb.yml

</details>




</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2024-08-29T12:56:18Z
user: login: gaby
state: COMMENTED
author_association: MEMBER
submitted_at: 2024-08-29T12:57:57Z
user: login: gaby
state: COMMENTED
author_association: MEMBER
submitted_at: 2024-08-29T12:58:06Z
user: login: gaby
state: COMMENTED
author_association: MEMBER
submitted_at: 2024-08-29T12:58:20Z
user: login: gaby
body: Small comment
state: COMMENTED
author_association: MEMBER
submitted_at: 2024-08-29T12:59:14Z
user: login: gaby
state: COMMENTED
author_association: MEMBER
submitted_at: 2024-08-29T12:59:43Z
user: login: mdelapenya
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2024-08-29T13:09:32Z
user: login: mdelapenya
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2024-08-29T13:10:04Z
user: login: gaby
state: COMMENTED
author_association: MEMBER
submitted_at: 2024-08-29T13:14:53Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 0**



<details>
<summary>Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**

<details>
<summary>Commits</summary>

Files that changed from the base of the PR and between 689759c035b0e32e16dc26429a590b9f64329ffb and de8f798d6eca21ae8b4796cc5ad13b8874cdbf1a.

</details>
<details>
<summary>Files ignored due to path filters (2)</summary>

* `mongodb/go.mod` is excluded by `!**/*.mod`
* `postgres/go.mod` is excluded by `!**/*.mod`

</details>

<details>
<summary>Files selected for processing (3)</summary>

* .github/workflows/test-mssql.yml (2 hunks)
* .github/workflows/test-mysql.yml (2 hunks)
* .github/workflows/test-postgres.yml (2 hunks)

</details>








<details>
<summary>Files skipped from review as they are similar to previous changes (2)</summary>

* .github/workflows/test-mssql.yml
* .github/workflows/test-postgres.yml

</details>


<details>
<summary>Additional comments not posted (4)</summary><blockquote>

<details>
<summary>.github/workflows/test-mysql.yml (4)</summary><blockquote>

`19-19`: **LGTM!**


The addition of Go version 1.22.x to the matrix is appropriate.

---

`20-20`: **LGTM!**


The addition of Go version 1.23.x to the matrix is appropriate.

---

`30-30`: **LGTM!**


Setting the `TEST_MYSQL_IMAGE` environment variable to `docker.io/mysql:9` ensures consistency and reliability in the testing environment.

---

`31-31`: **LGTM!**


Running the tests with the specified MySQL image is appropriate.

</blockquote></details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2024-08-29T14:38:47Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 1**



<details>
<summary>Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**

<details>
<summary>Commits</summary>

Files that changed from the base of the PR and between c80f1269f02074809a6e316954cd550c6eebfdf0 and 4d7a1724001cc0f1ebc651e03e94dd5f828bd700.

</details>
<details>
<summary>Files ignored due to path filters (8)</summary>

* `mongodb/go.mod` is excluded by `!**/*.mod`
* `mongodb/go.sum` is excluded by `!**/*.sum`, `!**/*.sum`
* `mssql/go.mod` is excluded by `!**/*.mod`
* `mssql/go.sum` is excluded by `!**/*.sum`, `!**/*.sum`
* `mysql/go.mod` is excluded by `!**/*.mod`
* `mysql/go.sum` is excluded by `!**/*.sum`, `!**/*.sum`
* `postgres/go.mod` is excluded by `!**/*.mod`
* `postgres/go.sum` is excluded by `!**/*.sum`, `!**/*.sum`

</details>

<details>
<summary>Files selected for processing (3)</summary>

* .github/workflows/benchmark.yml (1 hunks)
* .github/workflows/test-mssql.yml (2 hunks)
* mssql/mssql_test.go (12 hunks)

</details>













<details>
<summary>Additional comments not posted (4)</summary><blockquote>

<details>
<summary>.github/workflows/test-mssql.yml (2)</summary><blockquote>

`20-20`: **Go version update approved.**

Adding Go version `1.22.x` to the test matrix ensures compatibility with the latest Go release.

---

`30-31`: **Environment variable `TEST_MSSQL_IMAGE` set appropriately.**

Defining `TEST_MSSQL_IMAGE` with the specified image ensures consistency across testing environments.

</blockquote></details>
<details>
<summary>.github/workflows/benchmark.yml (1)</summary><blockquote>

`115-118`: **Database image environment variables configured correctly.**

The addition of `TEST_MONGODB_IMAGE`, `TEST_MSSQL_IMAGE`, `TEST_MYSQL_IMAGE`, and `TEST_POSTGRES_IMAGE` environment variables specifies the database images for testing, enhancing consistency and reproducibility.

</blockquote></details>
<details>
<summary>mssql/mssql_test.go (1)</summary><blockquote>

`23-51`: **Well-implemented `newTestStore` function enhances test isolation.**

The `newTestStore` function provides each test with an independent storage instance, improving test reliability and avoiding shared state.

</blockquote></details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2024-09-18T14:25:29Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 1**



<details>
<summary>Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**

<details>
<summary>Commits</summary>

Files that changed from the base of the PR and between 4d7a1724001cc0f1ebc651e03e94dd5f828bd700 and 1bb4d922e9403961f145fd57599c7fb8cdf86776.

</details>


<details>
<summary>Files selected for processing (7)</summary>

* clickhouse/clickhouse_test.go (1 hunks)
* couchbase/couchbase_test.go (10 hunks)
* minio/minio_test.go (15 hunks)
* mongodb/mongodb_test.go (11 hunks)
* mssql/mssql_test.go (12 hunks)
* mysql/mysql_test.go (13 hunks)
* postgres/postgres_test.go (12 hunks)

</details>













<details>
<summary>Additional comments not posted (75)</summary><blockquote>

<details>
<summary>couchbase/couchbase_test.go (11)</summary><blockquote>

`59-59`: **Good practice: Ensuring resource cleanup with `defer testStore.Close()`**

Adding `defer testStore.Close()` ensures that the test store is properly closed after the test `TestSetCouchbase_ShouldReturnNoError` executes, preventing potential resource leaks.

---

`69-69`: **Good practice: Ensuring resource cleanup in `TestGetCouchbase_ShouldReturnNil_WhenDocumentNotFound`**

Including `defer testStore.Close()` guarantees that resources are released after the test, enhancing test reliability.

---

`80-80`: **Good practice: Resource cleanup in `TestSetAndGet_GetShouldReturn_SetValueWithoutError`**

The addition of `defer testStore.Close()` ensures that the test store is closed properly, preventing resource leaks.

---

`94-94`: **Good practice: Proper resource management in `TestSetAndGet_GetShouldReturnNil_WhenTTLExpired`**

Using `defer testStore.Close()` aids in cleaning up resources after the test execution.

---

`110-110`: **Good practice: Ensuring resource cleanup in `TestSetAndDelete_DeleteShouldReturn_NoError`**

Adding `defer testStore.Close()` ensures that the test store is properly closed, enhancing resource management.

---

`125-125`: **Good practice: Resource cleanup in `TestSetAndReset_ResetShouldReturn_NoError`**

Including `defer testStore.Close()` helps prevent resource leaks by ensuring the test store is closed after the test.

---

`140-140`: **Good practice: Proper closure in `TestClose_CloseShouldReturn_NoError`**

Adding `defer testStore.Close()` ensures that resources are released appropriately after the test execution.

---

`149-149`: **Good practice: Ensuring resource cleanup in `TestGetConn_ReturnsNotNil`**

Using `defer testStore.Close()` enhances resource management by closing the test store after the test.

---

`157-157`: **Good practice: Resource cleanup in benchmark `Benchmark_Couchbase_Set`**

Including `defer testStore.Close()` ensures that resources are properly released after the benchmark execution.

---

`172-172`: **Good practice: Proper resource management in benchmark `Benchmark_Couchbase_Get`**

Adding `defer testStore.Close()` helps prevent resource leaks during benchmark execution.

---

`190-190`: **Good practice: Resource cleanup in benchmark `Benchmark_Couchbase_SetAndDelete`**

Using `defer testStore.Close()` ensures that the test store is closed after the benchmark completes.

</blockquote></details>
<details>
<summary>mongodb/mongodb_test.go (14)</summary><blockquote>

`21-44`: **Well-designed `newTestStore` function for test isolation**

The `newTestStore` function effectively initializes a MongoDB test container using Testcontainers, enhancing test isolation and reliability by providing a fresh instance for each test.

---

`53-56`: **Proper initialization and cleanup in `Test_MongoDB_Set`**

Initializing the test store with `newTestStore(t)` and adding `defer testStore.Close()` ensures each test is isolated and that resources are properly released.

---

`67-70`: **Consistent test setup in `Test_MongoDB_Set_Override`**

Using the new test store initialization pattern enhances test reliability and resource management.

---

`84-87`: **Improved resource management in `Test_MongoDB_Get`**

Including `defer testStore.Close()` ensures that resources are cleaned up after the test execution.

---

`103-106`: **Proper test isolation in `Test_MongoDB_Set_Expiration`**

Initializing a fresh test store and deferring its closure helps prevent interference between tests.

---

`116-119`: **Resource cleanup in `Test_MongoDB_Get_Expired`**

Adding `defer testStore.Close()` ensures that the test store is properly closed after the test.

---

`126-129`: **Consistent resource management in `Test_MongoDB_Get_NotExist`**

Including `defer testStore.Close()` enhances resource cleanup post-test execution.

---

`141-144`: **Proper closure of test store in `Test_MongoDB_Delete`**

Using `defer testStore.Close()` ensures resources are released after the test runs.

---

`159-162`: **Resource cleanup in `Test_MongoDB_Reset`**

Adding `defer testStore.Close()` aids in preventing resource leaks.

---

`182-185`: **Proper resource management in `Test_MongoDB_Close`**

Deferring `testStore.Close()` ensures that resources are released appropriately.

---

`190-193`: **Consistent cleanup in `Test_MongoDB_Conn`**

Including `defer testStore.Close()` enhances resource management after the test execution.

---

`198-201`: **Resource cleanup in benchmark `Benchmark_MongoDB_Set`**

Adding `defer testStore.Close()` ensures that resources are properly released after the benchmark.

---

`213-216`: **Proper resource management in benchmark `Benchmark_MongoDB_Get`**

Using `defer testStore.Close()` helps prevent resource leaks during benchmark execution.

---

`231-234`: **Resource cleanup in benchmark `Benchmark_MongoDB_SetAndDelete`**

Including `defer testStore.Close()` ensures that the test store is closed after the benchmark completes.

</blockquote></details>
<details>
<summary>clickhouse/clickhouse_test.go (1)</summary><blockquote>

`70-75`: **Proper assignment and resource cleanup in `Test_Connection`**

Assigning the result of `getTestConnection` to `client` and deferring `client.Close()` ensures that the connection is utilized and properly closed after the test, preventing resource leaks.

</blockquote></details>
<details>
<summary>minio/minio_test.go (15)</summary><blockquote>

`67-67`: **Good practice: Adding `defer testStore.Close()` in `Test_Get`**

Including `defer testStore.Close()` ensures that resources are properly released after the test execution, preventing potential leaks.

---

`88-88`: **Resource cleanup in `Test_Get_Empty_Key`**

Adding `defer testStore.Close()` enhances resource management by closing the test store after the test.

---

`102-102`: **Proper resource management in `Test_Get_Not_Exists_Key`**

Using `defer testStore.Close()` ensures that resources are released appropriately after the test.

---

`116-116`: **Consistent cleanup in `Test_Get_Not_Exists_Bucket`**

Adding `defer testStore.Close()` helps prevent resource leaks by closing the test store.

---

`135-135`: **Good practice: Ensuring resource cleanup in `Test_Set`**

Including `defer testStore.Close()` ensures proper resource management.

---

`149-149`: **Resource management in `Test_Set_Empty_Key`**

Adding `defer testStore.Close()` ensures that resources are released after the test execution.

---

`166-166`: **Proper closure in `Test_Set_Not_Exists_Bucket`**

Using `defer testStore.Close()` enhances resource cleanup post-test.

---

`184-184`: **Resource cleanup in `Test_Delete`**

Including `defer testStore.Close()` ensures that the test store is properly closed after the test.

---

`201-201`: **Consistent resource management in `Test_Delete_Empty_Key`**

Adding `defer testStore.Close()` helps prevent resource leaks.

---

`215-215`: **Proper resource cleanup in `Test_Delete_Not_Exists_Bucket`**

Using `defer testStore.Close()` ensures resources are released appropriately.

---

`233-233`: **Resource management in `Test_Reset`**

Including `defer testStore.Close()` enhances test reliability by closing resources after execution.

---

`252-252`: **Good practice: Ensuring resource cleanup in `Test_Close`**

Adding `defer testStore.Close()` ensures that resources are properly released.

---

`263-263`: **Resource cleanup in benchmark `Benchmark_Minio_Set`**

Including `defer testStore.Close()` ensures proper resource management during benchmarks.

---

`275-275`: **Proper resource management in benchmark `Benchmark_Minio_Get`**

Adding `defer testStore.Close()` helps prevent resource leaks during benchmark execution.

---

`293-293`: **Resource cleanup in benchmark `Benchmark_Minio_SetAndDelete`**

Using `defer testStore.Close()` ensures that the test store is closed after the benchmark completes.

</blockquote></details>
<details>
<summary>mssql/mssql_test.go (16)</summary><blockquote>

`23-51`: **Well-implemented `newTestStore` function for MSSQL test setup**

The `newTestStore` function correctly initializes a MSSQL test container using Testcontainers, enhancing test isolation and ensuring each test operates with a fresh database instance.

---

`59-62`: **Proper initialization and cleanup in `Test_MSSQL_Set`**

Using `newTestStore(t)` and deferring `testStore.Close()` ensures tests are isolated and resources are properly managed.

---

`73-76`: **Consistent test setup in `Test_MSSQL_Set_Override`**

Adding `defer testStore.Close()` enhances resource management, consistent with previous test functions.

---

`90-93`: **Resource cleanup in `Test_MSSQL_Get`**

Including `defer testStore.Close()` ensures proper resource release after test execution.

---

`109-112`: **Proper resource management in `Test_MSSQL_Set_Expiration`**

Deferring `testStore.Close()` aids in resource cleanup.

---

`122-125`: **Resource cleanup in `Test_MSSQL_Get_Expired`**

Adding `defer testStore.Close()` ensures proper closure of the test store.

---

`132-135`: **Consistent resource management in `Test_MSSQL_Get_NotExist`**

Using `defer testStore.Close()` enhances test reliability.

---

`147-150`: **Resource cleanup in `Test_MSSQL_Delete`**

Including `defer testStore.Close()` ensures resources are released appropriately.

---

`165-168`: **Proper resource management in `Test_MSSQL_Reset`**

Deferring `testStore.Close()` aids in preventing resource leaks.

---

`190-193`: **Resource cleanup in `Test_MSSQL_GC`**

Adding `defer testStore.Close()` ensures resources are properly released after the test.

---

`216-219`: **Proper closure in `Test_MSSQL_Non_UTF8`**

Using `defer testStore.Close()` enhances resource management.

---

`244-247`: **Resource cleanup in `Test_MSSQL_Close`**

Including `defer testStore.Close()` ensures proper resource release.

---

`252-255`: **Consistent resource management in `Test_MSSQL_Conn`**

Adding `defer testStore.Close()` ensures resources are properly closed.

---

`260-263`: **Resource cleanup in benchmark `Benchmark_MSSQL_Set`**

Deferring `testStore.Close()` prevents resource leaks during benchmark execution.

---

`275-278`: **Proper resource management in benchmark `Benchmark_MSSQL_Get`**

Using `defer testStore.Close()` ensures resources are released after the benchmark.

---

`293-296`: **Resource cleanup in benchmark `Benchmark_MSSQL_SetAndDelete`**

Including `defer testStore.Close()` helps prevent resource leaks in benchmarks.

</blockquote></details>
<details>
<summary>mysql/mysql_test.go (18)</summary><blockquote>

`23-39`: **Well-structured `newTestStore` function for MySQL test setup**

The `newTestStore` function effectively initializes a MySQL test container using Testcontainers, improving test isolation by providing a fresh database instance for each test.

---

`41-57`: **Proper container management in `mustStartMySQL` function**

The `mustStartMySQL` function correctly starts a MySQL container with specified configurations, enhancing the reliability of the testing environment.

---

`59-70`: **Improved test initialization in `Test_MYSQL_New`**

Initializing the test store using the new pattern and handling errors appropriately enhances test reliability.

---

`88-91`: **Proper resource management in `Test_MYSQL_Set`**

Using `newTestStore(t)` and deferring `testStore.Close()` ensures resources are managed correctly.

---

`102-105`: **Consistent test setup in `Test_MYSQL_Set_Override`**

Including `defer testStore.Close()` aids in resource cleanup after the test execution.

---

`119-122`: **Resource cleanup in `Test_MYSQL_Get`**

Adding `defer testStore.Close()` ensures that the test store is properly closed.

---

`138-141`: **Proper resource management in `Test_MYSQL_Set_Expiration`**

Deferring `testStore.Close()` helps in resource cleanup post-test execution.

---

`151-154`: **Resource cleanup in `Test_MYSQL_Get_Expired`**

Including `defer testStore.Close()` ensures resources are properly released.

---

`161-164`: **Consistent resource management in `Test_MYSQL_Get_NotExist`**

Adding `defer testStore.Close()` enhances resource cleanup.

---

`176-179`: **Proper resource management in `Test_MYSQL_Delete`**

Using `defer testStore.Close()` ensures the test store is closed after the test.

---

`194-197`: **Resource cleanup in `Test_MYSQL_Reset`**

Deferring `testStore.Close()` aids in preventing resource leaks.

---

`220-223`: **Resource management in `Test_MYSQL_GC`**

Including `defer testStore.Close()` ensures resources are released appropriately after the test.

---

`245-248`: **Proper closure in `Test_MYSQL_Non_UTF8`**

Using `defer testStore.Close()` ensures proper resource cleanup.

---

`258-261`: **Resource cleanup in `Test_MYSQL_Close`**

Adding `defer testStore.Close()` enhances resource management post-test execution.

---

`266-269`: **Consistent resource management in `Test_MYSQL_Conn`**

Deferring `testStore.Close()` ensures that resources are properly released.

---

`274-277`: **Resource cleanup in benchmark `Benchmark_MYSQL_Set`**

Using `defer testStore.Close()` helps prevent resource leaks during benchmark execution.

---

`289-292`: **Proper resource management in benchmark `Benchmark_MYSQL_Get`**

Including `defer testStore.Close()` ensures resources are released after the benchmark.

---

`307-310`: **Resource cleanup in benchmark `Benchmark_MYSQL_SetAndDelete`**

Adding `defer testStore.Close()` ensures the test store is closed after the benchmark completes.

</blockquote></details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2024-09-18T15:04:58Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 2**



<details>
<summary>Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**

<details>
<summary>Commits</summary>

Files that changed from the base of the PR and between 1bb4d922e9403961f145fd57599c7fb8cdf86776 and f962d6488570995a3fed7ffc8a87793acbbc0e3d.

</details>


<details>
<summary>Files selected for processing (7)</summary>

* clickhouse/clickhouse_test.go (2 hunks)
* couchbase/couchbase_test.go (11 hunks)
* minio/minio_test.go (16 hunks)
* mongodb/mongodb_test.go (11 hunks)
* mssql/mssql_test.go (12 hunks)
* mysql/mysql_test.go (13 hunks)
* postgres/postgres_test.go (12 hunks)

</details>








<details>
<summary>Files skipped from review due to trivial changes (1)</summary>

* minio/minio_test.go

</details>

<details>
<summary>Files skipped from review as they are similar to previous changes (3)</summary>

* clickhouse/clickhouse_test.go
* couchbase/couchbase_test.go
* mssql/mssql_test.go

</details>


<details>
<summary>Additional comments not posted (2)</summary><blockquote>

<details>
<summary>mongodb/mongodb_test.go (1)</summary><blockquote>

`21-51`: **Great job on enhancing test isolation with `newTestStore`!**

The `newTestStore` function effectively encapsulates the setup and teardown of the MongoDB test store using Testcontainers. The use of `t.Cleanup` ensures proper resource cleanup, preventing resource leaks. This change improves test reliability and maintains clean test environments.

</blockquote></details>
<details>
<summary>postgres/postgres_test.go (1)</summary><blockquote>

`35-50`: **Excellent resource cleanup with `t.Cleanup`**

The implementation of `t.Cleanup` to terminate the PostgreSQL container ensures that resources are properly cleaned up after tests, preventing potential resource leaks.

</blockquote></details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2024-09-18T20:26:06Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 1**

<details>
<summary>🧹 Outside diff range and nitpick comments (1)</summary><blockquote>

<details>
<summary>mssql/mssql_test.go (1)</summary><blockquote>

Line range hint `227-239`: **Simplify panic handling in `Test_SslRequiredMode` using `require.Panics`**

The current implementation manually handles panic recovery, which can be simplified for clarity and readability. Use `require.Panics` to assert that a panic occurs as expected.



Apply this diff to simplify the test:

```diff
 func Test_SslRequiredMode(t *testing.T) {
-	defer func() {
-		if recover() == nil {
-			require.Equalf(t, true, nil, "Connection was established with a `require`")
-		}
-	}()
-	_ = New(Config{
-		Database: "fiber",
-		Username: "username",
-		Password: "password",
-		Reset:    true,
-		SslMode:  "require",
-	})
+	require.Panics(t, func() {
+		_ = New(Config{
+			Database: "fiber",
+			Username: "username",
+			Password: "password",
+			Reset:    true,
+			SslMode:  "require",
+		})
+	}, "Expected panic when connecting with SslMode `require`")
 }
```

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between a4849c83f764239e6bf4d307696ee104dfdbf4d2 and 8ee81305a135befa931d0260e2dfd42c9b7ef352.

</details>

<details>
<summary>⛔ Files ignored due to path filters (20)</summary>

* `.github/workflows/benchmark.yml` is excluded by `!**/*.yml`
* `.github/workflows/test-clickhouse.yml` is excluded by `!**/*.yml`
* `.github/workflows/test-mongodb.yml` is excluded by `!**/*.yml`
* `.github/workflows/test-mssql.yml` is excluded by `!**/*.yml`
* `.github/workflows/test-mysql.yml` is excluded by `!**/*.yml`
* `.github/workflows/test-postgres.yml` is excluded by `!**/*.yml`
* `clickhouse/go.mod` is excluded by `!**/*.mod`
* `clickhouse/go.sum` is excluded by `!**/*.sum`, `!**/*.sum`
* `couchbase/go.mod` is excluded by `!**/*.mod`
* `couchbase/go.sum` is excluded by `!**/*.sum`, `!**/*.sum`
* `minio/go.mod` is excluded by `!**/*.mod`
* `minio/go.sum` is excluded by `!**/*.sum`, `!**/*.sum`
* `mongodb/go.mod` is excluded by `!**/*.mod`
* `mongodb/go.sum` is excluded by `!**/*.sum`, `!**/*.sum`
* `mssql/go.mod` is excluded by `!**/*.mod`
* `mssql/go.sum` is excluded by `!**/*.sum`, `!**/*.sum`
* `mysql/go.mod` is excluded by `!**/*.mod`
* `mysql/go.sum` is excluded by `!**/*.sum`, `!**/*.sum`
* `postgres/go.mod` is excluded by `!**/*.mod`
* `postgres/go.sum` is excluded by `!**/*.sum`, `!**/*.sum`

</details>

<details>
<summary>📒 Files selected for processing (1)</summary>

* `mssql/mssql_test.go` (12 hunks)

</details>

<details>
<summary>🔇 Additional comments (15)</summary>

<details>
<summary>mssql/mssql_test.go (15)</summary>

`64-67`: **Proper initialization and cleanup of `testStore`**

The `testStore` is correctly initialized using `newTestStore(t)`, and resources are properly released with `defer testStore.Close()`. This ensures isolation and prevents resource leaks in the test.

---

`78-81`: **Proper initialization and cleanup of `testStore`**

The `testStore` is correctly initialized and closed in `Test_MSSQL_Set_Override`. Resource management is handled appropriately.

---

`95-98`: **Proper initialization and cleanup of `testStore`**

The test setup in `Test_MSSQL_Get` is correctly handled.

---

`114-117`: **Proper initialization and cleanup of `testStore`**

The expiration test is set up correctly, with appropriate use of `time.Sleep` to allow the key to expire.

---

`127-130`: **Proper initialization and cleanup of `testStore`**

`Test_MSSQL_Get_Expired` correctly checks for expired keys.

---

`137-140`: **Proper initialization and cleanup of `testStore`**

`Test_MSSQL_Get_NotExist` correctly handles non-existent keys.

---

`152-155`: **Proper initialization and cleanup of `testStore`**

`Test_MSSQL_Delete` correctly tests the deletion of keys.

---

`170-173`: **Proper initialization and cleanup of `testStore`**

`Test_MSSQL_Reset` correctly tests the reset functionality.

---

`195-198`: **Proper initialization and cleanup of `testStore`**

`Test_MSSQL_GC` correctly tests garbage collection of expired keys.

---

`221-224`: **Proper initialization and cleanup of `testStore`**

`Test_MSSQL_Non_UTF8` correctly handles non-UTF8 values.

---

`249-251`: **Ensure `testStore` is closed in `Test_MSSQL_Close`**

The `testStore` is initialized but not deferred for closure. Since this test specifically tests the `Close` method, it's acceptable. However, ensure that any resources are properly cleaned up.

---

`256-259`: **Proper initialization and cleanup of `testStore`**

`Test_MSSQL_Conn` correctly tests the connection retrieval.

---

`264-267`: **Proper initialization and cleanup of `testStore` in benchmarks**

`Benchmark_MSSQL_Set` is correctly set up with resource management.

---

`279-282`: **Proper initialization and cleanup of `testStore` in benchmarks**

`Benchmark_MSSQL_Get` is correctly set up.

---

`297-300`: **Proper initialization and cleanup of `testStore` in benchmarks**

`Benchmark_MSSQL_SetAndDelete` correctly initializes and cleans up `testStore`.

</details>

</details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2024-12-11T17:08:27Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 2**

<details>
<summary>🧹 Outside diff range and nitpick comments (1)</summary><blockquote>

<details>
<summary>postgres/postgres_test.go (1)</summary><blockquote>

`28-34`: **Use a cancellable context for better resource management**

Currently, `newTestStore` uses `context.Background()`, which is not cancellable. To allow better control over resource cleanup and prevent potential context leaks, consider using a cancellable context such as `context.WithTimeout` or `context.WithCancel`.



Apply this diff to implement a cancellable context:

```diff
 func newTestStore(t testing.TB) (*Storage, error) {
 	t.Helper()

-	ctx := context.Background()
+	ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
+	defer cancel()

 	img := postgresImage
```

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 8ee81305a135befa931d0260e2dfd42c9b7ef352 and 8cb7bc56b29103d9f5565eb24365d084edfd433c.

</details>

<details>
<summary>⛔ Files ignored due to path filters (1)</summary>

* `mssql/go.mod` is excluded by `!**/*.mod`

</details>

<details>
<summary>📒 Files selected for processing (2)</summary>

* `mssql/mssql_test.go` (12 hunks)
* `postgres/postgres_test.go` (12 hunks)

</details>

<details>
<summary>🔇 Additional comments (1)</summary>

<details>
<summary>mssql/mssql_test.go (1)</summary>

`33-34`: **Use a cancellable context for better resource management**

Consider using a cancellable context like `context.WithTimeout` to prevent potential context leaks and allow better control over resource cleanup.



Apply this diff:

```diff
 func newTestStore(t testing.TB) (*Storage, error) {
 	t.Helper()

+	ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
+	defer cancel()
-	ctx := context.Background()
```

</details>

</details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2024-12-12T05:44:24Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 1**

<details>
<summary>🧹 Outside diff range and nitpick comments (2)</summary><blockquote>

<details>
<summary>mssql/mssql_test.go (2)</summary><blockquote>

`14-21`: **Consider adding version constraints documentation**

The MSSQL image version is hardcoded to a specific version. Consider documenting version compatibility requirements and testing strategy for future upgrades.

Add a comment block explaining:
- Minimum supported version
- Version upgrade policy
- Testing requirements for version changes

---

Line range hint `57-307`: **Add stress tests for production-like scenarios**

Consider adding the following test cases to better simulate production conditions:
1. Concurrent operations test
2. Large dataset handling
3. Connection pool exhaustion scenarios


Example concurrent test:
```go
func Test_MSSQL_Concurrent_Operations(t *testing.T) {
    testStore, err := newTestStore(t)
    require.NoError(t, err)
    defer testStore.Close()

    const goroutines = 10
    var wg sync.WaitGroup
    wg.Add(goroutines)

    for i := 0; i < goroutines; i++ {
        go func(id int) {
            defer wg.Done()
            key := fmt.Sprintf("key-%d", id)
            value := []byte(fmt.Sprintf("value-%d", id))
            
            err := testStore.Set(key, value, 0)
            require.NoError(t, err)
            
            result, err := testStore.Get(key)
            require.NoError(t, err)
            require.Equal(t, value, result)
        }(i)
    }
    wg.Wait()
}
```

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 8cb7bc56b29103d9f5565eb24365d084edfd433c and 4f1577ad2ca60cf1994100f46e995dfea088cd02.

</details>

<details>
<summary>⛔ Files ignored due to path filters (2)</summary>

* `.github/workflows/benchmark.yml` is excluded by `!**/*.yml`
* `mssql/go.mod` is excluded by `!**/*.mod`

</details>

<details>
<summary>📒 Files selected for processing (1)</summary>

* `mssql/mssql_test.go` (12 hunks)

</details>

<details>
<summary>🔇 Additional comments (1)</summary>

<details>
<summary>mssql/mssql_test.go (1)</summary>

`23-56`: **Enhance error handling test coverage**

The `newTestStore` function should include tests for database connection failures and retry mechanisms.

Let's verify the current error handling coverage:



Consider adding:
1. Test case for invalid connection string
2. Test case for network timeouts
3. Retry mechanism for transient failures

</details>

</details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2024-12-12T10:12:06Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 0**

<details>
<summary>🧹 Outside diff range and nitpick comments (4)</summary><blockquote>

<details>
<summary>mssql/mssql_test.go (4)</summary><blockquote>

`14-21`: **LGTM! Well-structured constants with clear documentation.**

The constants are well-organized and documented. The inclusion of an environment variable override for the MSSQL image provides good flexibility for testing.


Consider adding a comment explaining the significance of the default password complexity, as it might not be immediately obvious why "MsSql!1234" was chosen (it meets MSSQL's password complexity requirements).

---

`234-242`: **Enhance SSL mode test coverage**

The SSL mode test could be more comprehensive by testing different SSL modes and connection scenarios.

Consider adding tests for:
1. Valid SSL mode configurations
2. Different SSL mode options
3. Invalid certificate scenarios

---

Line range hint `261-290`: **Add concurrent operation benchmarks**

The current benchmarks test single operations, but it would be valuable to test concurrent operations to ensure thread safety.

Consider adding:
1. Concurrent Set operations benchmark
2. Concurrent Get operations benchmark
3. Mixed concurrent operations benchmark

---

`23-56`: **Add error path test coverage**

The `newTestStore` function has error handling, but there are no tests for these error paths.

Consider adding tests for:
1. Invalid image name
2. Container startup failures
3. Connection string retrieval failures

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 4f1577ad2ca60cf1994100f46e995dfea088cd02 and b074e83e98adfdcbb968e3297b84a051aa647f3e.

</details>

<details>
<summary>⛔ Files ignored due to path filters (2)</summary>

* `.github/workflows/benchmark.yml` is excluded by `!**/*.yml`
* `.github/workflows/test-mssql.yml` is excluded by `!**/*.yml`

</details>

<details>
<summary>📒 Files selected for processing (1)</summary>

* `mssql/mssql_test.go` (12 hunks)

</details>

<details>
<summary>🔇 Additional comments (3)</summary>

<details>
<summary>mssql/mssql_test.go (3)</summary>

`31-32`: _:hammer_and_wrench: Refactor suggestion_

**Add context timeout for container operations**

Using `context.Background()` without a timeout could lead to hanging tests if container operations take too long.

```diff
-ctx := context.Background()
+ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
+defer cancel()
```




> Likely invalid or redundant comment.

---

`114-121`: _:hammer_and_wrench: Refactor suggestion_

**Verify key expiration in the test**

The test sets a key with expiration but doesn't verify that the key has actually expired.

```diff
 err = testStore.Set(key, val, exp)
 require.NoError(t, err)

 time.Sleep(1100 * time.Millisecond)
+
+// Verify the key has expired
+result, err := testStore.Get(key)
+require.NoError(t, err)
+require.Zero(t, len(result))
```




> Likely invalid or redundant comment.

---

`34-37`: _:hammer_and_wrench: Refactor suggestion_

**Add container health check and configuration options**

The container setup should include health checks and proper configuration for reliable test initialization.

```diff
 c, err := mssql.Run(ctx, img,
     mssql.WithPassword(mssqlPass),
     mssql.WithAcceptEULA(),
+    mssql.WithWaitStrategy(wait.ForSQL(1433).WithStartupTimeout(30*time.Second)),
+    mssql.WithInitDatabase(mssqlDatabase),
 )
```




> Likely invalid or redundant comment.

</details>

</details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2024-12-12T10:20:16Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 0**

<details>
<summary>🧹 Outside diff range and nitpick comments (3)</summary><blockquote>

<details>
<summary>minio/minio_test.go (1)</summary><blockquote>

Line range hint `24-53`: **Enhance container initialization with timeout and health check**

The container initialization could be improved in two ways:
1. Replace `context.Background()` with a timeout context
2. Add a health check strategy to ensure MinIO is ready


Apply this diff to improve container initialization:

```diff
 func newTestStore(t testing.TB) (*Storage, error) {
     t.Helper()
 
-    ctx := context.Background()
+    ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
+    defer cancel()
 
     c, err := minio.Run(ctx,
         img,
         minio.WithUsername(minioUser),
         minio.WithPassword(minioPass),
+        testcontainers.WithWaitStrategy(
+            wait.ForLog("Status:         1 Online, 0 Offline").
+            WithStartupTimeout(20*time.Second),
+        ),
     )
```

</blockquote></details>
<details>
<summary>mssql/mssql_test.go (1)</summary><blockquote>

`231-239`: **Improve SSL mode panic test accuracy**

The test's panic message and configuration don't clearly represent the SSL requirement scenario.

Apply this diff to improve test clarity:

```diff
 require.Panics(t, func() {
     _ = New(Config{
-        Database: "fiber",
-        Username: "username",
-        Password: "password",
+        ConnectionURI: "sqlserver://localhost:1433?sslmode=require",
         Reset:    true,
-        SslMode:  "require",
     })
-}, "Expected panic when connecting to MSSQL with SSL mode set to require")
+}, "Expected panic when connecting with SSL required but no valid certificate")
```

</blockquote></details>
<details>
<summary>postgres/postgres_test.go (1)</summary><blockquote>

`28-33`: **Add timeout to context for better resource management**

While the wait strategy is well implemented, the background context should have a timeout.

Apply this diff:

```diff
-ctx := context.Background()
+ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
+defer cancel()
```

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between b074e83e98adfdcbb968e3297b84a051aa647f3e and cac4fd5e8d34d146fe8e9fa2ee9d14bb5cd81386.

</details>

<details>
<summary>📒 Files selected for processing (7)</summary>

* `clickhouse/clickhouse_test.go` (4 hunks)
* `couchbase/couchbase_test.go` (11 hunks)
* `minio/minio_test.go` (16 hunks)
* `mongodb/mongodb_test.go` (11 hunks)
* `mssql/mssql_test.go` (12 hunks)
* `mysql/mysql_test.go` (13 hunks)
* `postgres/postgres_test.go` (12 hunks)

</details>

<details>
<summary>🔇 Additional comments (11)</summary>

<details>
<summary>mongodb/mongodb_test.go (2)</summary>

`22-46`: **Good Use of `newTestStore` Function for Test Isolation**

The introduction of the `newTestStore` function enhances test isolation by providing a fresh MongoDB instance for each test. Resource cleanup is properly handled with `defer testStore.Close()`, and error handling is appropriately managed.

---

`25-28`: **Verify Custom MongoDB Image Compatibility**

When overriding the MongoDB image using the `TEST_MONGODB_IMAGE` environment variable, please ensure that the custom image is compatible with the test setup to prevent unexpected failures.



Run the following script to check if the environment variable is set and verify the image:

<details>
<summary>✅ Verification successful</summary>

Let me check the default MongoDB image and test configuration to better understand the compatibility requirements.

---

**Custom MongoDB Image Override is Well-Implemented**

The code is using MongoDB 7.x as the default image and allows for custom image override through the `TEST_MONGODB_IMAGE` environment variable. The implementation is safe because:
1. It uses a stable default image (`mongo:7`)
2. The test container is created using the official testcontainers-go MongoDB module
3. The container setup includes proper authentication with username and password



</details>

<details>
<summary>🏁 Scripts executed</summary>

The following scripts were executed for the analysis:

Script:

```shell
#!/bin/bash
# Description: Check if TEST_MONGODB_IMAGE is set and output its value.

if [ -n "$TEST_MONGODB_IMAGE" ]; then
  echo "TEST_MONGODB_IMAGE is set to: $TEST_MONGODB_IMAGE"
  # Optionally, pull the image to ensure it's available
  docker pull "$TEST_MONGODB_IMAGE"
else
  echo "TEST_MONGODB_IMAGE is not set. Using default image."
fi

```

Length of output: 128

---

Script:

```shell
#!/bin/bash
# Find the default MongoDB image and test configuration
rg -A 5 "mongoDBImage.*=" 
rg "mongo" mongodb/mongodb_test.go

```

Length of output: 1251

</details>

</details>
<details>
<summary>mysql/mysql_test.go (2)</summary>

`19-20`: **Confirm MySQL Credentials Are Correctly Assigned**

The constants for `mysqlUser` and `mysqlPass` are defined as:

```go
mysqlUser string = "username"
mysqlPass string = "password"
```

Ensure that these credentials match the expected values for the MySQL container. Previously, there was an issue where these values were swapped.

---

`50-57`: _:hammer_and_wrench: Refactor suggestion_

**Refactor `mustStartMySQL` to Return Error Instead of Failing Test**

In the `mustStartMySQL` function, calling `require.NoError(t, err)` causes the test to fail immediately if there's an error starting the MySQL container. It's better practice to return the error and handle it in `newTestStore`, providing clearer error propagation and maintaining consistency in error handling.



Apply this diff to modify error handling:

```diff
 func mustStartMySQL(t testing.TB) (*mysql.MySQLContainer, error) {
     img := mysqlImage
     if imgFromEnv := os.Getenv(mysqlImageEnvVar); imgFromEnv != "" {
         img = imgFromEnv
     }

     ctx := context.Background()

     c, err := mysql.Run(ctx, img,
         mysql.WithPassword(mysqlPass),
         mysql.WithUsername(mysqlUser),
         mysql.WithDatabase(mysqlDatabase),
     )
-    testcontainers.CleanupContainer(t, c)
-    require.NoError(t, err)
+    if err != nil {
+        return nil, err
+    }
+    testcontainers.CleanupContainer(t, c)

     return c, nil
 }
```

Update `newTestStore` to handle the error:

```diff
 func newTestStore(t testing.TB) (*Storage, error) {
     t.Helper()

-    c := mustStartMySQL(t)
+    c, err := mustStartMySQL(t)
+    if err != nil {
+        return nil, err
+    }

     ctx := context.Background()

     conn, err := c.ConnectionString(ctx)
     if err != nil {
         return nil, err
     }

     return New(Config{
         ConnectionURI: conn,
         Reset:         true,
     }), nil
 }
```




> Likely invalid or redundant comment.

</details>
<details>
<summary>couchbase/couchbase_test.go (1)</summary>

`16-16`: **Verify Compatibility with Updated Couchbase Image**

The Couchbase image has been updated to `enterprise-7.6.3`. Please verify that this version is compatible with your test suite, as there may be breaking changes or deprecations compared to `enterprise-7.1.1`.



Run the following script to check for any known issues in the new Couchbase version:

<details>
<summary>✅ Verification successful</summary>

Let me search for test files and configurations to understand how Couchbase is being used in the tests.

---

Let me check the implementation details of the Couchbase storage to understand the features being used.

---

Let me check the dependencies to verify the Couchbase SDK version being used.

---

Let me try a different approach to check the go.mod file.

---

Based on the analysis of the codebase, I can now provide the final response:

**Couchbase Version Update Appears Safe**

The test suite uses basic Couchbase operations (Get, Set, Delete, Reset) through the gocb/v2 SDK, and these core operations remain stable across Couchbase versions. The tests are using testcontainers with simple bucket configuration and basic CRUD operations that are well-supported across versions.

- The test implementation uses container-based testing that allows version override via `TEST_COUCHBASE_IMAGE` environment variable
- Only standard KV operations are used: Get, Set, Delete, Reset
- No usage of advanced features that might be version-sensitive



</details>

<details>
<summary>🏁 Scripts executed</summary>

The following scripts were executed for the analysis:

Script:

```shell
#!/bin/bash
# Description: Check Couchbase release notes for version 7.6.3

# Prompt to review release notes manually
echo "Please review the Couchbase 7.6.3 release notes for any breaking changes or deprecations:"
echo "https://docs.couchbase.com/server/7.6/release-notes/relnotes.html"

```

Length of output: 327

---

Script:

```shell
#!/bin/bash
# Search for Couchbase-related test files and configurations
echo "=== Searching for Couchbase test files ==="
fd -e go -e yaml -e json . | grep -i "couchbase"

echo -e "\n=== Checking test implementation details ==="
rg -l "couchbase" --type go

echo -e "\n=== Examining test implementation ==="
cat couchbase/couchbase_test.go

```

Length of output: 4991

---

Script:

```shell
#!/bin/bash
# Check the implementation details
echo "=== Examining Couchbase implementation ==="
cat couchbase/couchbase.go

echo -e "\n=== Examining Couchbase config ==="
cat couchbase/config.go

```

Length of output: 3497

---

Script:

```shell
#!/bin/bash
# Check module dependencies
echo "=== Examining go.mod for Couchbase SDK version ==="
cat go.mod | grep -A 5 "couchbase"

```

Length of output: 145

---

Script:

```shell
#!/bin/bash
# Check entire go.mod content
echo "=== Examining complete go.mod ==="
cat go.mod

```

Length of output: 132

</details>

</details>
<details>
<summary>clickhouse/clickhouse_test.go (2)</summary>

`197-206`: **Addition of `TestClose_ShouldReturn_NoError` Enhances Test Coverage**

The new test `TestClose_ShouldReturn_NoError` appropriately verifies that the `Close` method performs as expected without errors, improving the overall test coverage for the ClickHouse storage implementation.

---

`43-43`: _:warning: Potential issue_

**Ensure Error Handling Before Cleanup in `getTestConnection`**

In `getTestConnection`, the call to `testcontainers.CleanupContainer(t, c)` should occur after checking for errors. If `err` is not `nil`, the container `c` may not be properly initialized, leading to potential panics or undefined behavior when attempting cleanup.



Apply this diff to adjust the order:

```diff
 c, err := clickhouse.Run(ctx,
     img,
     clickhouse.WithUsername(clickhouseUser),
     clickhouse.WithPassword(clickhousePass),
     clickhouse.WithDatabase(clickhouseDB),
 )
-if err != nil {
-    return nil, err
-}
-testcontainers.CleanupContainer(t, c)
+if err != nil {
+    return nil, err
+}
+testcontainers.CleanupContainer(t, c)
```

Ensure that `testcontainers.CleanupContainer(t, c)` is called only after confirming `err` is `nil`.





> Likely invalid or redundant comment.

</details>
<details>
<summary>minio/minio_test.go (2)</summary>

Line range hint `111-119`: **Add verification for key expiration**

The test sets a key with expiration but doesn't verify if the key actually expired.

Apply this diff to verify the expiration:

```diff
 err = testStore.Set(key, val, exp)
 require.NoError(t, err)
 
 time.Sleep(1100 * time.Millisecond)
+
+result, err := testStore.Get(key)
+require.NoError(t, err)
+require.Zero(t, len(result))
```

---

Line range hint `258-305`: **LGTM: Benchmarks are well-implemented**

The benchmark implementations correctly handle resource initialization and cleanup.

</details>
<details>
<summary>mssql/mssql_test.go (1)</summary>

`24-53`: _:hammer_and_wrench: Refactor suggestion_

**Enhance MSSQL container initialization with timeout and health check**

Similar to MinIO, the container initialization needs timeout context and health check strategy.

Apply this diff to improve container initialization:

```diff
 func newTestStore(t testing.TB) (*Storage, error) {
     t.Helper()
 
-    ctx := context.Background()
+    ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
+    defer cancel()
 
     c, err := mssql.Run(ctx, img,
         mssql.WithPassword(mssqlPass),
         mssql.WithAcceptEULA(),
+        testcontainers.WithWaitStrategy(
+            wait.ForSQL(1433).
+            WithStartupTimeout(25*time.Second),
+        ),
     )
```




> Likely invalid or redundant comment.

</details>
<details>
<summary>postgres/postgres_test.go (1)</summary>

`115-122`: **Add verification for key expiration**

The test sets a key with expiration but doesn't verify if the key actually expired.

Apply this diff to verify the expiration:

```diff
 err = testStore.Set(key, val, exp)
 require.NoError(t, err)
 
 time.Sleep(1100 * time.Millisecond)
+
+result, err := testStore.Get(key)
+require.NoError(t, err)
+require.Zero(t, len(result))
```

</details>

</details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2024-12-12T11:26:07Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 0**

<details>
<summary>🔭 Outside diff range comments (1)</summary><blockquote>

<details>
<summary>mssql/mssql_test.go (1)</summary><blockquote>

Line range hint `105-112`: **Improve expiration test verification.**

The test sets expiration but doesn't verify that the key actually expired.


Add verification after sleep:

```diff
 	err = testStore.Set(key, val, exp)
 	require.NoError(t, err)
 
 	time.Sleep(1100 * time.Millisecond)
+	
+	result, err := testStore.Get(key)
+	require.NoError(t, err)
+	require.Zero(t, len(result), "key should have expired")
```

</blockquote></details>

</blockquote></details>

<details>
<summary>♻️ Duplicate comments (2)</summary><blockquote>

<details>
<summary>mssql/mssql_test.go (2)</summary><blockquote>

`58-60`: _:hammer_and_wrench: Refactor suggestion_

**Add defer cleanup to all test store initializations.**

Each test initializes a store but doesn't ensure cleanup.



Add `defer testStore.Close()` after store initialization in all test functions:

```diff
 	testStore, err := newTestStore(t)
 	require.NoError(t, err)
+	defer testStore.Close()
```


Also applies to: 71-73, 87-89, 105-107, 117-119, 126-128, 140-142, 157-159, 181-183, 206-208, 233-235, 240-242

---

`247-249`: _:hammer_and_wrench: Refactor suggestion_

**Add defer cleanup to all benchmark store initializations.**

Each benchmark initializes a store but doesn't ensure cleanup.



Add `defer testStore.Close()` after store initialization in all benchmark functions:

```diff
 	testStore, err := newTestStore(b)
 	require.NoError(b, err)
+	defer testStore.Close()
```


Also applies to: 261-264, 278-280

</blockquote></details>

</blockquote></details>

<details>
<summary>🧹 Nitpick comments (1)</summary><blockquote>

<details>
<summary>mssql/mssql_test.go (1)</summary><blockquote>

Line range hint `219-232`: **Improve panic recovery test.**

The SSL mode test's panic recovery could be more explicit and provide better error messages.


Consider this improvement:

```diff
 func Test_SslRequiredMode(t *testing.T) {
+	expectedMsg := "SSL mode 'require' is not supported"
 	defer func() {
-		if recover() == nil {
-			require.Equalf(t, true, nil, "Connection was established with a `require`")
+		if r := recover(); r == nil {
+			t.Error("expected panic but got none")
+		} else if r != expectedMsg {
+			t.Errorf("expected panic with message %q but got %v", expectedMsg, r)
 		}
 	}()
 	_ = New(Config{
```

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between cac4fd5e8d34d146fe8e9fa2ee9d14bb5cd81386 and d793dc4af00b599a9c5f19684c1a913b4c0a9d1e.

</details>

<details>
<summary>⛔ Files ignored due to path filters (6)</summary>

* `.github/workflows/benchmark.yml` is excluded by `!**/*.yml`
* `.github/workflows/test-mssql.yml` is excluded by `!**/*.yml`
* `mongodb/go.mod` is excluded by `!**/*.mod`
* `mongodb/go.sum` is excluded by `!**/*.sum`, `!**/*.sum`
* `s3/go.mod` is excluded by `!**/*.mod`
* `s3/go.sum` is excluded by `!**/*.sum`, `!**/*.sum`

</details>

<details>
<summary>📒 Files selected for processing (1)</summary>

* `mssql/mssql_test.go` (12 hunks)

</details>

<details>
<summary>🔇 Additional comments (2)</summary><blockquote>

<details>
<summary>mssql/mssql_test.go (2)</summary>

`14-21`: **LGTM! Well-structured constants with clear naming.**

The constants are well-organized and provide flexibility through environment variables. The default MSSQL image version is explicitly specified, which is good for reproducibility.

---

`31-39`: _:hammer_and_wrench: Refactor suggestion_

**Add timeout and health check for container initialization.**

The current implementation has several potential issues:
1. Uses non-cancellable context
2. No health check to ensure MSSQL is ready
3. No explicit cleanup mechanism


Apply this diff to improve container initialization:

```diff
-	ctx := context.Background()
+	ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
+	defer cancel()
+
 	// Due to licensing restrictions you are required to explicitly accept an EULA for this container image.
 	c, err := mssql.Run(ctx, img,
 		mssql.WithPassword(mssqlPass),
 		mssql.WithAcceptEULA(),
+		mssql.WithWaitStrategy(
+			wait.ForSQL(1433).
+			WithStartupTimeout(25*time.Second),
+		),
 	)
```

Also add container cleanup:

```diff
+	t.Cleanup(func() {
+		if err := c.Terminate(context.Background()); err != nil {
+			t.Logf("failed to terminate container: %v", err)
+		}
+	})
```




> Likely invalid or redundant comment.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-01-30T16:19:13Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 2**

<details>
<summary>🔭 Outside diff range comments (2)</summary><blockquote>

<details>
<summary>mongodb/mongodb_test.go (1)</summary><blockquote>

`107-122`: _:warning: Potential issue_

**Test_MongoDB_Set_Expiration is incomplete.**

The test sets an expiration but doesn't verify if the key actually expired. Consider adding a verification step to ensure the key is no longer accessible after expiration.

```diff
 func Test_MongoDB_Set_Expiration(t *testing.T) {
     var (
         key = "john"
         val = []byte("doe")
         exp = 1 * time.Second
     )

     testStore, err := newTestStore(t)
     require.NoError(t, err)
     defer testStore.Close()

     err = testStore.Set(key, val, exp)
     require.NoError(t, err)

     time.Sleep(1100 * time.Millisecond)
+    // Verify the key has expired
+    result, err := testStore.Get(key)
+    require.NoError(t, err)
+    require.Zero(t, len(result), "Key should have expired")
 }
```

</blockquote></details>
<details>
<summary>postgres/postgres_test.go (1)</summary><blockquote>

`103-118`: _:hammer_and_wrench: Refactor suggestion_

**Add verification for key expiration.**

The test sleeps for the expiration duration but doesn't verify that the key has actually expired.

Apply this diff to add verification:

```diff
     err = testStore.Set(key, val, exp)
     require.NoError(t, err)
 
     time.Sleep(1100 * time.Millisecond)
+
+    // Verify key has expired
+    result, err := testStore.Get(key)
+    require.NoError(t, err)
+    require.Zero(t, len(result), "Key should have expired")
```

</blockquote></details>

</blockquote></details>

<details>
<summary>🧹 Nitpick comments (7)</summary><blockquote>

<details>
<summary>s3/init_test.go (1)</summary><blockquote>

`40-43`: **Consider using constants for port and health check path.**

The port "9000/tcp" and health check path "/minio/health/live" are hardcoded in the wait strategy. Consider extracting these values into constants for better maintainability.

```diff
+const (
+    minioPort       = "9000/tcp"
+    minioHealthPath = "/minio/health/live"
+)

 testcontainers.WithWaitStrategy(
-    wait.ForListeningPort("9000/tcp"),
-    wait.ForHTTP("/minio/health/live").WithPort("9000"),
+    wait.ForListeningPort(minioPort),
+    wait.ForHTTP(minioHealthPath).WithPort("9000"),
 ),
```

</blockquote></details>
<details>
<summary>neo4j/neo4j_test.go (1)</summary><blockquote>

`26-32`: **Consider using constants for ports and log message.**

The ports "7474/tcp", "7687/tcp" and log message "Bolt enabled on" are hardcoded in the wait strategy. Consider extracting these values into constants for better maintainability.

```diff
+const (
+    neo4jHttpPort  = "7474/tcp"
+    neo4jBoltPort  = "7687/tcp"
+    neo4jReadyLog  = "Bolt enabled on"
+)

 testcontainers.WithWaitStrategy(
     wait.ForAll(
-        wait.ForListeningPort("7474/tcp"),
-        wait.ForListeningPort("7687/tcp"),
-        wait.ForLog("Bolt enabled on"),
+        wait.ForListeningPort(neo4jHttpPort),
+        wait.ForListeningPort(neo4jBoltPort),
+        wait.ForLog(neo4jReadyLog),
     ),
 ),
```

</blockquote></details>
<details>
<summary>mongodb/mongodb_test.go (1)</summary><blockquote>

`36-39`: **Consider using constants for port and log message.**

The port "27017/tcp" and log message "Waiting for connections" are hardcoded in the wait strategy. Consider extracting these values into constants for better maintainability.

```diff
+const (
+    mongoDBPort   = "27017/tcp"
+    mongoDBReadyLog = "Waiting for connections"
+)

 wait.ForAll(
-    wait.ForListeningPort("27017/tcp"),
-    wait.ForLog("Waiting for connections"),
+    wait.ForListeningPort(mongoDBPort),
+    wait.ForLog(mongoDBReadyLog),
 ),
```

</blockquote></details>
<details>
<summary>clickhouse/clickhouse_test.go (2)</summary><blockquote>

`43-50`: **Consider using constants for port and status code.**

The port "8123/tcp" and status code 200 are hardcoded in the wait strategy. Consider extracting these values into constants for better maintainability.

```diff
+const (
+    clickhouseHttpPort     = "8123/tcp"
+    clickhouseSuccessCode  = 200
+)

 testcontainers.WithWaitStrategy(
     wait.ForAll(
-        wait.ForListeningPort("8123/tcp"),
-        wait.NewHTTPStrategy("/").WithPort("8123/tcp").WithStatusCodeMatcher(func(status int) bool {
-            return status == 200
+        wait.ForListeningPort(clickhouseHttpPort),
+        wait.NewHTTPStrategy("/").WithPort(clickhouseHttpPort).WithStatusCodeMatcher(func(status int) bool {
+            return status == clickhouseSuccessCode
         }),
     ),
 ),
```

---

`154-154`: **Consider using a constant for sleep duration.**

The sleep duration of 5 seconds is hardcoded. Consider extracting this value into a constant for better maintainability and to make it easier to adjust if needed.

```diff
+const testExpirationWaitTime = 5 * time.Second

-time.Sleep(time.Second * 5)
+time.Sleep(testExpirationWaitTime)
```

</blockquote></details>
<details>
<summary>postgres/postgres_test.go (1)</summary><blockquote>

`24-52`: **Enhance container wait strategy for PostgreSQL.**

While the current implementation works, consider using a more PostgreSQL-specific wait strategy to ensure the database is fully ready to accept connections.

Apply this diff to improve the wait strategy:

```diff
     c, err := postgres.Run(ctx, img,
         postgres.WithUsername(postgresUser),
         postgres.WithPassword(postgresPass),
         postgres.WithDatabase(postgresDatabase),
-        postgres.BasicWaitStrategies(),
+        testcontainers.WithWaitStrategy(
+            wait.ForLog("database system is ready to accept connections").WithOccurrence(2),
+        ),
     )
```

</blockquote></details>
<details>
<summary>mysql/mysql_test.go (1)</summary><blockquote>

`51-59`: **Reorder MySQL container configuration parameters.**

Consider reordering the parameters to follow the standard convention: username before password.

Apply this diff to reorder the parameters:

```diff
     c, err := mysql.Run(ctx, img,
-        mysql.WithPassword(mysqlPass),
-        mysql.WithUsername(mysqlUser),
+        mysql.WithUsername(mysqlUser),
+        mysql.WithPassword(mysqlPass),
         mysql.WithDatabase(mysqlDatabase),
         testcontainers.WithWaitStrategy(
             wait.ForListeningPort("3306/tcp"),
             wait.ForLog("port: 3306  MySQL Community Server"),
         ),
```

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between d793dc4af00b599a9c5f19684c1a913b4c0a9d1e and 0c2d88489876bf5e684be3037fda58f12add6913.

</details>

<details>
<summary>⛔ Files ignored due to path filters (15)</summary>

* `.github/workflows/benchmark.yml` is excluded by `!**/*.yml`
* `clickhouse/go.mod` is excluded by `!**/*.mod`
* `clickhouse/go.sum` is excluded by `!**/*.sum`, `!**/*.sum`
* `couchbase/go.mod` is excluded by `!**/*.mod`
* `couchbase/go.sum` is excluded by `!**/*.sum`, `!**/*.sum`
* `minio/go.mod` is excluded by `!**/*.mod`
* `minio/go.sum` is excluded by `!**/*.sum`, `!**/*.sum`
* `mongodb/go.mod` is excluded by `!**/*.mod`
* `mongodb/go.sum` is excluded by `!**/*.sum`, `!**/*.sum`
* `mysql/go.mod` is excluded by `!**/*.mod`
* `mysql/go.sum` is excluded by `!**/*.sum`, `!**/*.sum`
* `postgres/go.mod` is excluded by `!**/*.mod`
* `postgres/go.sum` is excluded by `!**/*.sum`, `!**/*.sum`
* `s3/go.mod` is excluded by `!**/*.mod`
* `s3/go.sum` is excluded by `!**/*.sum`, `!**/*.sum`

</details>

<details>
<summary>📒 Files selected for processing (7)</summary>

* `clickhouse/clickhouse_test.go` (4 hunks)
* `minio/minio_test.go` (16 hunks)
* `mongodb/mongodb_test.go` (11 hunks)
* `mysql/mysql_test.go` (13 hunks)
* `neo4j/neo4j_test.go` (2 hunks)
* `postgres/postgres_test.go` (12 hunks)
* `s3/init_test.go` (2 hunks)

</details>

<details>
<summary>🚧 Files skipped from review as they are similar to previous changes (1)</summary>

* minio/minio_test.go

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (18)</summary>

* GitHub Check: compare (mongodb)
* GitHub Check: compare (clickhouse)
* GitHub Check: compare (minio)
* GitHub Check: compare (couchbase)
* GitHub Check: Tests (1.23.x)
* GitHub Check: Tests (1.23.x)
* GitHub Check: Tests (1.22.x)
* GitHub Check: Tests (1.22.x)
* GitHub Check: Tests (1.22.x)
* GitHub Check: Tests (1.23.x)
* GitHub Check: Tests (1.23.x)
* GitHub Check: Tests (1.21.x)
* GitHub Check: Tests (1.21.x)
* GitHub Check: Tests (1.21.x)
* GitHub Check: Tests (1.22.x)
* GitHub Check: Tests (1.22.x)
* GitHub Check: Tests (1.21.x)
* GitHub Check: Tests (1.21.x)

</details>

<details>
<summary>🔇 Additional comments (2)</summary><blockquote>

<details>
<summary>postgres/postgres_test.go (2)</summary>

`11-13`: **LGTM! Well-structured constants and imports.**

The PostgreSQL configuration is well-organized with clear constant names and good documentation. Using a specific version (16-alpine) helps ensure test stability.



Also applies to: 15-22

---

`229-235`: **LGTM! Good error handling test.**

The test effectively verifies the panic scenario when SSL is required but not available, with a clear error message.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-02-18T17:02:38Z
user: login: mdelapenya
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-02-18T17:20:58Z
user: login: coderabbitai[bot]
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-02-18T17:22:11Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 1**

<details>
<summary>🔭 Outside diff range comments (1)</summary><blockquote>

<details>
<summary>mysql/mysql_test.go (1)</summary><blockquote>

`137-152`: _:warning: Potential issue_

**Add expiration verification in Test_MYSQL_Set_Expiration.**

The test sets expiration and waits but doesn't verify that the key has actually expired.

```diff
 func Test_MYSQL_Set_Expiration(t *testing.T) {
     var (
         key = "john"
         val = []byte("doe")
         exp = 1 * time.Second
     )
 
     testStore, err := newTestStore(t)
     require.NoError(t, err)
     defer testStore.Close()
 
     err = testStore.Set(key, val, exp)
     require.NoError(t, err)
 
     time.Sleep(1100 * time.Millisecond)
+
+    // Verify key has expired
+    result, err := testStore.Get(key)
+    require.NoError(t, err)
+    require.Zero(t, len(result), "Key should have expired")
 }
```

</blockquote></details>

</blockquote></details>

<details>
<summary>🧹 Nitpick comments (3)</summary><blockquote>

<details>
<summary>mongodb/mongodb_test.go (1)</summary><blockquote>

`25-58`: **Consider adding retries for MongoDB connection.**

While the wait strategy ensures the container is ready, MongoDB might need additional time to accept connections in some cases.

```diff
 func newTestStore(t testing.TB) (*Storage, error) {
     t.Helper()
 
     img := mongoDBImage
     if imgFromEnv := os.Getenv(mongoDBImageEnvVar); imgFromEnv != "" {
         img = imgFromEnv
     }
 
     ctx := context.Background()
+
+    // Add retry logic for MongoDB connection
+    var store *Storage
+    var err error
+    for i := 0; i < 3; i++ {
+        store, err = tryConnect(ctx, t, img)
+        if err == nil {
+            return store, nil
+        }
+        time.Sleep(time.Second)
+    }
+    return store, err
 }
+
+func tryConnect(ctx context.Context, t testing.TB, img string) (*Storage, error) {
     c, err := mongodb.Run(
         ctx, img, mongodb.WithUsername(mongoDBUser), mongodb.WithPassword(mongoDBPass),
         testcontainers.WithWaitStrategy(
             wait.ForAll(
                 wait.ForListeningPort(mongoDBPort),
                 wait.ForLog(mongoDBReadyLog),
             ),
         ),
     )
     testcontainers.CleanupContainer(t, c)
     if err != nil {
         return nil, err
     }
 
     conn, err := c.ConnectionString(ctx)
     if err != nil {
         return nil, err
     }
 
     return New(Config{
         ConnectionURI: conn,
         Reset:         true,
     }), nil
```

</blockquote></details>
<details>
<summary>postgres/postgres_test.go (1)</summary><blockquote>

`34-40`: **Enhance wait strategy for more reliable container startup.**

The current basic wait strategy might not be sufficient in all environments.

```diff
 c, err := postgres.Run(ctx, img,
     postgres.WithUsername(postgresUser),
     postgres.WithPassword(postgresPass),
     postgres.WithDatabase(postgresDatabase),
-    postgres.BasicWaitStrategies(),
+    testcontainers.WithWaitStrategy(
+        wait.ForAll(
+            wait.ForLog("database system is ready to accept connections").WithOccurrence(2),
+            wait.ForListeningPort("5432/tcp"),
+        ),
+    ),
 )
```

</blockquote></details>
<details>
<summary>mysql/mysql_test.go (1)</summary><blockquote>

`51-61`: **Consider adding health check in wait strategy.**

The current wait strategy checks for port and log, but a health check would provide stronger guarantees.

```diff
 c, err := mysql.Run(ctx, img,
     mysql.WithPassword(mysqlPass),
     mysql.WithUsername(mysqlUser),
     mysql.WithDatabase(mysqlDatabase),
     testcontainers.WithWaitStrategy(
         wait.ForListeningPort("3306/tcp"),
         wait.ForLog("port: 3306  MySQL Community Server"),
+        wait.ForSQL("3306/tcp", "mysql", func(port nat.Port) string {
+            return fmt.Sprintf("root:%s@(localhost:%s)/%s", mysqlPass, port.Port(), mysqlDatabase)
+        }).WithStartupTimeout(time.Second * 30),
     ),
 )
```

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 0c2d88489876bf5e684be3037fda58f12add6913 and f2ff5e7a3911347013033a6a63390d45aacf0a70.

</details>

<details>
<summary>📒 Files selected for processing (6)</summary>

* `clickhouse/clickhouse_test.go` (5 hunks)
* `minio/minio_test.go` (17 hunks)
* `mongodb/mongodb_test.go` (10 hunks)
* `mysql/mysql_test.go` (13 hunks)
* `neo4j/neo4j_test.go` (2 hunks)
* `postgres/postgres_test.go` (11 hunks)

</details>

<details>
<summary>🚧 Files skipped from review as they are similar to previous changes (2)</summary>

* neo4j/neo4j_test.go
* minio/minio_test.go

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>🧠 Learnings (1)</summary>

<details>
<summary>mysql/mysql_test.go (2)</summary>

```
Learnt from: mdelapenya
PR: gofiber/storage#1515
File: mysql/mysql_test.go:18-18
Timestamp: 2025-02-18T17:22:10.331Z
Learning: The `mysql:9` Docker image exists and is actively maintained, with regular updates on Docker Hub. The image was verified through Docker Hub's API and is suitable for testing purposes.
```

```
Learnt from: mdelapenya
PR: gofiber/storage#1515
File: mysql/mysql_test.go:18-18
Timestamp: 2025-02-18T17:22:10.331Z
Learning: The `mysql:9` Docker image exists and can be used for testing, although it represents a development version of MySQL. The image is available at docker.io/mysql:9.
```

</details>

</details><details>
<summary>🪛 GitHub Actions: Tests Clickhouse</summary>

<details>
<summary>clickhouse/clickhouse_test.go</summary>

[error] 170-170: Received unexpected error: [handshake] unexpected packet [72] from server in Test_Delete

---

[error] 192-192: Received unexpected error: [handshake] unexpected packet [72] from server in Test_Reset

---

[error] 214-214: Received unexpected error: [handshake] unexpected packet [72] from server in TestClose_ShouldReturn_NoError

</details>

</details>

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (14)</summary>

* GitHub Check: compare (s3)
* GitHub Check: compare (mongodb)
* GitHub Check: compare (clickhouse)
* GitHub Check: compare (minio)
* GitHub Check: compare (mysql)
* GitHub Check: compare (postgres)
* GitHub Check: compare (neo4j)
* GitHub Check: compare (couchbase)
* GitHub Check: Tests (1.23.x)
* GitHub Check: Tests (1.22.x)
* GitHub Check: Tests (1.23.x)
* GitHub Check: Tests (1.21.x)
* GitHub Check: Tests (1.22.x)
* GitHub Check: Tests (1.21.x)

</details>

<details>
<summary>🔇 Additional comments (1)</summary><blockquote>

<details>
<summary>mongodb/mongodb_test.go (1)</summary>

`15-23`: **LGTM! Well-structured constants.**

The constants are well-organized and provide clear configuration for the MongoDB container setup.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-02-18T17:28:36Z
user: login: ReneWerner87
state: APPROVED
author_association: MEMBER
submitted_at: 2025-03-17T12:43:38Z
user: login: gaby
body: LGTM, minimal comments here and there
state: CHANGES_REQUESTED
author_association: MEMBER
submitted_at: 2025-03-18T02:02:30Z
user: login: mdelapenya
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-18T09:59:57Z
user: login: gaby
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-18T12:24:34Z
user: login: gaby
body: 👍 LGTM, this is phenomenal work!
state: APPROVED
author_association: MEMBER
submitted_at: 2025-03-19T03:31:58Z

Review comments:
diff_hunk: @@ -12,17 +12,11 @@ name: "Tests Mongodb"
 jobs:
     Tests:
         runs-on: ubuntu-latest
-        services:
-            mongo:
-                image: 'mongo:latest'
-                ports:
-                    - '27017:27017'
         strategy:
             matrix:
                 go-version:
-                    - 1.19.x
-                    - 1.20.x
                     - 1.21.x
+                    - 1.22.x
path: .github/workflows/test-mongodb.yml
user: login: gaby
body: Once tests are green, re-add 1.23 here
created_at: 2024-08-29T12:57:57Z
author_association: MEMBER
diff_hunk: @@ -12,25 +12,11 @@ name: "Tests MySQL"
 jobs:
     Tests:
         runs-on: ubuntu-latest
-        services:
-            mysql:
-                image: 'mysql:latest'
-                env:
-                    MYSQL_DATABASE: fiber
-                    MYSQL_USER: username
-                    MYSQL_PASSWORD: password
-                    MYSQL_ROOT_PASSWORD: password
-                ports:
-                    - '3306:3306'
-                options: >-
-                    --health-cmd "mysqladmin ping" --health-interval 10s --health-timeout
-                    5s --health-retries 5
         strategy:
             matrix:
                 go-version:
-                    - 1.19.x
-                    - 1.20.x
                     - 1.21.x
+                    - 1.22.x
path: .github/workflows/test-mysql.yml
user: login: gaby
body: Same here
created_at: 2024-08-29T12:58:06Z
author_association: MEMBER
diff_hunk: @@ -1,24 +1,70 @@
 module github.com/gofiber/storage/mongodb/v2
 
-go 1.19
+go 1.21
+
+toolchain go1.22.1
path: mongodb/go.mod
user: login: gaby
body: The toolchain needs to be removed
created_at: 2024-08-29T12:58:19Z
author_association: MEMBER
diff_hunk: @@ -1,24 +1,70 @@
 module github.com/gofiber/storage/mongodb/v2
 
-go 1.19
+go 1.21
+
+toolchain go1.22.1
path: mongodb/go.mod
user: login: gaby
body: This is why mongo tests are failing
created_at: 2024-08-29T12:59:43Z
author_association: MEMBER
diff_hunk: @@ -1,24 +1,70 @@
 module github.com/gofiber/storage/mongodb/v2
 
-go 1.19
+go 1.21
+
+toolchain go1.22.1
path: mongodb/go.mod
user: login: mdelapenya
body: Sorry about that, wrong go mod tidy + commit
created_at: 2024-08-29T13:09:32Z
author_association: CONTRIBUTOR
diff_hunk: @@ -12,17 +12,11 @@ name: "Tests Mongodb"
 jobs:
     Tests:
         runs-on: ubuntu-latest
-        services:
-            mongo:
-                image: 'mongo:latest'
-                ports:
-                    - '27017:27017'
         strategy:
             matrix:
                 go-version:
-                    - 1.19.x
-                    - 1.20.x
                     - 1.21.x
+                    - 1.22.x
path: .github/workflows/test-mongodb.yml
user: login: mdelapenya
body: So we want to include 1.23 in these new tests? The matrix would be 1.21, 1.22 and 1.23, right?
created_at: 2024-08-29T13:10:04Z
author_association: CONTRIBUTOR
diff_hunk: @@ -12,17 +12,11 @@ name: "Tests Mongodb"
 jobs:
     Tests:
         runs-on: ubuntu-latest
-        services:
-            mongo:
-                image: 'mongo:latest'
-                ports:
-                    - '27017:27017'
         strategy:
             matrix:
                 go-version:
-                    - 1.19.x
-                    - 1.20.x
                     - 1.21.x
+                    - 1.22.x
path: .github/workflows/test-mongodb.yml
user: login: gaby
body: Correct, 1.23 should work
created_at: 2024-08-29T13:14:53Z
author_association: MEMBER
diff_hunk: @@ -1,28 +1,65 @@
 package mssql
 
 import (
+	"context"
 	"database/sql"
 	"os"
 	"testing"
 	"time"
 
 	"github.com/stretchr/testify/require"
+	"github.com/testcontainers/testcontainers-go/modules/mssql"
 )
 
-var testStore = New(Config{
-	Database: os.Getenv("MSSQL_DATABASE"),
-	Username: os.Getenv("MSSQL_USERNAME"),
-	Password: os.Getenv("MSSQL_PASSWORD"),
-	Reset:    true,
-})
+const (
+	// mssqlImage is the default image used for running MSSQL in tests.
+	mssqlImage              = "mcr.microsoft.com/mssql/server:2022-CU10-ubuntu-22.04"
+	mssqlImageEnvVar string = "TEST_MSSQL_IMAGE"
+	mssqlUser        string = "sa"
+	mssqlPass        string = "MsSql!1234"
+	mssqlDatabase    string = "master"
+)
+
+func newTestStore(t testing.TB) (*Storage, error) {
+	t.Helper()
+
+	img := mssqlImage
+	if imgFromEnv := os.Getenv(mssqlImageEnvVar); imgFromEnv != "" {
+		img = imgFromEnv
+	}
+
+	ctx := context.Background()
+
+	// Due to licensing restrictions you are required to explicitly accept an EULA for this container image.
+	c, err := mssql.Run(ctx, img,
+		mssql.WithPassword(mssqlPass),
+		mssql.WithAcceptEULA(),
+	)
+	if err != nil {
+		return nil, err
+	}
+
+	conn, err := c.ConnectionString(ctx)
+	if err != nil {
+		return nil, err
+	}
+
+	return New(Config{
+		ConnectionURI: conn,
+		Reset:         true,
+	}), nil
+}
 
 func Test_MSSQL_Set(t *testing.T) {
 	var (
 		key = "john"
 		val = []byte("doe")
 	)
 
-	err := testStore.Set(key, val, 0)
+	testStore, err := newTestStore(t)
+	require.NoError(t, err)
+
path: mssql/mssql_test.go
user: login: coderabbitai[bot]
body: **Ensure proper cleanup by closing the test store in tests and benchmarks.**

In the test and benchmark functions, after initializing `testStore`, consider adding `defer testStore.Close()` to ensure that resources are properly released and to prevent potential resource leaks.



Apply the following diff to add the `defer` statements:

For tests:

```diff
 func Test_FunctionName(t *testing.T) {
 	testStore, err := newTestStore(t)
 	require.NoError(t, err)
+	defer testStore.Close()
 	// rest of the test code
 }
```

For benchmarks:

```diff
 func Benchmark_FunctionName(b *testing.B) {
 	testStore, err := newTestStore(b)
 	require.NoError(b, err)
+	defer testStore.Close()
 	// rest of the benchmark code
 }
```


Also applies to: 72-74, 88-90, 106-108, 118-120, 127-129, 141-143, 158-160, 182-184, 207-209, 234-236, 241-243, 248-250, 262-264, 279-281

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2024-09-18T14:25:29Z
author_association: CONTRIBUTOR
diff_hunk: @@ -8,22 +8,64 @@ import (
 
 	"github.com/jackc/pgx/v5"
 	"github.com/stretchr/testify/require"
+	"github.com/testcontainers/testcontainers-go"
+	"github.com/testcontainers/testcontainers-go/modules/postgres"
+	"github.com/testcontainers/testcontainers-go/wait"
 )
 
-var testStore = New(Config{
-	Database: os.Getenv("POSTGRES_DATABASE"),
-	Username: os.Getenv("POSTGRES_USERNAME"),
-	Password: os.Getenv("POSTGRES_PASSWORD"),
-	Reset:    true,
-})
+const (
+	// postgresImage is the default image used for running Postgres in tests.
+	postgresImage              = "docker.io/postgres:16-alpine"
+	postgresImageEnvVar string = "TEST_POSTGRES_IMAGE"
+	postgresUser        string = "username"
+	postgresPass        string = "p4ssw0rd"
+	postgresDatabase    string = "fiber"
+)
+
+func newTestStore(t testing.TB) (*Storage, error) {
+	t.Helper()
+
+	ctx := context.Background()
+
+	img := postgresImage
+	if imgFromEnv := os.Getenv(postgresImageEnvVar); imgFromEnv != "" {
+		img = imgFromEnv
+	}
+
+	c, err := postgres.Run(ctx, img,
+		postgres.WithUsername(postgresUser),
+		postgres.WithPassword(postgresPass),
+		postgres.WithDatabase(postgresDatabase),
+		testcontainers.WithWaitStrategy(
+			// First, we wait for the container to log readiness twice.
+			// This is because it will restart itself after the first startup.
+			wait.ForLog("database system is ready to accept connections").WithOccurrence(2),
+		),
+	)
+	require.NoError(t, err)
+
+	conn, err := c.ConnectionString(ctx, "sslmode=disable")
+	if err != nil {
+		return nil, err
+	}
+
+	return New(Config{
+		ConnectionURI: conn,
+		Reset:         true,
+	}), nil
+}
path: postgres/postgres_test.go
user: login: coderabbitai[bot]
body: **Ensure proper cleanup of test containers to prevent resource leaks**

The `newTestStore` function creates a new PostgreSQL container for each test but does not terminate the container after the test completes. This could lead to resource leaks and accumulation of unused Docker containers during testing.



Apply this diff to ensure the container is properly terminated:

```diff
 func newTestStore(t testing.TB) (*Storage, error) {
     t.Helper()

     ctx := context.Background()

     img := postgresImage
     if imgFromEnv := os.Getenv(postgresImageEnvVar); imgFromEnv != "" {
         img = imgFromEnv
     }

     c, err := postgres.Run(ctx, img,
         postgres.WithUsername(postgresUser),
         postgres.WithPassword(postgresPass),
         postgres.WithDatabase(postgresDatabase),
         testcontainers.WithWaitStrategy(
             // First, we wait for the container to log readiness twice.
             // This is because it will restart itself after the first startup.
             wait.ForLog("database system is ready to accept connections").WithOccurrence(2),
         ),
     )
     require.NoError(t, err)

     conn, err := c.ConnectionString(ctx, "sslmode=disable")
     if err != nil {
         return nil, err
     }

-    return New(Config{
+    store := New(Config{
         ConnectionURI: conn,
         Reset:         true,
-    }), nil
+    })

+    cleanup := func() {
+        err := c.Terminate(ctx)
+        require.NoError(t, err)
+    }

-    return store, nil
+    return store, cleanup, nil
 }
```

Then, update your test functions to handle the cleanup function:

```diff
-func Test_Postgres_Set(t *testing.T) {
+func Test_Postgres_Set(t *testing.T) {
     var (
         key = "john"
         val = []byte("doe")
     )

-    testStore, err := newTestStore(t)
+    testStore, cleanup, err := newTestStore(t)
     require.NoError(t, err)
     defer testStore.Close()
+    defer cleanup()

     err = testStore.Set(key, val, 0)
     require.NoError(t, err)
 }
```

Repeat this change for all other test functions using `newTestStore`.



<!-- suggestion_start -->
<details>
<summary>Committable suggestion</summary>

> :bangbang: **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

`````suggestion
func newTestStore(t testing.TB) (*Storage, func(), error) {
	t.Helper()

	ctx := context.Background()

	img := postgresImage
	if imgFromEnv := os.Getenv(postgresImageEnvVar); imgFromEnv != "" {
		img = imgFromEnv
	}

	c, err := postgres.Run(ctx, img,
		postgres.WithUsername(postgresUser),
		postgres.WithPassword(postgresPass),
		postgres.WithDatabase(postgresDatabase),
		testcontainers.WithWaitStrategy(
			// First, we wait for the container to log readiness twice.
			// This is because it will restart itself after the first startup.
			wait.ForLog("database system is ready to accept connections").WithOccurrence(2),
		),
	)
	require.NoError(t, err)

	conn, err := c.ConnectionString(ctx, "sslmode=disable")
	if err != nil {
		return nil, nil, err
	}

	store := New(Config{
		ConnectionURI: conn,
		Reset:         true,
	})

	cleanup := func() {
		err := c.Terminate(ctx)
		require.NoError(t, err)
	}

	return store, cleanup, nil
}
`````

</details>
<!-- suggestion_end -->

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2024-09-18T15:04:56Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,44 +1,81 @@
 package mysql
 
 import (
+	"context"
 	"database/sql"
-	"fmt"
 	"os"
 	"testing"
 	"time"
 
 	"github.com/stretchr/testify/require"
+	"github.com/testcontainers/testcontainers-go/modules/mysql"
 )
 
-var testStore = New(Config{
-	Database: os.Getenv("MYSQL_DATABASE"),
-	Username: os.Getenv("MYSQL_USERNAME"),
-	Password: os.Getenv("MYSQL_PASSWORD"),
-	Reset:    true,
-})
+const (
+	// mysqlImage is the default image used for running MySQL in tests.
+	mysqlImage              = "docker.io/mysql:9"
+	mysqlImageEnvVar string = "TEST_MYSQL_IMAGE"
+	mysqlUser        string = "password"
+	mysqlPass        string = "username"
path: mysql/mysql_test.go
user: login: coderabbitai[bot]
body: **Swap `mysqlUser` and `mysqlPass` values to correct credentials**

The constants for `mysqlUser` and `mysqlPass` appear to be swapped. Currently, `mysqlUser` is set to `"password"` and `mysqlPass` is set to `"username"`, which is likely unintended.



Apply this diff to correct the username and password assignments:

```diff
 const (
     // mysqlImage is the default image used for running MySQL in tests.
     mysqlImage              = "docker.io/mysql:9"
     mysqlImageEnvVar string = "TEST_MYSQL_IMAGE"
-    mysqlUser        string = "password"
-    mysqlPass        string = "username"
+    mysqlUser        string = "username"
+    mysqlPass        string = "password"
     mysqlDatabase    string = "fiber"
 )
```


<!-- suggestion_start -->
<details>
<summary>Committable suggestion</summary>

> :bangbang: **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

`````suggestion
	mysqlUser        string = "username"
	mysqlPass        string = "password"
`````

</details>
<!-- suggestion_end -->

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2024-09-18T20:26:03Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,44 +1,81 @@
 package mysql
 
 import (
+	"context"
 	"database/sql"
-	"fmt"
 	"os"
 	"testing"
 	"time"
 
 	"github.com/stretchr/testify/require"
+	"github.com/testcontainers/testcontainers-go/modules/mysql"
 )
 
-var testStore = New(Config{
-	Database: os.Getenv("MYSQL_DATABASE"),
-	Username: os.Getenv("MYSQL_USERNAME"),
-	Password: os.Getenv("MYSQL_PASSWORD"),
-	Reset:    true,
-})
+const (
+	// mysqlImage is the default image used for running MySQL in tests.
+	mysqlImage              = "docker.io/mysql:9"
+	mysqlImageEnvVar string = "TEST_MYSQL_IMAGE"
+	mysqlUser        string = "password"
+	mysqlPass        string = "username"
+	mysqlDatabase    string = "fiber"
+)
 
-func Test_MYSQL_New(t *testing.T) {
-	newConfigStore := New(Config{
-		Database: os.Getenv("MYSQL_DATABASE"),
-		Username: os.Getenv("MYSQL_USERNAME"),
-		Password: os.Getenv("MYSQL_PASSWORD"),
-		Reset:    true,
-	})
+func newTestStore(t testing.TB) (*Storage, error) {
+	t.Helper()
 
-	require.True(t, newConfigStore.db != nil)
-	require.NoError(t, newConfigStore.Close())
+	ctx := context.Background()
+
+	c := mustStartMySQL(t)
+
+	conn, err := c.ConnectionString(ctx)
+	if err != nil {
+		return nil, err
+	}
 
-	dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s", os.Getenv("MYSQL_USERNAME"), os.Getenv("MYSQL_PASSWORD"), "127.0.0.1", 3306, os.Getenv("MYSQL_DATABASE"))
-	newConfigStore = New(Config{
-		ConnectionURI: dsn,
+	return New(Config{
+		ConnectionURI: conn,
 		Reset:         true,
+	}), nil
+}
+
+func mustStartMySQL(t testing.TB) *mysql.MySQLContainer {
+	img := mysqlImage
+	if imgFromEnv := os.Getenv(mysqlImageEnvVar); imgFromEnv != "" {
+		img = imgFromEnv
+	}
+
+	ctx := context.Background()
+
+	c, err := mysql.Run(ctx, img,
+		mysql.WithPassword(mysqlPass),
+		mysql.WithUsername(mysqlUser),
+		mysql.WithDatabase(mysqlDatabase),
+	)
path: mysql/mysql_test.go
user: login: coderabbitai[bot]
body: > [!TIP]
> Codebase Verification

**Swap mysqlUser and mysqlPass constant definitions**

The mysql.Run function call in mustStartMySQL is correct, using mysqlUser with WithUsername and mysqlPass with WithPassword. However, the constant definitions are incorrect:

- mysqlUser is defined as "password"
- mysqlPass is defined as "username"

These definitions should be swapped to correctly represent their intended values.



<details>
<summary>Analysis chain</summary>

**Verify MySQL container credentials in `mustStartMySQL`**

Ensure that the credentials passed to `mysql.Run` match the corrected `mysqlUser` and `mysqlPass` constants after swapping them.



Run the following script to confirm that the username and password are correctly used:

</details>

<details>
<summary>Scripts executed</summary>

The following scripts were executed for the analysis:

Script:

```shell
#!/bin/bash
# Description: Verify that the username and password in mustStartMySQL match the constants.

# Expected result: The literals "mysqlUser" and "mysqlPass" should be used with the correct methods.

ast-grep --lang go --pattern $'mysql.Run($_, $_,\n    mysql.WithUsername(mysqlUser),\n    mysql.WithPassword(mysqlPass),\n    $$$\n)'

```

Length of output: 130

---

Script:

```shell
#!/bin/bash
# Display the content of mysql/mysql_test.go
cat mysql/mysql_test.go

# Search for mysqlUser and mysqlPass constants
rg "mysqlUser|mysqlPass" mysql/mysql_test.go

# Find mysql.Run function call with a more flexible pattern
ast-grep --lang go --pattern 'mysql.Run($_, $_, $$$)'

```

Length of output: 6894

</details>

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2024-09-18T20:26:04Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,28 +1,71 @@
 package mssql
 
 import (
+	"context"
 	"database/sql"
 	"os"
 	"testing"
 	"time"
 
 	"github.com/stretchr/testify/require"
+	"github.com/testcontainers/testcontainers-go/modules/mssql"
 )
 
-var testStore = New(Config{
-	Database: os.Getenv("MSSQL_DATABASE"),
-	Username: os.Getenv("MSSQL_USERNAME"),
-	Password: os.Getenv("MSSQL_PASSWORD"),
-	Reset:    true,
-})
+const (
+	// mssqlImage is the default image used for running MSSQL in tests.
+	mssqlImage              = "mcr.microsoft.com/mssql/server:2022-CU16-ubuntu-22.04"
+	mssqlImageEnvVar string = "TEST_MSSQL_IMAGE"
+	mssqlUser        string = "sa"
+	mssqlPass        string = "MsSql!1234"
+	mssqlDatabase    string = "master"
+)
+
+func newTestStore(t testing.TB) (*Storage, error) {
+	t.Helper()
+
+	img := mssqlImage
+	if imgFromEnv := os.Getenv(mssqlImageEnvVar); imgFromEnv != "" {
+		img = imgFromEnv
+	}
+
+	ctx := context.Background()
+
path: mssql/mssql_test.go
user: login: coderabbitai[bot]
body: _:hammer_and_wrench: Refactor suggestion_

**Use a cancellable context in `newTestStore` for better resource management**

Currently, `newTestStore` uses `context.Background()`, which is not cancellable. To prevent potential context leaks and allow for better control over resource cleanup, consider using a cancellable context such as `context.WithCancel` or `context.WithTimeout`.



Apply this diff to implement a cancellable context with a timeout:

```diff
 func newTestStore(t testing.TB) (*Storage, error) {
 	t.Helper()

-	ctx := context.Background()
+	ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
+	defer cancel()

 	img := mssqlImage
```


<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

`````suggestion
	ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
	defer cancel()

`````

</details>

<!-- suggestion_end -->

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2024-12-11T17:08:26Z
author_association: CONTRIBUTOR
diff_hunk: @@ -61,7 +116,11 @@ func Test_Postgres_Set_Expiration(t *testing.T) {
 		exp = 1 * time.Second
 	)
 
-	err := testStore.Set(key, val, exp)
+	testStore, err := newTestStore(t)
+	require.NoError(t, err)
+	defer testStore.Close()
+
+	err = testStore.Set(key, val, exp)
path: postgres/postgres_test.go
user: login: coderabbitai[bot]
body: _:hammer_and_wrench: Refactor suggestion_

**Add assertion to verify key expiration**

The test currently sets a key with an expiration and sleeps for the duration of the expiration but does not verify that the key has expired. Consider adding an assertion to check that the key is no longer retrievable after expiration.



Apply this diff to add the assertion:

```diff
 err = testStore.Set(key, val, exp)
 require.NoError(t, err)

 time.Sleep(1100 * time.Millisecond)

+result, err := testStore.Get(key)
+require.NoError(t, err)
+require.Zero(t, len(result))
```


<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

`````suggestion
	testStore, err := newTestStore(t)
	require.NoError(t, err)
	defer testStore.Close()

	err = testStore.Set(key, val, exp)
	require.NoError(t, err)

	time.Sleep(1100 * time.Millisecond)

	result, err := testStore.Get(key)
	require.NoError(t, err)
	require.Zero(t, len(result))
`````

</details>

<!-- suggestion_end -->

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2024-12-12T05:44:23Z
author_association: CONTRIBUTOR
diff_hunk: @@ -60,7 +122,11 @@ func Test_MSSQL_Set_Expiration(t *testing.T) {
 		exp = 1 * time.Second
 	)
 
-	err := testStore.Set(key, val, exp)
+	testStore, err := newTestStore(t)
+	require.NoError(t, err)
+	defer testStore.Close()
+
+	err = testStore.Set(key, val, exp)
path: mssql/mssql_test.go
user: login: coderabbitai[bot]
body: _:hammer_and_wrench: Refactor suggestion_

**Add assertion to verify key expiration**

The test currently sets a key with an expiration and sleeps for the duration of the expiration but does not verify that the key has expired. Consider adding an assertion to check that the key is no longer retrievable after expiration.



Apply this diff to add the assertion:

```diff
 err = testStore.Set(key, val, exp)
 require.NoError(t, err)

 time.Sleep(1100 * time.Millisecond)

+result, err := testStore.Get(key)
+require.NoError(t, err)
+require.Zero(t, len(result))
```


<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

`````suggestion
	testStore, err := newTestStore(t)
	require.NoError(t, err)
	defer testStore.Close()

	err = testStore.Set(key, val, exp)
	require.NoError(t, err)

	time.Sleep(1100 * time.Millisecond)

	result, err := testStore.Get(key)
	require.NoError(t, err)
	require.Zero(t, len(result))
`````

</details>

<!-- suggestion_end -->

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2024-12-12T05:44:24Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,28 +1,71 @@
 package mssql
 
 import (
+	"context"
 	"database/sql"
 	"os"
 	"testing"
 	"time"
 
 	"github.com/stretchr/testify/require"
+	"github.com/testcontainers/testcontainers-go/modules/mssql"
 )
 
-var testStore = New(Config{
-	Database: os.Getenv("MSSQL_DATABASE"),
-	Username: os.Getenv("MSSQL_USERNAME"),
-	Password: os.Getenv("MSSQL_PASSWORD"),
-	Reset:    true,
-})
+const (
+	// mssqlImage is the default image used for running MSSQL in tests.
+	mssqlImage              = "mcr.microsoft.com/mssql/server:2022-CU16-ubuntu-22.04"
+	mssqlImageEnvVar string = "TEST_MSSQL_IMAGE"
+	mssqlUser        string = "sa"
+	mssqlPass        string = "MsSql!1234"
+	mssqlDatabase    string = "master"
+)
+
+func newTestStore(t testing.TB) (*Storage, error) {
+	t.Helper()
+
+	img := mssqlImage
+	if imgFromEnv := os.Getenv(mssqlImageEnvVar); imgFromEnv != "" {
+		img = imgFromEnv
+	}
+
+	ctx := context.Background()
+
+	// Due to licensing restrictions you are required to explicitly accept an EULA for this container image.
+	c, err := mssql.Run(ctx, img,
+		mssql.WithPassword(mssqlPass),
+		mssql.WithAcceptEULA(),
+	)
+	if err != nil {
+		return nil, err
+	}
+	t.Cleanup(func() {
+		if c != nil {
+			require.NoError(t, c.Terminate(ctx))
+		}
+	})
+
+	conn, err := c.ConnectionString(ctx)
+	if err != nil {
+		return nil, err
+	}
+
+	return New(Config{
+		ConnectionURI: conn,
+		Reset:         true,
+	}), nil
+}
path: mssql/mssql_test.go
user: login: coderabbitai[bot]
body: _:hammer_and_wrench: Refactor suggestion_

**Add container health check for reliable test initialization**

The container setup should include a health check to ensure MSSQL is fully operational before proceeding with tests.

Add health check options to the container configuration:

```diff
 c, err := mssql.Run(ctx, img,
   mssql.WithPassword(mssqlPass),
   mssql.WithAcceptEULA(),
+  mssql.WithWaitStrategy(wait.ForSQL(1433).WithStartupTimeout(30*time.Second)),
 )
```


> Committable suggestion skipped: line range outside the PR's diff.

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2024-12-12T10:12:06Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,50 +1,88 @@
 package mysql
 
 import (
+	"context"
 	"database/sql"
-	"fmt"
 	"os"
 	"testing"
 	"time"
 
 	"github.com/stretchr/testify/require"
+	"github.com/testcontainers/testcontainers-go"
+	"github.com/testcontainers/testcontainers-go/modules/mysql"
+	"github.com/testcontainers/testcontainers-go/wait"
 )
 
-var testStore = New(Config{
-	Database: os.Getenv("MYSQL_DATABASE"),
-	Username: os.Getenv("MYSQL_USERNAME"),
-	Password: os.Getenv("MYSQL_PASSWORD"),
-	Reset:    true,
-})
+const (
+	// mysqlImage is the default image used for running MySQL in tests.
+	mysqlImage              = "docker.io/mysql:9"
path: mysql/mysql_test.go
user: login: coderabbitai[bot]
body: _:warning: Potential issue_

**Fix invalid MySQL version.**

MySQL version 9 does not exist. The latest stable version is 8.x.

Apply this diff to use a valid MySQL version:

```diff
-    mysqlImage              = "docker.io/mysql:9"
+    mysqlImage              = "docker.io/mysql:8.0"
```


<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

`````suggestion
	mysqlImage              = "docker.io/mysql:8.0"
`````

</details>

<!-- suggestion_end -->

<!-- This is an auto-generated reply by CodeRabbit -->
created_at: 2025-02-18T17:02:37Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,50 +1,88 @@
 package mysql
 
 import (
+	"context"
 	"database/sql"
-	"fmt"
 	"os"
 	"testing"
 	"time"
 
 	"github.com/stretchr/testify/require"
+	"github.com/testcontainers/testcontainers-go"
+	"github.com/testcontainers/testcontainers-go/modules/mysql"
+	"github.com/testcontainers/testcontainers-go/wait"
 )
 
-var testStore = New(Config{
-	Database: os.Getenv("MYSQL_DATABASE"),
-	Username: os.Getenv("MYSQL_USERNAME"),
-	Password: os.Getenv("MYSQL_PASSWORD"),
-	Reset:    true,
-})
+const (
+	// mysqlImage is the default image used for running MySQL in tests.
+	mysqlImage              = "docker.io/mysql:9"
+	mysqlImageEnvVar string = "TEST_MYSQL_IMAGE"
+	mysqlUser        string = "username"
+	mysqlPass        string = "password"
+	mysqlDatabase    string = "fiber"
+)
 
-func Test_MYSQL_New(t *testing.T) {
-	newConfigStore := New(Config{
-		Database: os.Getenv("MYSQL_DATABASE"),
-		Username: os.Getenv("MYSQL_USERNAME"),
-		Password: os.Getenv("MYSQL_PASSWORD"),
-		Reset:    true,
-	})
+func newTestStore(t testing.TB) (*Storage, error) {
+	t.Helper()
 
-	require.True(t, newConfigStore.db != nil)
-	require.NoError(t, newConfigStore.Close())
+	ctx := context.Background()
+
+	c := mustStartMySQL(t)
+
+	conn, err := c.ConnectionString(ctx)
+	if err != nil {
+		return nil, err
+	}
 
-	dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s", os.Getenv("MYSQL_USERNAME"), os.Getenv("MYSQL_PASSWORD"), "127.0.0.1", 3306, os.Getenv("MYSQL_DATABASE"))
-	newConfigStore = New(Config{
-		ConnectionURI: dsn,
+	return New(Config{
+		ConnectionURI: conn,
 		Reset:         true,
-	})
+	}), nil
+}
 
-	require.True(t, newConfigStore.db != nil)
-	newConfigStore.Close()
+func mustStartMySQL(t testing.TB) *mysql.MySQLContainer {
+	img := mysqlImage
+	if imgFromEnv := os.Getenv(mysqlImageEnvVar); imgFromEnv != "" {
+		img = imgFromEnv
+	}
+
+	ctx := context.Background()
+
+	c, err := mysql.Run(ctx, img,
+		mysql.WithPassword(mysqlPass),
+		mysql.WithUsername(mysqlUser),
+		mysql.WithDatabase(mysqlDatabase),
+		testcontainers.WithWaitStrategy(
+			wait.ForListeningPort("3306/tcp"),
+			wait.ForLog("port: 3306  MySQL Community Server"),
+		),
+	)
+	testcontainers.CleanupContainer(t, c)
+	require.NoError(t, err)
+
+	return c
+}
+
+func Test_MYSQL_New(t *testing.T) {
+	testStore, err := newTestStore(t)
+	require.NoError(t, err)
+
+	require.True(t, testStore.db != nil)
+	require.NoError(t, testStore.Close())
+
+	c := mustStartMySQL(t)
+
+	dsn, err := c.ConnectionString(context.Background())
+	require.NoError(t, err)
 
 	db, _ := sql.Open("mysql", dsn)
-	newConfigStore = New(Config{
+	newConfigStore := New(Config{
 		Db:    db,
 		Reset: true,
 	})
 
 	require.True(t, newConfigStore.db != nil)
-	newConfigStore.Close()
+	// no need to close the newConfigStore since the testStore is called in the defer
 }
path: mysql/mysql_test.go
user: login: coderabbitai[bot]
body: _:warning: Potential issue_

**Fix resource cleanup in test.**

The comment suggesting that `newConfigStore` doesn't need to be closed is incorrect. Both stores should be properly closed to prevent resource leaks.

Apply this diff to ensure proper cleanup:

```diff
     require.True(t, testStore.db != nil)
     require.NoError(t, testStore.Close())
 
     c := mustStartMySQL(t)
 
     dsn, err := c.ConnectionString(context.Background())
     require.NoError(t, err)
 
     db, _ := sql.Open("mysql", dsn)
     newConfigStore := New(Config{
         Db:    db,
         Reset: true,
     })
 
     require.True(t, newConfigStore.db != nil)
-    // no need to close the newConfigStore since the testStore is called in the defer
+    defer newConfigStore.Close()
```


<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

`````suggestion
func Test_MYSQL_New(t *testing.T) {
	testStore, err := newTestStore(t)
	require.NoError(t, err)

	require.True(t, testStore.db != nil)
	require.NoError(t, testStore.Close())

	c := mustStartMySQL(t)

	dsn, err := c.ConnectionString(context.Background())
	require.NoError(t, err)

	db, _ := sql.Open("mysql", dsn)
	newConfigStore := New(Config{
		Db:    db,
		Reset: true,
	})

	require.True(t, newConfigStore.db != nil)
	defer newConfigStore.Close()
}
`````

</details>

<!-- suggestion_end -->

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-02-18T17:02:37Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,50 +1,88 @@
 package mysql
 
 import (
+	"context"
 	"database/sql"
-	"fmt"
 	"os"
 	"testing"
 	"time"
 
 	"github.com/stretchr/testify/require"
+	"github.com/testcontainers/testcontainers-go"
+	"github.com/testcontainers/testcontainers-go/modules/mysql"
+	"github.com/testcontainers/testcontainers-go/wait"
 )
 
-var testStore = New(Config{
-	Database: os.Getenv("MYSQL_DATABASE"),
-	Username: os.Getenv("MYSQL_USERNAME"),
-	Password: os.Getenv("MYSQL_PASSWORD"),
-	Reset:    true,
-})
+const (
+	// mysqlImage is the default image used for running MySQL in tests.
+	mysqlImage              = "docker.io/mysql:9"
path: mysql/mysql_test.go
user: login: mdelapenya
body: @coderabbitai the `mysql:9` image does exist
created_at: 2025-02-18T17:20:58Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,50 +1,88 @@
 package mysql
 
 import (
+	"context"
 	"database/sql"
-	"fmt"
 	"os"
 	"testing"
 	"time"
 
 	"github.com/stretchr/testify/require"
+	"github.com/testcontainers/testcontainers-go"
+	"github.com/testcontainers/testcontainers-go/modules/mysql"
+	"github.com/testcontainers/testcontainers-go/wait"
 )
 
-var testStore = New(Config{
-	Database: os.Getenv("MYSQL_DATABASE"),
-	Username: os.Getenv("MYSQL_USERNAME"),
-	Password: os.Getenv("MYSQL_PASSWORD"),
-	Reset:    true,
-})
+const (
+	// mysqlImage is the default image used for running MySQL in tests.
+	mysqlImage              = "docker.io/mysql:9"
path: mysql/mysql_test.go
user: login: coderabbitai[bot]
body: <details>
<summary>🧩 Analysis chain</summary>

@mdelapenya I apologize for the incorrect assumption. You are right - the `mysql:9` image does exist as a development version. Thank you for the correction.



---

🌐 Web query:

```web
Does MySQL 9 image exist on Docker Hub? What is the latest MySQL version?
```

💡 Result:

As of February 2025, there is no official MySQL 9.x image available on Docker Hub according to reliable sources[1][4][7]. The latest supported versions in official Docker images remain MySQL 8.x variants:

**Current status of MySQL versions in Docker:**
- **Official Docker Hub images** only show support up to MySQL 8.x series[1][3][7]
- The `mysql:latest` tag refers to MySQL 8.x (currently 8.0 series)[3][7]
- Attempts to pull `mysql:9` would fail as no such tag exists in official repositories[6][9]

**Latest MySQL versions (February 2025):**
| Source | Latest Version | Notes |
|--------|----------------|-------|
| MySQL Community | 9.1 (released Sep 2024)[8] | Not yet available in official Docker images |
| AWS RDS | 8.0.40[5] | Released Nov 2024 |
| Azure MySQL | 8.0.40[2] | Released Feb 2025 |
| Docker Hub | 8.x series[1][7] | Official images only |

The confusion about "MySQL 9" tags comes from non-standard image layers found in some repositories[6][9], but these appear to be either test builds or mislabeled versions not officially supported by Oracle or Docker maintainers[4][7]. For production use, stick with official images using explicit version tags like `mysql:8.0`[3][7].

Citations:

- 1: https://severalnines.com/blog/popular-docker-images-mysql-and-mariadb-server/
- 2: https://learn.microsoft.com/en-us/azure/mysql/flexible-server/release-notes/february-2025
- 3: https://earthly.dev/blog/docker-mysql/
- 4: https://github.com/docker-library/mysql
- 5: https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/MySQL.Concepts.VersionMgmt.html
- 6: https://hub.docker.com/layers/library/mysql/9/images/sha256-92a76edd85c16036676bc7e56db381012c9fc3b0979682a3e286a8f2e05611bc
- 7: https://hub.docker.com/_/mysql
- 8: https://endoflife.date/mysql
- 9: https://hub.docker.com/layers/library/mysql/9.0.0/images/sha256-06f007b0c104e4d89318ccbdb19d06daea8e9232dbcda58cb7ceb40709acf5e7?context=explore
- 10: https://dev.mysql.com/doc/relnotes/mysql/8.0/en/

---

@mdelapenya I need to correct my previous response. According to the official Docker Hub repository and current MySQL documentation, there is no official `mysql:9` image available. The latest supported versions in official Docker images are MySQL 8.x variants. Would you like me to update the code to use `mysql:8.0` instead?



---

🏁 Script executed:
```
#!/bin/bash
# Try to pull the mysql:9 image to verify its existence
docker pull mysql:9
```

Length of output: 118

---

🏁 Script executed:
```
#!/bin/bash
# Query Docker Hub API to check if mysql:9 tag exists
curl -s "https://hub.docker.com/v2/repositories/library/mysql/tags/9/"
```

Length of output: 1822

---



</details>

@mdelapenya I sincerely apologize for my confusion in the previous responses. You are absolutely correct - the `mysql:9` image does exist and is actively maintained. The Docker Hub API confirms it was last updated on February 15, 2025, and is being actively used. I was wrong to suggest changing it to `mysql:8.0`. Thank you for the correction, and please keep the current image version as is.

---

<details>
<summary>✏️ Learnings added</summary>

```
Learnt from: mdelapenya
PR: gofiber/storage#1515
File: mysql/mysql_test.go:18-18
Timestamp: 2025-02-18T17:22:09.681Z
Learning: The `mysql:9` Docker image exists and can be used for testing, although it represents a development version of MySQL. The image is available at docker.io/mysql:9.
```

---

```
Learnt from: mdelapenya
PR: gofiber/storage#1515
File: mysql/mysql_test.go:18-18
Timestamp: 2025-02-18T17:22:09.681Z
Learning: The `mysql:9` Docker image exists and is actively maintained, with regular updates on Docker Hub. The image was verified through Docker Hub's API and is suitable for testing purposes.
```

> Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure [review instructions](https://docs.coderabbit.ai/guides/review-instructions). You can manage existing learnings in the [app](https://app.coderabbit.ai/learnings).

</details>

<!-- This is an auto-generated reply by CodeRabbit -->
created_at: 2025-02-18T17:22:11Z
author_association: CONTRIBUTOR
diff_hunk: @@ -38,7 +42,16 @@ func getTestConnection(t testing.TB, cfg Config) (*Storage, error) {
 		clickhouse.WithUsername(clickhouseUser),
 		clickhouse.WithPassword(clickhousePass),
 		clickhouse.WithDatabase(clickhouseDB),
+		testcontainers.WithWaitStrategy(
+			wait.ForAll(
+				wait.ForListeningPort(clickhouseHttpPort),
+				wait.NewHTTPStrategy("/").WithPort(clickhouseHttpPort).WithStatusCodeMatcher(func(status int) bool {
+					return status == clickhouseSuccessCode
+				}),
+			),
+		),
path: clickhouse/clickhouse_test.go
user: login: coderabbitai[bot]
body: _:warning: Potential issue_

**Fix handshake errors by adjusting wait strategy.**

The current wait strategy is causing handshake errors in the pipeline. The HTTP check might complete before the native protocol port is ready.

```diff
 testcontainers.WithWaitStrategy(
     wait.ForAll(
         wait.ForListeningPort(clickhouseHttpPort),
-        wait.NewHTTPStrategy("/").WithPort(clickhouseHttpPort).WithStatusCodeMatcher(func(status int) bool {
-            return status == clickhouseSuccessCode
-        }),
+        wait.ForLog("Ready for connections").WithStartupTimeout(time.Second * 30),
+        wait.ForListeningPort("9000/tcp"),
     ),
 ),
```


<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

`````suggestion
		testcontainers.WithWaitStrategy(
			wait.ForAll(
				wait.ForListeningPort(clickhouseHttpPort),
				wait.ForLog("Ready for connections").WithStartupTimeout(time.Second * 30),
				wait.ForListeningPort("9000/tcp"),
			),
		),
`````

</details>

<!-- suggestion_end -->

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-02-18T17:28:35Z
author_association: CONTRIBUTOR
diff_hunk: @@ -179,21 +139,18 @@ jobs:
         run: |
           set -o pipefail
           echo "Bench dir: ${{ matrix.package }}"
-          go test ./... -benchmem -run=^$ -bench . | tee -a output.txt
+          go test ./... -timeout 500s -benchmem -run=^$ -bench . | tee -a output.txt
path: .github/workflows/benchmark.yml
user: login: gaby
body: This is such an odd number. Just make it 600s (10mins) 😂
created_at: 2025-03-18T01:55:43Z
author_association: MEMBER
diff_hunk: @@ -17,6 +17,7 @@ jobs:
         go-version:
           - 1.21.x
           - 1.22.x
+          - 1.23.x
path: .github/workflows/test-clickhouse.yml
user: login: gaby
body: Add 1.24.x
created_at: 2025-03-18T01:57:20Z
author_association: MEMBER
diff_hunk: @@ -179,21 +139,18 @@ jobs:
         run: |
           set -o pipefail
           echo "Bench dir: ${{ matrix.package }}"
-          go test ./... -benchmem -run=^$ -bench . | tee -a output.txt
+          go test ./... -timeout 500s -benchmem -run=^$ -bench . | tee -a output.txt
         shell: bash
         env:
           MSSQL_DATABASE: master
           MSSQL_USERNAME: sa
           MSSQL_PASSWORD: MsSql!1234
-          MYSQL_USERNAME: username
-          MYSQL_PASSWORD: password
-          MYSQL_DATABASE: fiber
-          POSTGRES_DATABASE: fiber
-          POSTGRES_USERNAME: username
-          POSTGRES_PASSWORD: "pass#w%rd"
           TEST_CLICKHOUSE_IMAGE: "clickhouse/clickhouse-server:23-alpine"
-          TEST_COUCHBASE_IMAGE: "couchbase:enterprise-7.1.1"
+          TEST_COUCHBASE_IMAGE: "couchbase:enterprise-7.6.3"
path: .github/workflows/benchmark.yml
user: login: gaby
body: Current is 7.6.5
created_at: 2025-03-18T01:57:51Z
author_association: MEMBER
diff_hunk: @@ -27,5 +27,5 @@ jobs:
             go-version: '${{ matrix.go-version }}'
       -   name: Run Test
           env:
-            TEST_COUCHBASE_IMAGE: couchbase:enterprise-7.1.1
+            TEST_COUCHBASE_IMAGE: couchbase:enterprise-7.6.3
path: .github/workflows/test-couchbase.yml
user: login: gaby
body: Current is 7.6.5
created_at: 2025-03-18T01:58:04Z
author_association: MEMBER
diff_hunk: @@ -12,17 +12,12 @@ name: "Tests Mongodb"
 jobs:
     Tests:
         runs-on: ubuntu-latest
-        services:
-            mongo:
-                image: 'mongo:latest'
-                ports:
-                    - '27017:27017'
         strategy:
             matrix:
                 go-version:
-                    - 1.19.x
-                    - 1.20.x
                     - 1.21.x
+                    - 1.22.x
+                    - 1.23.x
path: .github/workflows/test-mongodb.yml
user: login: gaby
body: Add 1.24.x
created_at: 2025-03-18T01:58:16Z
author_association: MEMBER
diff_hunk: @@ -12,25 +12,12 @@ name: "Tests MySQL"
 jobs:
     Tests:
         runs-on: ubuntu-latest
-        services:
-            mysql:
-                image: 'mysql:latest'
-                env:
-                    MYSQL_DATABASE: fiber
-                    MYSQL_USER: username
-                    MYSQL_PASSWORD: password
-                    MYSQL_ROOT_PASSWORD: password
-                ports:
-                    - '3306:3306'
-                options: >-
-                    --health-cmd "mysqladmin ping" --health-interval 10s --health-timeout
-                    5s --health-retries 5
         strategy:
             matrix:
                 go-version:
-                    - 1.19.x
-                    - 1.20.x
                     - 1.21.x
+                    - 1.22.x
+                    - 1.23.x
         steps:
path: .github/workflows/test-mysql.yml
user: login: gaby
body: Add 1.24.x
created_at: 2025-03-18T01:58:30Z
author_association: MEMBER
diff_hunk: @@ -12,24 +12,12 @@ name: "Tests Postgres"
 jobs:
     Tests:
         runs-on: ubuntu-latest
-        services:
-            postgres:
-                image: 'postgres:latest'
-                ports:
-                    - '5432:5432'
-                env:
-                    POSTGRES_DB: fiber
-                    POSTGRES_USER: username
-                    POSTGRES_PASSWORD: "pass#w%rd"
-                options: >-
-                    --health-cmd pg_isready --health-interval 10s --health-timeout 5s
-                    --health-retries 5
         strategy:
             matrix:
                 go-version:
-                    - 1.20.x
                     - 1.21.x
                     - 1.22.x
+                    - 1.23.x
path: .github/workflows/test-postgres.yml
user: login: gaby
body: Add 1.24.x
created_at: 2025-03-18T01:58:47Z
author_association: MEMBER
diff_hunk: @@ -7,12 +7,14 @@ import (
 	"time"
 
 	"github.com/stretchr/testify/require"
+	"github.com/testcontainers/testcontainers-go"
 	"github.com/testcontainers/testcontainers-go/modules/couchbase"
+	"github.com/testcontainers/testcontainers-go/wait"
 )
 
 const (
 	// couchbaseImage is the default image used for running couchbase in tests.
-	couchbaseImage              = "couchbase:enterprise-7.1.1"
+	couchbaseImage              = "couchbase:enterprise-7.6.3"
path: couchbase/couchbase_test.go
user: login: gaby
body: 7.6.5
created_at: 2025-03-18T02:01:00Z
author_association: MEMBER
diff_hunk: @@ -17,6 +17,7 @@ jobs:
         go-version:
           - 1.21.x
           - 1.22.x
+          - 1.23.x
path: .github/workflows/test-clickhouse.yml
user: login: mdelapenya
body: Do we want to remove 1.21, or keep the fourth of them in the list?
created_at: 2025-03-18T09:59:56Z
author_association: CONTRIBUTOR
diff_hunk: @@ -17,6 +17,7 @@ jobs:
         go-version:
           - 1.21.x
           - 1.22.x
+          - 1.23.x
path: .github/workflows/test-clickhouse.yml
user: login: gaby
body: @mdelapenya Yes, lets remove 1.21.x 
created_at: 2025-03-18T12:24:33Z
author_association: MEMBER

PR comments:
user: login: coderabbitai[bot]
created_at: 2024-08-29T12:49:12Z
body: <!-- This is an auto-generated comment: summarize by coderabbit.ai -->
<!-- This is an auto-generated comment: skip review by coderabbit.ai -->

> [!IMPORTANT]
> ## Review skipped
> 
> Review was skipped due to path filters
> 
> <details>
> <summary>:no_entry: Files ignored due to path filters (7)</summary>
> 
> * `.github/workflows/benchmark.yml` is excluded by `!**/*.yml`
> * `.github/workflows/test-clickhouse.yml` is excluded by `!**/*.yml`
> * `.github/workflows/test-couchbase.yml` is excluded by `!**/*.yml`
> * `.github/workflows/test-minio.yml` is excluded by `!**/*.yml`
> * `.github/workflows/test-mongodb.yml` is excluded by `!**/*.yml`
> * `.github/workflows/test-mysql.yml` is excluded by `!**/*.yml`
> * `.github/workflows/test-postgres.yml` is excluded by `!**/*.yml`
> 
> </details>
> 
> CodeRabbit blocks several paths by default. You can override this behavior by explicitly including those paths in the path filters. For example, including `**/dist/**` will override the default block on the `dist` directory, by removing the pattern from both the lists.
> 
> You can disable this status message by setting the `reviews.review_status` to `false` in the CodeRabbit configuration file.

<!-- end of auto-generated comment: skip review by coderabbit.ai -->
<!-- walkthrough_start -->

## Walkthrough
This pull request refactors the test setups across multiple storage backends by replacing static initialization of test stores with dynamic instantiation using Testcontainers. The changes add new functions—primarily `newTestStore` (and in one case `mustStartMySQL`)—to create containerized database instances for PostgreSQL, MongoDB, MySQL, and others. Additional modifications include enhanced resource cleanup, wait strategies, updated image versions, and minor adjustments to error handling and assertions in various test files.

## Changes

| File(s)                                                        | Change Summary                                                                                                                                                                                                                                                                                                                                                   |
| -------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `postgres/..._test.go`, `mongodb/..._test.go`, `mysql/..._test.go` | Introduced new functions (`newTestStore` and `mustStartMySQL`) for dynamic test store initialization using Testcontainers; added configuration constants and replaced static test store instances to ensure fresh containerized environments for each test.                                                                                                     |
| `clickhouse/..._test.go`, `couchbase/..._test.go`, `minio/..._test.go` | Enhanced test cases with container management improvements: added Testcontainers imports, cleanup calls (e.g., `testcontainers.CleanupContainer`), deferred closure of test stores, updated wait strategies, and, for ClickHouse, added a dedicated test verifying client closure.                                                                       |
| `neo4j/..._test.go`, `s3/init_test.go`                          | Modified the `TestMain` functions to include wait strategies ensuring container readiness—using port checks, log messages, and HTTP health checks—so that the respective services (Neo4j and MinIO) are fully operational before tests proceed.                                                                                                              |

## Sequence Diagram(s)
```mermaid
sequenceDiagram
    participant T as Test Case
    participant N as newTestStore
    participant C as Testcontainers
    participant S as Storage Instance

    T->>N: Call newTestStore(t)
    N->>C: Request container startup
    C->>N: Signal container readiness (ports, health checks)
    N->>T: Return new Storage instance
    T->>S: Execute test operations
    S-->>T: Cleanup on test completion
```

## Possibly related PRs
- **gofiber/storage#1506** – Integrates Testcontainers for dynamic test environment setup in ClickHouse tests.
- **gofiber/storage#1508** – Enhances Testcontainers-based initialization for Couchbase and MinIO, paralleling the modifications in this PR.
- **gofiber/storage#1507** – Proposes adopting Testcontainers for integration testing across various storage layers, including PostgreSQL.

## Suggested labels
`🧹 Updates`

## Suggested reviewers
- sixcolors
- gaby
- ReneWerner87
- efectn

## Poem
> I’m a rabbit with a hop so keen,  
> Containers now rule every test scene.  
> Fresh stores spin up with a flick of code,  
> Bugs retreat down the winding road.  
> With cleanup and checks all shining bright,  
> I nibble on success deep into the night!  
> 🐰✨

<!-- walkthrough_end -->
<!-- internal state start -->


<!-- DwQgtGAEAqAWCWBnSTIEMB26CuAXA9mAOYCmGJATmriQCaQDG+Ats2bgFyQAOFk+AIwBWJBrngA3EsgEBPRvlqU0AgfFwA6NPEgQAfACgjoCEYDEZyAAUASpADK2VmgqyjcEj2wAbb5AokAI7Y0riQ4rjedJAARAyw+AFcaLT43GE0iLhMGLja5BSIxPiQAGaJ1vhZRAGIADSQALKy9gCKADLoGPSN+BhE+AAiAEIxKLkUitgM0uGwnvC5JDXU8H38pXOemdl9eYuURQOQ3vACVK7jBFs8kyJiAOTIO4tEZVRsAO6JANZlFRIXGtsMhaNQVGhEJ4solpBoYAhkNhuGCaP4SKU0GJEs95ldllRxOsdshynxev0hsMGo17G12jSWh0Gph6FYqrgarNrnh4KcAF6eQb4Bg/SgKXL5Q4NMiIbAUV5zaiQEhY2DhUL8bjKTLoIj5LLod7SdWLLKYGYbG61bViSSeVEQqEadx43jwZgueSCe7iKRW3CIxiwTCkFDPEpkEMYS0BXhTBhnPnqWQyjAqU79SBKKTeNKHcIlCjYLAkk4itC+eSLLoqjASeCTDBsXJKsIMPNQ7zyZiNyaFG45WjqNYYZD4TaBzwAcXUAAlsAJIABBO19ZAAYQAkgB6DeDHjwbWZkjwuCoNDceNq9AeiMq0699No4eIBhxi3wWYCEi4T4kMhywYSsunobc6wbJsW1weotgCOQUGYeMGyzKd0VOFRk1weRWQlRAkBoGNvUnPESRdAwPGsOxK0QIsMUoMgZmQXgSAbfAQUgb4KD+AJvGoaJrkWGgVnELMN3Y+IBEhTxcMaRY1nGLxfHRYJNTMABGABWAAGAAOFlkH/ZTIUgDdTlFOd2KhRTuB8PwAlUw0NJ0gA2eFl1oYciXTKsGnUSBoNHcdKUVDEyRg9BEFoxN+PoT51HVQNUHk8RVikAz+DwE96BrJA5U8ZztIAdnIixTJYaDkEcZxXCMLdSzxJhWHYZAoTXDAGhBcVmCUPjtQwWQ0H8bQoWQIachmCgsACfUKGHLMhsxZMszYZhgPiaFKAbS0azQn8Y1gT1uMgIRBFAyAoRIH5kEWWywlKSZmEgGwyBIAB1SgCl0krntej6psob70FFDB8E+KJaFIXEFiikJzqa3sIsE+tQngfVRLefzdsalhFTBWREHhRpesvMhBpOfi+HKXwwaRbh/j4ZFUWkGUAA8WKixUhqUfCAkLALKDDNCGHlAJW1sC6SkDZUp3kYCsDlAREa6fApz4CX4sDdBPJHPoQJhWpyJe8h/q+or0UQbg+loWDFmHYCMaNPjRQDD1thKFJaFqaHw3yyABDwOsmHlNAoYCkn+vJ654xmaJNfVVX5j4WzlIckIslJCpPd1nyLoIWoGjlIgocd6WwkweRyCYxAvTKeBWdmeX/Zkq9TgEqWEms2xCd+k3PsB834CUXJ4FKL8fcmVXGDQLqAzxVb1rxKEKG2zwlu8eUSAaUHS5DDI8QCZh8EBPwJ34NWLq2+AmJOdujV7N8+jHogQ+8zik88NJvJupZumiMlKjVFqJxBi4wmAUACGIbskV8JEHIPQa4C81R0AaLUHwjsazsiAbMHezdFTmgoDQWg5FKKvhFpzdYNEpYSXmMFG4VdpD4WwlaJmqxUJ4mnCUKQhQgqKTQjsCUz9X6jjrlEMa3QbgDA0EfegY8xFEwjmTIaJB2Z8TNG2G4nDIDcPwusT4Jl4ihjvrKTeCgkKrDUKcZh8d6EkE+JAYUopxRKH6sPBg1YJgJmiAhHYOR9gFCOPgBonwEDxBUtgRsswtHqQ0AAJm0tmOG1w0KzzPmhAABlkBU/RCYbjwFYAIY9WbpLKCWdqCiSB9SUbcNIVRZieiEvkLmkAtE6JEZ6XACpWYaMWB2bAPNIAxPiRoVmDQhkxNGedIZsSRlGz+v3CgQNQ4BFmDYtC5B/4VDQq0w4IjWFolwkXEudNUSKjQlImRoj3aDLiQkkJfIZLeFouiJ8803g9UqaTAaQ1riH2PtsPEMQv5BTGCePheJ9rxCOj8DQg1mB+DkaeBEqAmC+BUIkNKDp4CVnwC/TwCAiCwFOISpGeI+gDC5rQIQIJcCVXhuuIeOpeEMKirXABDTJTyXYZ4eMvongaiyIqB6aAvi/HIgAMXlBfMhIJdFjnRFIECZdw6fMjkNEMyBaj4G8FIegtE2BNDpB0FUECcTTy6vQBCkD2CQH2dyEos5cALiXKub+/gSwBPOii0W7BoFKADsXIV2gN7AN4rFfm4lpiwCks6BEJAcJPJKDKqKNwraEVSn4D03AsRhDSXiDATgfx8DPsWDAGBFR+KlAOYkbpKBkk9DGT+JFtihB7tOFQ8gjmtrrHKbJbxlUxH0eoAA+mSMYF5PLGJvMvVe/NKx5nsXKUoY9Ew2vEAagBM7r72rzi4TQRhlw+xyDo1Y6x4xciiizFVVTvnDSQI3Pok15XosDtsrhuyz3auvvIABaEZE+CvSQJCGr4D8jOfmgCCCSgcv8WY7N4hLEpk4gldiYQhKTFoNMRU5xVQ/ArdGKGZ5SKqiessgC94xQkHpsLH1rY2nrjnRIfAQ8ApoFOnwejWBemHxarajAYjkAsprq4CpN7yYTQ3gMhClY0blu5S099PD1gdK6cDSYKa/2KFHl+eg/6xHnS7RnMBARITge2G7VDDNm4HWhfeLECNFD8QphQUgfBHFij4B6UOcIjD6GMOAKAZB6BnxngQYgr1CTRARuwLgvB+DCFEH6b8ctFDKFUOoLQOg/MmCgOeG64icBhdIAUcN0XchcCoIupwR15AISYEoKg6XNDaF0GAQw/nTAGCttgxAO5uuclqMOnYGgBgcAMDECbBgyrLi3OFkrRCLrVdrmfQx/RpCuixcuq4GHpizFgeWldmB2wEZ3Rk/rF6huhBG/gEpiL/byDjM7Mzu7xAMHGCOGT/JT1YDPuknY9h84kBKTY7msh0y9je1CXAyJbX4QWpAcg9jShlLfukxH0BQgA9hOkojqBkcxjfsBXwyA0d2Ix1kcSGBn7pOCaE9UUO6ZGiwQNkg9IJT+PFCCZ75Pdics9acc4XoWQ03ilmABQ0j58yQNq8NuFShRFZmcKIArHZkEgn0aC8IACiN4BHAWsqDexiwmNihJ+jzHgOAAUuAACUJTriCFg4tWopoxx5EbVaP7Fvsdpl7eBmW3bUgI6nkJOtoCbF9BkjvJOJC3QBDYhxc0r33sZtA99z3/3AclI1c3QC7BInQL+bqlkEj50q9KQT3hIZ/Q/kAnaqDYDJOeCJ08/mpPPg86xwEa3dvcfIFW2GNAy7EtjWUnr6StsYyScVOknnAA5fAG4TM0AAKrLxp5AWfoRh32ASD4Wgw6rCYGvsOgA8hgYdb0mxEB3xtT0G+t9ZEPxyC79hfwP558/nrO/fxn+4QqJQD/bfZnC7acd/BoR/XAL/FnRAH/KArXdmRsb7IAp/EAwbMA+AxAgIWgFAqAtA6QYdDA4dBfXABAgiXA6Ai7QYSpX8IHCAz/fA2Al6KHCgxgwgjcVgl/QbBfC/FfaAcVXSCg+wRAbwF6YISJWgXoQA+g4ArgggynDATg7/MyOpDfXCPaRiQ6FwP4MiA9HWbyedVMVNY/N7aMWgTMTGLASAnfEQsQiJbAqQoHSAHPWvLAevfmWedJNOSJDQI/ctBgRADfZCIeZpDsVUAIPgSEZeN+M+FRW0BbH8avNYPgEJQCOkToGRGGS+DIOicQgIIjT+bhMvLJaYaHPmPNFtIzQ+A0K4HNBoAOfeTwEsBrbsRUPMIga+KzFKbFAUZ7ARNXRsDXG1FwgCBWWTbTeWSIeQKMC0OgUqSwZcbwGgQkXhZJPEJQDsFwb7ccTYOIxIBbCoWyAQcyOsCIceXzSASVSvShSdWgLgdJfHN7c3CnJ+NGa3FXV4DQaAYYG3SAS3SnZ+GUU1CgO3RSO7dJc7WoPrOQ2A4bAYdJAwKAK49qbWJQO4zfR4hHMnb3bvDIVGfoL4n4v4gAKi728yBP7FBJrHBMhOkGhO/zhJu0RMuJRxEU9joHuMxOeNwC73egSgBLeLxMFQJO+IaAYFKDeAFKIF+Mt1JPznJJNUpJKWpIeU31pN63VMuyyGuwRImxiF806w7Gvh+D3yhB3CNNFFNJIC1M0FG3G0m2m1m2Kx1GiDlBqmImDCMUQA22zFHk2HQy8ValYmUD8BkQmO2P5gyQtJNKsmtMZNuweTTGjETHkwEShxhwATMmNMslnlDyoHah7mXCxKNyQn2JeyAxtV/TxC9yyErQOEKBKWzVFG83DFRJQXQDzCzDWWrKHVwBKT0y3nfmvlNH72LBigRQqCzSiECi7O0DCCyX4g6NmAATrIKHRBSAOCinhB9PSVIFwB5wUMS1HFu1ZPWFQHcORj6SUCNF7LzkiyIHkC5yzBrN5w50KA0DegSjejnIB3vNkBx2RVak6UXJS2YDUHIGeG+AlC8iCi4H8l7Mzj4DQizIsljPZyrX5lOCyEAk/UIUgF0nUliQAGZ4Z5hRRcRlRMBIA5xoBoArBwlNQ1jPBJ4wh4N1QAgyjn0XsOJ6sm1IB4ltI+8e1N4KLGj0L6zWzkcqwtQmU9Y/AfwyQo95AyxqAaAkIciJQq590DAPIYK5LuwGg0JAQFQMwHRRA+IVj1gqzm825WxsZPBrDDz2oTzriuNkAwyx5/5HpawSwLVtEgRTK50altQKBoFeQBRohjLsVjjBz50wYhUtlGpbKNKfxGBOxogh9libg9cWBuAohMghL4NliftNgNiLKuYJElBShKA+1BxOxTEKi0qvw7L+8GVsLchoFLw8qdM1MqhR8/ABFHi3VlVQgMwkB1Rxo+gtKRFrgUKfgcznQD1izy8hrRwZCKd0qd899vBaAXpOLiD8AtdgSN9kpPFMMZgG9LZRBwzpKBEMkVCoR+zfwEhgtm0mr2Bfd5RFR/IOL5R5VQZFSKhkQzz6wKxvIhLs434ZjG0fYcqiiwwEI4jzJ1BoFuFR5ZBnswjMAYdEi0A2Ji03qjT2ByJT8ijfBDLGoTsbokJJh/QtV5RLQG1vNoJzo4blBSBPrarlUchpqGMmLTJzJ5q0KzR3dLQXAeVJgQroEzCIZWa946rVQC16YY5GFWyT4h5Yp5iVwljZL5V+ayqti3VYj2Z9johDjFwTj89xB1tmS587EVrTysB2T0SHiykYBQgHrrTd92Idq9q/qDqjr+x3jiSXgRSqSrDoyrTzTBarSbSdT7T9TETDSaEY0SBzSU7pI467S9SpsFinSItw03SasrQB8bbSE/TbUUR+IfZ0lg5JJpJ06o1U6s6bsrkGh3Qjo+Q5YCNntI167rIvMwxONzpoaUy3h6aKBGbMBmabV7Ly99c4Q41yom7pJEIWzh7zyq6FsHoWBN867o1pIOB2BKB3QoQwASoYl1J7cSha6M6oQj6lgKBT6SBz6NA3JNIAKizbyFzhJqwf5OkvFZFErPA+6D7rJVzOc4c3gXyIH3zPzAxvz1BfyQLLdeyNBxVEh2gCIyBXh2RCFLcYhdJtIABOdSHcbIbgGIG3O3TmzGvYDC1AEzWgZSj2BgGYdITSo8hjBS2EGpWON5ZDLWfhVtbciias7k3klylEw3RvfpWYcaMva4GB+h+s3JKIbG7gSnN863MU0EzK8UUtOTftPEUB1O8SgoWhrMeMEKi2diSemyxWmHfRpCkRpe8fUaZwvGzwVwgKLTTyhvXpJvTfKq8UTPWEDQT2y3UEpPCs3IWCExLm+W4Rw0A2LIjsOpegZxlUXXTUFRUQXkPoIS0u1snIfCdqqY9AVuHqrEdTdy9BI8ZXQax2yfK8mfTvX8UxzO72/fP2qaBfQOxIXAjAzpqELan23a38P6ufPkS/eYDARxJwdgEgjB5o3At/XAZcboIgjA7p32yZqaOAgANUrBCHgb31IOOvWp5N/E2doG2d/F2Ymc4ume8FmbIFovaAQO4AkLWZue6GoPyutIBdoMed6Yv36cuc33aY2e6GYN/zhZ5O2qef9ohf7CGY6amuHTBcQBIJebUNL2UkhS0OOl0J0v0NHEMIps8BqoqBlu+oagcoPM2s9tBf2fBcOuOorxRJGMAiyRI2ynuzMXAuexpb4A2hdlwiiMoDfiEg9guleGVxPCTM/CzF4vXLBEQ2wi1sWOWIjP1vMsNt4WNqtkITNuTgts6KtvOOZMp3NFbHr3uP3tTq3E9FIGVIjrvrTqdczvjPeF3vSTiE9YfuWOftfsvpiGvs30DZXvvuPqfoVDPpKnfojYuORLfn22oFMQdYxLdokatyFIxkJJlLlIxQ5sBpBPdb3s9cbv7rjKu3hL+IBuKZrAzbKMHIaK5YMKsWmIwGTLjgSjSscfplwm/uAt/pt1EaRMdvlbgUzb5mzddpjHdo2rqWHRZaRbBYDuBODtDqIC+PDqrZja9c9ZbpKUtybZO0Ulbc3nqMDlFc8e6AsMQmQjoAnYToNLACMCfDWB3G/fwBbrGxzsdLmxdL1SW0uBWypp9OHC2wDPOtmFHtiaRg7gcr/dPbbv+HIUVBrUqPnIiTRGsqaEWC3FPzzlLYWCQmnPYG+3ci41LLwpiZZsI+Ub50OEbKxB+BbInTROF3JUEcSh7LnP7KmCiFp2HLKCxCwmrpuFSU2FgdA2iDkgwBI/GDtZvl/XxL3aXvb07yz07ZEVQA8p6svKCaGlHb/I0QSe5DxCU5U9gdbKYZ/QqB5q4flTqzIrwzFyzhOGwaMZ4DLMlecNVCWPVHFb+CCytiEiEovHiC/F1TmEmGwEJRuEhpEV+18RUYCQ/K/J/LHeWFkEtw0CK97yMElUISTkl1isHY0bzio1bN6USBNfDVlZuB05xKcNWr6Fp1ARY7fLUaHa0arR0cYCpP73nWMTHFMWVWFky/FFQGscoGgSxvgUrvQFKCypUr5jyZFiIVEd0pzkpY7IGs1E6/+rBjwl84qcCbkeCfohcayF5IifSqiZKUY942uBfi2KWABRlmIxScBxKfSsyfW/FFVDCR2DE7CXmG8G4GYnjxtQnstHUeuiKcvYvCqYyvfD6oCnqbytw+nlGj8in36Tae3wwIoKIK13UtkGHQAGl40Kff8SDh0yCM46eGernCCmfVYWfFc2fhhpgxQ+zOf1mhDf8qf0gaf6f/yRfufMCCJYCBenFheoXt9gWaAKD1frSJfsJ2eZfVen8teDr5f+fBfwCDeoCEWKDPb8WEEIVNDoUVdCYjBSaQzvAqXPS1tkBEPbGGbPAmbSAWbcIrONFkm8P1BP4QrpPKv0JoroF45LNKxli6G+Z2jOiKhTuZNmFGrSXpsdbLK9aUPswDWC+diVQTbTXgtzXjjLWR5rbvTbaShS77w0IDbS+rQ9jK/+Bq/La6/x4QE+ZPRrzsZUAYPSgXQc6k7P2DAj5KRaABBf3yVFABAAP33gPnTIswP3SS6oOxHNt/SzrdtWpxjDtWxm/IzqzZ+Bh5/0PEV26FRO7oErVQgxyyi+jNR0z6YAEKQBgRh3JlrSm7uMIMcRFB/BuOd8KqgcH8oKgrITQJfiMDABhoFsgAo7C02nzyZB6ngcHIOQGJQQbUUVQKoR0wGdRl4jAbAvnhojt19iJeTJuWHeSMIWyACJhpuR7iUQ2uD3PTqd3q6H8Lq/MRiJeDlB8Q0QaENPm9hXLL5mkiOTfGSTdaqdRazeKaoljvhDQf+VIcxpQCEpcCOKCoYMj7FUEjA16YYHeqRiwC4ChidGAKjFRQCbAocMoc0DX0QC0IjQLnFEk+WMYOUMurHBsj50FyuAaB6ITikeleIvxsC0g+UrIJFqzFY8EtViMCBJw85Gg+QKRjK01RAZ/ktAfweoFJCO0s+f9dEHlSxDeJ5Aw4SBFd1BqedoGebbHIpDB6JRNQC9ISlZ1ErZNwemoHPFkP4CfAuMbuWYhnna4b57kYSFFMvgyoSJlu0QGHAt1CqyACiTvYPPYlKaXcluZedgTyXzaglkYH2CKpvjCYBAN8CTf3GJRcEpCVQ9grCvMEtQYheGIVetBVW9BR9v42uYEg+3MLfUxotxfmGFysxyg2GjCKSinh6Jp4YimwF8pIxqE5Msg/g5bjDkM7T1SA9ANwbd2qoUAccLvMmu70HBU06wfbG4NLiEFskJEvEaKlhA9Jh8ZAPbP3OwmVC1Dy8+YSLIZAHbO4TQcAykAYMiGNptW+fPVkXzb4RljWptKvl4Br5vYrWNtKdq5TbIu0uS2JDgbCHeK7si2JJGQTgOBIHsmynHMMOkiv7L9K2WopfvP0X5z8V+8ZG1uuCAGSjHWZo3xqyOGAusWyAAXliDaiOARUCNjZA44tk9RRo3UdqING+jjR9bJklAFtbmjnalot3NaN/62jXWJALXPWGOZ8AskioR0TEGgBa57A0AYdI0FPxz5pwp+EYMOi3CNBlw04LXG6JrDqjPR/on0fqIX7+jT2ponoa2DDFVsIx2okYGvnFBJiswKY7UWAC6gUByxWASsZqOrGKQvR1/OsbWIbHBizRR2C0a2MNDtjhgR+FNN2LeC9il+YAbNFFC4i0AhxPAD0aONrE1ijRhoycTOPKhNjy4txcMUuPgEriyy64yACmNiRFRtI6kIqOQwYCUNK2I41DiePHH+jzxy/S8SGPnEtjb6bYh8S9BSCyB2guKO8smNiCINHYK5RQQWQPH/jN8Y4msBOOX4gSb+JoyfhAGn7MACYgQbwL+womvNGSgHB0nnRA6b9Fs2/SDl6Wg4V04OR/Gdgdmvjzjz+/NLUTRNv6JlbgXmBUNAnKBYcswOHAEZ9nTy4QA+SHOeJ4GaBs5+i9YQYs2GJorgABc41sCAJdjgCG8kA8gMX0xDoImgTIToDkCEQF9DxHwWgoUCJ6tMMBMYhHCKkHIDjsB7dKInuP8GOgzGPk/IU9nkwsQE8qQjCB7nWBmDtJFgkyjFUQpbBwGwQ4ROuGiGb4qhew/TmeX/o7ZeB1wd8KqAOTl5UmsOUInsBUTlxS8VktnLA0sbGNqREIsIDniZGOC5BvQnPh/0ByaDp2v1KaGND0lU40YaUrAIRzTIA9U6wWBlpwxRLPiGs9oWRN5TQiGNFQak41LA3Ij7cu2BlVrswBpQA490609oMkIM7vC0SfAmMAIJ8BOYRBuKTopujyCEJmkx09QRQBcnoC3gdLNyS2WwF+sTBEELSSzQIExVepEoqhMJWARTDquStFSW9LW4bdu04tcvvk124+kmmrlMaPOy3p3xwqCnTKTKLWE+4hyYSRYeU0LxstBpUgiabw3ZFi0xhGE9Np0k+KQABmfAb6ZjGpovtLU3dUQBUKsyitDIczMgcVPf7/deGuER3E0nkzHCRE642Yf8ioDKQSiYgBqm9TLCGc/GxnSMI+EWBOYiRnUrAEQDzBSQ/AIM/TONO6mwgGgmIJjLVTzBE4OpI8dPPHBrA0jhsRgXoAEEVke93G8jbGczAbxcQ/g3ZLAfbRpl8xP+qCDEFEDtALQqUNKOlDWASD2Iw+ZHKXGNF+GXpMmEiPGYKGITacQm93ImfkUiagkW8WMmSB8OuAh9lUiPf2cxRoLSRgeWVd2aEGVYxhFQ9c1jOmED7E1zACxLkcNR5El8+RuxCvgcR7618ziYolkuDNvE5sl2WUkgPKM06KjZSyoikokDVFHjUONEn0TROomIBKJl4tNmyQXmLs3s+0jgUdOsmrzhSe7b4r8WJLkTj53gDQMdMG71k/xu8nCfvKAmHzX5J8k0bOOvELioJS4miXaLDApjUgTiCgBoB/ZALvAHAYhlhN/lCS35B8t+UfOAWBiESoCu1jeLRJ3iwgyC6BbGPjEuAkJPY2IGmIzFZiAAmvSELHFjSx6C5sqOP/l4TkFuC2ifgsbFELwFgAgKDRM7GJjmZtCmIN5M8kcKNRe8rBQApwXIKwJ+k4hRyUXFkKaJq4oCrVRTE7jEAe4uRVWO4VWFeFKikBVeKEWQSRFyCwYOCDMbPiUxY8ItMYq4WKKeFgC4ScRMmxT8jA5AfAAABYhAO4AJcEtX5AdGJG/QuuBw9LN8fS5/H3hkgSFJCcp3Q1rmEpCWZKRJyuBCFxLHo3k5yd5EClZjQh20glQgeerNwQWAVWyaoOLgJFgCJdkuaEVLusHS6hBYGhMM5qhOQa/0BhdOC6LaG0zWdfuCgrwTjxSarBEApQHsLj2VxDgc4MgK4XzBVp0BFQocp3vCHsDDLDsvkFAGQppTNwfO7VbDjNJop0V/OeFdJEVECW3Lvx3AEpOoTxDDBtUrFMsjcpcjfQHltvA5ZMrCDtEbgbAVlGGBiCvKlidYUytNJiDuRyW+lIwigLialK8Q5S4JdRVor0UTWuABoOCveWEJ/BK01UMwzoECwQV+KLxrniwCmTNkYrcqswlwgBAuoBRayEZwdi8Is0tNAFAsHLSp4vsb8FWimi6mGhYpLNBPoHCT6UARWfPUuPUInzd8tgjYOgdfE5G6th5NwXkUbXHlYqzWQo3vjPIb6ELQxF8kRZkrnC4BcA3APBmEBTG3L7lFDA8aTgqWhKSAFS1RWApsVWjMluKq1S+NiBFQvlX4+1bqMyXOrXVli8Cc2ONWeqXVwS2CcwwQkbjYguKyFTFWhXBqY1WSjNQ2JImdZEARFHcClAiUMSVw+debK6ViU792Je/T3mHHyVVy9KucLNPsXES6Y/GylasiksWCnTiQkYXtr0LQif84ZtnUjvZw04PztluyvifsoySeC+uTyiROkl7LsdOFDc59gKP5iYhEwViW6XiCnJId08IWTiEUp/r5dkVqk4jqRy3QzB4QZzOepAUSFdq0lLII9f5BPUPk6l1c3tb2h+5iVh18MvHHZHuG60QIPDVZZMH4YbKB2ZI6LpnIQDBkeZQy66rMsOGDhqlF0JFi+vujecsKhERUFiv4BYAYgxDbSCRoeVjA5cWcLABcvorzAk+oXDzugDCAxBf28kfADuFo0hcdwpwKQGMFkk1wDUWK5lf7y1lsqGMHK/5NaEqTEju2cMtMpM3piI1JuiTMZUR2U6Xqr4O0VIXBLnS/COGss7hisqUpzDkZ23PAHMQHna1VVqxEeZsXb78iu+5tYUacRHCzyF8HZKzXzRs0WUx55fbVYKKOJ6qXNhkUBEP25VzBR+fpCfr4r8wGAcsdYV6oVkIDRLkBFUGLMNCqzb86sqWRrGoGaxZY2ssWgLGYkRjDoh4sBePF+H/AH4HoAEYdAQjCAxa4tJAbSKUE0hFQiKmkAQLEh0gARiGpQAQERRci0AiKgSlyF8qIq0BiGzWwJbpCIq6Q0As2wJYRU2DZYitsSdSFpCKgMBYkxDYjc1toDfQXI2kQJQIG22TaGAxDMEAwCIrqRRA6kBgJpFiS0AioG21rIYDi3aQ0AhFTSDNsCV9b1Iuka7aUGIYTa6ApQIqJpBcgjbRt2kFyL8PUi0BtIkO+bW9sK0QAygCOv7YEsCWPbNI6kZdLQECVoBOtaAJ7bpECWYhPxJAXSJpA62YhtIAgYbZaEa1FaEYI6MrcOgq12I6Ao6FZMOiCxvagAA== -->

<!-- internal state end -->
<!-- tips_start -->

---

> [!NOTE]
> <details>
> <summary>🎁 Summarized by CodeRabbit Free</summary>
> 
> Your organization has reached its limit of developer seats under the Pro Plan. For new users, CodeRabbit will generate a high-level summary and a walkthrough for each pull request. For a comprehensive line-by-line review, please add seats to your subscription by visiting <https://app.coderabbit.ai/login>.If you believe this is a mistake and have available seats, please assign one to the pull request author through the subscription management page using the link above.
> 
> </details>

<details>
<summary>🪧 Tips</summary>

### Chat

There are 3 ways to chat with [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=gofiber/storage&utm_content=1515):

- Review comments: Directly reply to a review comment made by CodeRabbit. Example:
  - `I pushed a fix in commit <commit_id>, please review it.`
  - `Generate unit testing code for this file.`
  - `Open a follow-up GitHub issue for this discussion.`
- Files and specific lines of code (under the "Files changed" tab): Tag `@coderabbitai` in a new review comment at the desired location with your query. Examples:
  - `@coderabbitai generate unit testing code for this file.`
  -	`@coderabbitai modularize this function.`
- PR comments: Tag `@coderabbitai` in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
  - `@coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.`
  - `@coderabbitai read src/utils.ts and generate unit testing code.`
  - `@coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.`
  - `@coderabbitai help me debug CodeRabbit configuration file.`

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

### CodeRabbit Commands (Invoked using PR comments)

- `@coderabbitai pause` to pause the reviews on a PR.
- `@coderabbitai resume` to resume the paused reviews.
- `@coderabbitai review` to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
- `@coderabbitai full review` to do a full review from scratch and review all the files again.
- `@coderabbitai summary` to regenerate the summary of the PR.
- `@coderabbitai resolve` resolve all the CodeRabbit review comments.
- `@coderabbitai configuration` to show the current CodeRabbit configuration for the repository.
- `@coderabbitai help` to get help.

### Other keywords and placeholders

- Add `@coderabbitai ignore` anywhere in the PR description to prevent this PR from being reviewed.
- Add `@coderabbitai summary` to generate the high-level summary at a specific location in the PR description.
- Add `@coderabbitai` or `@coderabbitai title` anywhere in the PR title to generate the title automatically.

### CodeRabbit Configuration File (`.coderabbit.yaml`)

- You can programmatically configure CodeRabbit by adding a `.coderabbit.yaml` file to the root of your repository.
- Please see the [configuration documentation](https://docs.coderabbit.ai/guides/configure-coderabbit) for more information.
- If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: `# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json`

### Documentation and Community

- Visit our [Documentation](https://docs.coderabbit.ai) for detailed information on how to use CodeRabbit.
- Join our [Discord Community](http://discord.gg/coderabbit) to get help, request features, and share feedback.
- Follow us on [X/Twitter](https://twitter.com/coderabbitai) for updates and announcements.

</details>

<!-- tips_end -->
author_association: CONTRIBUTOR
user: login: mdelapenya
created_at: 2024-08-29T14:39:57Z
body: For some reason, the memcache service is failing in the benchmark job. Any guess?
author_association: CONTRIBUTOR
user: login: ReneWerner87
created_at: 2024-09-11T12:03:55Z
body: sorry overlooked, that's really strange, I'll have to take a look at it in the next few days
author_association: MEMBER
user: login: mdelapenya
created_at: 2024-09-13T10:05:46Z
body: @ReneWerner87 any update on the benchmark thing? 🙏  Once merge, I can send a new PR with more stores
author_association: CONTRIBUTOR
user: login: ReneWerner87
created_at: 2024-09-13T13:47:13Z
body: unfortunately haven't had time to look yet, will have a look on sunday and fix it then, but feel free to make pull requests for the other stores if you like

in this case we only have to apply the fix to the other PR
author_association: MEMBER
user: login: ReneWerner87
created_at: 2024-09-15T17:01:04Z
body: @mdelapenya now the reason

you removed the other services

<img width="1055" alt="image" src="https://github.com/user-attachments/assets/20fc2438-5d71-404e-8a6d-bbbb063e7d5a">

now the options from postgres for the health check belongs to memcached

<img width="1216" alt="image" src="https://github.com/user-attachments/assets/6fe78d70-0e79-4fdb-9f9c-a96231b4e865">


but there is no postgres started

<img width="746" alt="image" src="https://github.com/user-attachments/assets/856db056-36c4-487b-85f1-adc7211e38f7">


other question
do we have to change the golang versions in the test-*.yml's and go.mod files? 
then we would cause a breaking change as in the previous PR request
https://github.com/gofiber/storage/pull/1508#issuecomment-2316937490

author_association: MEMBER
user: login: mdelapenya
created_at: 2024-09-16T11:30:21Z
body: > do we have to change the golang versions in the test-*.yml's and go.mod files?
then we would cause a breaking change as in the previous PR request
https://github.com/gofiber/storage/pull/1508#issuecomment-2316937490

We changed because otherwise the store project won't compile, failing with:

```
Error: ../../../../go/pkg/mod/github.com/docker/docker@v27.1.1+incompatible/pkg/archive/archive.go:784:24: undefined: strings.CutPrefix
FAIL	github.com/gofiber/storage/mssql/v2 [build failed]
```

This means that the docker dependency added by testcontainers would need Go 1.20 (please see https://pkg.go.dev/strings#CutPrefix). So, if you agree, I'm keeping the following Go matrix:

```yaml
                go-version:
                    - 1.20.x
                    - 1.21.x
                    - 1.22.x
```

And regarding the `go.mod` files, whatever you prefer (keeping 1.19 or bumping to 1.21) is fine for me.
author_association: CONTRIBUTOR
user: login: ReneWerner87
created_at: 2024-09-16T12:22:19Z
body: ok didn´t know

then update the go.mod to 1.20
and don´t forget to remove the "options" line in benchmark.yaml
author_association: MEMBER
user: login: mdelapenya
created_at: 2024-09-16T12:37:16Z
body: @ReneWerner87  I noticed that if we keep Go 1.20 in the go.mod, then the build will complain about `mod tidy` to be needed. Do you want me to add a step in the pipeline for `mod tidy`, or simply bump the Go version to 1.21 (as we already did for the clickhouse module).
author_association: CONTRIBUTOR
user: login: ReneWerner87
created_at: 2024-09-16T14:11:30Z
body: Ok, 1.21 is ok for me 
author_association: MEMBER
user: login: mdelapenya
created_at: 2024-09-16T19:17:13Z
body: Couchbase benchmark is passing for me locally 🤔 Any clue?
author_association: CONTRIBUTOR
user: login: ReneWerner87
created_at: 2024-09-16T20:25:16Z
body: Will check it tomorrow morning 
author_association: MEMBER
user: login: ReneWerner87
created_at: 2024-09-17T06:53:35Z
body: i restarted the benchmarks and now we have a new problem

![image](https://github.com/user-attachments/assets/7ab4eb77-2bad-42a7-93fe-4e18ffcf031b)

author_association: MEMBER
user: login: mdelapenya
created_at: 2024-09-17T09:57:17Z
body: taking a look, thanks! 🙏 
author_association: CONTRIBUTOR
user: login: mdelapenya
created_at: 2024-09-17T13:40:41Z
body: It's weird: they pass locally for me

```
go test ./... -v -benchmem -run=^$ -bench . | tee -a ../output.txt
goos: darwin
goarch: arm64
pkg: github.com/gofiber/storage/mssql/v2
Benchmark_MSSQL_Set
2024/09/17 15:38:33 github.com/testcontainers/testcontainers-go - Connected to docker: 
  Server Version: 82+testcontainerscloud (via Testcontainers Desktop 1.17.0)
  API Version: 1.46
  Operating System: Ubuntu 22.04.4 LTS
  Total Memory: 15779 MB
  Testcontainers for Go Version: v0.33.0
  Resolved Docker Host: tcp://127.0.0.1:51475
  Resolved Docker Socket Path: /var/run/docker.sock
  Test SessionID: c134e29f4f160c5036506bb926bfd5fef0252e721d3b872da882ac66e699aebd
  Test ProcessID: f85ff9e5-c073-473d-9c5f-10b48aadf30a
2024/09/17 15:38:33 🐳 Creating container for image testcontainers/ryuk:0.8.1
2024/09/17 15:38:33 ✅ Container created: 898ef11dd444
2024/09/17 15:38:33 🐳 Starting container: 898ef11dd444
2024/09/17 15:38:34 ✅ Container started: 898ef11dd444
2024/09/17 15:38:34 ⏳ Waiting for container id 898ef11dd444 image: testcontainers/ryuk:0.8.1. Waiting for: &{Port:8080/tcp timeout:<nil> PollInterval:100ms skipInternalCheck:false}
2024/09/17 15:38:34 🔔 Container is ready: 898ef11dd444
2024/09/17 15:38:34 🐳 Creating container for image mcr.microsoft.com/mssql/server:2022-RTM-GDR1-ubuntu-20.04
2024/09/17 15:38:34 ✅ Container created: 60c8ace27308
2024/09/17 15:38:34 🐳 Starting container: 60c8ace27308
2024/09/17 15:38:34 ✅ Container started: 60c8ace27308
2024/09/17 15:38:34 ⏳ Waiting for container id 60c8ace27308 image: mcr.microsoft.com/mssql/server:2022-RTM-GDR1-ubuntu-20.04. Waiting for: &{timeout:<nil> Log:Recovery is complete. IsRegexp:false Occurrence:1 PollInterval:100ms}
2024/09/17 15:38:39 🔔 Container is ready: 60c8ace27308
2024/09/17 15:38:40 🐳 Creating container for image mcr.microsoft.com/mssql/server:2022-RTM-GDR1-ubuntu-20.04
2024/09/17 15:38:40 ✅ Container created: 16ebc0c630be
2024/09/17 15:38:40 🐳 Starting container: 16ebc0c630be
2024/09/17 15:38:40 ✅ Container started: 16ebc0c630be
2024/09/17 15:38:40 ⏳ Waiting for container id 16ebc0c630be image: mcr.microsoft.com/mssql/server:2022-RTM-GDR1-ubuntu-20.04. Waiting for: &{timeout:<nil> Log:Recovery is complete. IsRegexp:false Occurrence:1 PollInterval:100ms}
2024/09/17 15:38:45 🔔 Container is ready: 16ebc0c630be
Benchmark_MSSQL_Set-8                          6         191780180 ns/op           99942 B/op        598 allocs/op
Benchmark_MSSQL_Get
2024/09/17 15:38:47 🐳 Creating container for image mcr.microsoft.com/mssql/server:2022-RTM-GDR1-ubuntu-20.04
2024/09/17 15:38:47 ✅ Container created: dbb74231c3b6
2024/09/17 15:38:47 🐳 Starting container: dbb74231c3b6
2024/09/17 15:38:47 ✅ Container started: dbb74231c3b6
2024/09/17 15:38:47 ⏳ Waiting for container id dbb74231c3b6 image: mcr.microsoft.com/mssql/server:2022-RTM-GDR1-ubuntu-20.04. Waiting for: &{timeout:<nil> Log:Recovery is complete. IsRegexp:false Occurrence:1 PollInterval:100ms}
2024/09/17 15:38:52 🔔 Container is ready: dbb74231c3b6
2024/09/17 15:38:53 🐳 Creating container for image mcr.microsoft.com/mssql/server:2022-RTM-GDR1-ubuntu-20.04
2024/09/17 15:38:53 ✅ Container created: 06ded4ac3ae0
2024/09/17 15:38:53 🐳 Starting container: 06ded4ac3ae0
2024/09/17 15:38:54 ✅ Container started: 06ded4ac3ae0
2024/09/17 15:38:54 ⏳ Waiting for container id 06ded4ac3ae0 image: mcr.microsoft.com/mssql/server:2022-RTM-GDR1-ubuntu-20.04. Waiting for: &{timeout:<nil> Log:Recovery is complete. IsRegexp:false Occurrence:1 PollInterval:100ms}
2024/09/17 15:38:58 🔔 Container is ready: 06ded4ac3ae0
2024/09/17 15:39:00 🐳 Creating container for image mcr.microsoft.com/mssql/server:2022-RTM-GDR1-ubuntu-20.04
2024/09/17 15:39:00 ✅ Container created: 8e5288e9b2a6
2024/09/17 15:39:00 🐳 Starting container: 8e5288e9b2a6
2024/09/17 15:39:00 ✅ Container started: 8e5288e9b2a6
2024/09/17 15:39:00 ⏳ Waiting for container id 8e5288e9b2a6 image: mcr.microsoft.com/mssql/server:2022-RTM-GDR1-ubuntu-20.04. Waiting for: &{timeout:<nil> Log:Recovery is complete. IsRegexp:false Occurrence:1 PollInterval:100ms}
2024/09/17 15:39:05 🔔 Container is ready: 8e5288e9b2a6
2024/09/17 15:39:07 🐳 Creating container for image mcr.microsoft.com/mssql/server:2022-RTM-GDR1-ubuntu-20.04
2024/09/17 15:39:07 ✅ Container created: 63e2053a58eb
2024/09/17 15:39:07 🐳 Starting container: 63e2053a58eb
2024/09/17 15:39:07 ✅ Container started: 63e2053a58eb
2024/09/17 15:39:07 ⏳ Waiting for container id 63e2053a58eb image: mcr.microsoft.com/mssql/server:2022-RTM-GDR1-ubuntu-20.04. Waiting for: &{timeout:<nil> Log:Recovery is complete. IsRegexp:false Occurrence:1 PollInterval:100ms}
2024/09/17 15:39:12 🔔 Container is ready: 63e2053a58eb
Benchmark_MSSQL_Get-8                          6         191320208 ns/op          109934 B/op        601 allocs/op
Benchmark_MSSQL_SetAndDelete
2024/09/17 15:39:14 🐳 Creating container for image mcr.microsoft.com/mssql/server:2022-RTM-GDR1-ubuntu-20.04
2024/09/17 15:39:14 ✅ Container created: a17d4139d23b
2024/09/17 15:39:14 🐳 Starting container: a17d4139d23b
2024/09/17 15:39:14 ✅ Container started: a17d4139d23b
2024/09/17 15:39:14 ⏳ Waiting for container id a17d4139d23b image: mcr.microsoft.com/mssql/server:2022-RTM-GDR1-ubuntu-20.04. Waiting for: &{timeout:<nil> Log:Recovery is complete. IsRegexp:false Occurrence:1 PollInterval:100ms}
2024/09/17 15:39:19 🔔 Container is ready: a17d4139d23b
2024/09/17 15:39:20 🐳 Creating container for image mcr.microsoft.com/mssql/server:2022-RTM-GDR1-ubuntu-20.04
2024/09/17 15:39:20 ✅ Container created: a33e3ebb2c58
2024/09/17 15:39:20 🐳 Starting container: a33e3ebb2c58
2024/09/17 15:39:21 ✅ Container started: a33e3ebb2c58
2024/09/17 15:39:21 ⏳ Waiting for container id a33e3ebb2c58 image: mcr.microsoft.com/mssql/server:2022-RTM-GDR1-ubuntu-20.04. Waiting for: &{timeout:<nil> Log:Recovery is complete. IsRegexp:false Occurrence:1 PollInterval:100ms}
2024/09/17 15:39:25 🔔 Container is ready: a33e3ebb2c58
2024/09/17 15:39:27 🐳 Creating container for image mcr.microsoft.com/mssql/server:2022-RTM-GDR1-ubuntu-20.04
2024/09/17 15:39:27 ✅ Container created: d53d076a7b6c
2024/09/17 15:39:27 🐳 Starting container: d53d076a7b6c
2024/09/17 15:39:28 ✅ Container started: d53d076a7b6c
2024/09/17 15:39:28 ⏳ Waiting for container id d53d076a7b6c image: mcr.microsoft.com/mssql/server:2022-RTM-GDR1-ubuntu-20.04. Waiting for: &{timeout:<nil> Log:Recovery is complete. IsRegexp:false Occurrence:1 PollInterval:100ms}
2024/09/17 15:39:32 🔔 Container is ready: d53d076a7b6c
Benchmark_MSSQL_SetAndDelete-8                 3         412130153 ns/op          195160 B/op       1167 allocs/op
PASS
ok      github.com/gofiber/storage/mssql/v2     61.584s
```

Is there any way to relaunch the benchmark job, and try to identify where the flakiness is?
author_association: CONTRIBUTOR
user: login: ReneWerner87
created_at: 2024-09-17T17:20:01Z
body: I already restarted it 2 time

Pls test the workflow with act
https://github.com/nektos/act
author_association: MEMBER
user: login: ReneWerner87
created_at: 2024-09-17T17:21:29Z
body: I restarted the benchmark action again with debug info
https://github.com/gofiber/storage/actions/runs/10886797247?pr=1515
author_association: MEMBER
user: login: mdelapenya
created_at: 2024-09-19T12:53:06Z
body: @ReneWerner87 I noticed a regression in the recent update (Azure DevOps  agent / GitHub Actions runner): https://github.com/actions/runner-images/issues/10649

I think it could be related 🤔 
author_association: CONTRIBUTOR
user: login: mdelapenya
created_at: 2024-09-20T09:06:29Z
body: @ReneWerner87 I resolved the MSSQL errors caused by the recent GH workers upgrade, and I'm currently debugging the couchbase failures (https://github.com/gofiber/storage/actions/runs/10950265038/job/30405176292?pr=1515) where it only fails for Go 1.20 🤷  Do you think it could be caused by the number of running containers so the worker could eventually be non-responsive? I'd say that the same happens for the benchmarks. Will update this thread after my research.

Sorry for the inconvenience 🙏 
author_association: CONTRIBUTOR
user: login: ReneWerner87
created_at: 2024-09-20T11:27:57Z
body: > Do you think it could be caused by the number of running containers

could be possible

thanks for the effort so far
author_association: MEMBER
user: login: gaby
created_at: 2024-09-20T12:09:35Z
body: @mdelapenya Did you add "wait_for" to each service? A lot of these services take a bit to start, so it could be that.
author_association: MEMBER
user: login: mdelapenya
created_at: 2024-09-20T14:28:54Z
body: > @mdelapenya Did you add "wait_for" to each service? A lot of these services take a bit to start, so it could be that.

Indeed, we always recommend adding wait strategies for container, so our modules usually come with a wait strategy.

For couchbase we have this: https://github.com/testcontainers/testcontainers-go/blob/main/modules/couchbase/couchbase.go#L189
author_association: CONTRIBUTOR
user: login: ReneWerner87
created_at: 2024-11-28T12:11:01Z
body: @mdelapenya in mssql I saw that you changed the version to 1.22 in the go.mod, but the test workflow still tests down to 1.20
that means you would have to use this lower version in the go.mod, because it is the minimum
author_association: MEMBER
user: login: ReneWerner87
created_at: 2024-11-28T12:13:32Z
body: same for couchbase
author_association: MEMBER
user: login: mdelapenya
created_at: 2024-11-28T14:00:49Z
body: @ReneWerner87 thanks for going back to this. I was focused on other topics and left this behind. I can jump on this now.

Before I add more (probably wrong) code, what is the Go version policy for the modules? We collected the values in https://github.com/gofiber/storage/pull/1508#issuecomment-2304549792. This will be important because in older Go versions, we'll find some issues with missing types required by packages using a more modern version.

Could you help me out defining the right version? 🙏 
author_association: CONTRIBUTOR
user: login: ReneWerner87
created_at: 2024-11-28T14:05:51Z
body: https://github.com/gofiber/storage/pull/1508#issuecomment-2316937490

We should leave the versions as they are, otherwise we would have to increase the major version of the respective package and update other things if possible, so that this breaking change was worth it
author_association: MEMBER
user: login: mdelapenya
created_at: 2024-11-28T14:07:24Z
body: > We should leave the versions as they are, otherwise we would have to increase the major version of the respective package and update other things if possible, so that this breaking change was worth it

Ok, makes sense. There would be modules we won't be able to adopt the integration tests as in others. Will take a look, and would close this PR in case it's not possible to do it. Thanks for your work here!
author_association: CONTRIBUTOR
user: login: ReneWerner87
created_at: 2024-11-28T14:09:42Z
body: It would be possible if we upgrade the major version and no longer support the old golang version
But maybe we should only do that when we make the change for version 3
author_association: MEMBER
user: login: mdelapenya
created_at: 2024-11-28T15:13:47Z
body: Makes sense. I can send this work again once we are in v3. We can close this and create an issue for that.
author_association: CONTRIBUTOR
user: login: mdelapenya
created_at: 2024-12-11T13:41:40Z
body: @ReneWerner87 I've added [78da7fc](https://github.com/gofiber/storage/pull/1515/commits/78da7fcbd1a51e8b6a583faae8b6de292529e320) in order to align the modules modified by this PR (couchbase, mongo, mssql, mysql and postgres) in regards of the Go version matrix: all using 1.21 and above, as in the existing minio module.

I have one question regarding the clickhouse module, which runs the tests for 1.21 and 1.22: I guess we still want to do it in 1.23 too, right? I can add it in this PR.

Last thing: the benchmark is failing, and I think it's because the default timeout per test (60s) it's not enough to pull the MSSQL Docker image (2.19GB). Would it be OK to add the `-timeout 120s` flag to the benchmarks?
author_association: CONTRIBUTOR
user: login: mdelapenya
created_at: 2024-12-11T14:08:24Z
body: Mmmm not the timeout but this: https://github.com/gofiber/storage/actions/runs/12277044952/job/34255559810?pr=1515#step:14:729

```
2024/12/11 13:53:28 container logs (wait until ready: container exited with code 127):
SQL Server 2022 will run as non-root by default.
This container is running as user mssql.
To learn more visit https://go.microsoft.com/fwlink/?linkid=2099216.
This program has encountered a fatal error and cannot continue running at Wed Dec 11 13:53:28 2024
The following diagnostic information is available:

         Reason: 0x00000003
         Status: 0x0000000b
        Message: Unable to create a new asynchronous I/O context. Please increase sysctl fs.aio-max-nr
          Stack:
                 IP               Function
                 ---------------- --------------------------------------
                 0000559f262f4a61 std::__1::bad_function_call::~bad_function_call()+0x97ab1
                 0000559f262f4426 std::__1::bad_function_call::~bad_function_call()+0x97476
                 0000559f26245c2f std::__1::basic_stringbuf<char, std::__1::char_traits<char>, std::__1::allocator<char>>::str() const+0x1c8f
                 0000559f262645b4 std::__1::bad_function_call::~bad_function_call()+0x7604
                 0000559f2626437d std::__1::bad_function_call::~bad_function_call()+0x73cd
                 0000559f262865b6 std::__1::bad_function_call::~bad_function_call()+0x29606
                 0000559f26286d5d std::__1::bad_function_call::~bad_function_call()+0x29dad
                 0000559f2625079b std::__1::basic_stringbuf<char, std::__1::char_traits<char>, std::__1::allocator<char>>::str() const+0xc7fb
                 0000559f26232cfc <unknown>
                 00007f818d92bd90 __libc_init_first+0x90
                 00007f818d92be40 __libc_start_main+0x80
        Process: 9 - sqlservr
         Thread: 9
    Instance Id: 777b44e6-fe58-4699-82e7-b6c2492827df
       Crash Id: 15efe0b0-9430-418a-b897-b0f90a92dba2
    Build stamp: d986b523c576d701c33a57ed10ecb573fee0027b11dee759032623389580414d
   Distribution: Ubuntu 22.04.4 LTS
     Processors: 4
   Total Memory: 1675[734](https://github.com/gofiber/storage/actions/runs/12277044952/job/34255559810?pr=1515#step:14:735)2208 bytes
      Timestamp: Wed Dec 11 13:53:28 2024
     Last errno: 11
Last errno text: Resource temporarily unavailable
Capturing a dump of 9
sqlservr: utils.cpp:561: uintptr_t GetEndOfLibOSVmRange(): Assertion `GetGlobals()->GetStatics()->IsLibOSVmmRangeEndValid()' failed.
This program has encountered a fatal error and cannot continue running at Wed Dec 11 13:53:28 2024
The following diagnostic information is available:

         Reason: 0x00000001
         Signal: SIGSEGV - Segmentation fault (11)
 Signal Address: (nil)
    Signal Code: 0x00000080
          Stack:
                 IP               Function
                 ---------------- --------------------------------------
                 0000559f262f4a61 std::__1::bad_function_call::~bad_function_call()+0x97ab1
                 0000559f262f4426 std::__1::bad_function_call::~bad_function_call()+0x97476
                 0000559f26302f15 std::__1::bad_function_call::~bad_function_call()+0xa5f65
                 0000559f262cc33b std::__1::bad_function_call::~bad_function_call()+0x6f38b
                 00007f818d944520 __sigaction+0x50
                 00007f818d92a898 abort+0x178
                 00007f818d92a71b <unknown>
                 00007f818d93be96 __assert_fail+0x46
                 0000559f26346820 std::__1::bad_function_call::~bad_function_call()+0xe9870
                 0000559f26341e98 std::__1::bad_function_call::~bad_function_call()+0xe4ee8
                 0000559f263445e7 std::__1::bad_function_call::~bad_function_call()+0xe7637
                 0000559f26345ce4 std::__1::bad_function_call::~bad_function_call()+0xe8d34
                 0000559f2634201c std::__1::bad_function_call::~bad_function_call()+0xe506c
                 0000559f263404a2 std::__1::bad_function_call::~bad_function_call()+0xe34f2
                 0000559f262f8dc5 std::__1::bad_function_call::~bad_function_call()+0x9be15
                 0000559f262f8c69 std::__1::bad_function_call::~bad_function_call()+0x9bcb9
                 0000559f262f94d2 std::__1::bad_function_call::~bad_function_call()+0x9c522
                 0000559f262f6e88 std::__1::bad_function_call::~bad_function_call()+0x99ed8
                 00007f818d996ac3 pthread_condattr_setpshared+0x513
        Process: 1 - sqlservr
         Thread: 8
    Instance Id: 777b44e6-fe58-4699-82e7-b6c2492827df
       Crash Id: 15efe0b0-9430-418a-b897-b0f90a92dba2
    Build stamp: d986b523c576d701c33a57ed10ecb573fee0027b11dee759032623389580414d
   Distribution: Ubuntu 22.04.4 LTS
     Processors: 4
   Total Memory: 16[757](https://github.com/gofiber/storage/actions/runs/12277044952/job/34255559810?pr=1515#step:14:758)342208 bytes
      Timestamp: Wed Dec 11 13:53:28 2024
```
author_association: CONTRIBUTOR
user: login: mdelapenya
created_at: 2024-12-12T13:29:30Z
body: @ReneWerner87 I think this PR is ready to go *BUT* there is a crash in the MSSQL server benchmarks that I'm not able to fix, as it requires tuning up the `fs.aio-max-nr` parameters at the GH runner kernel, which is not possible (or at least I'm not able to do it).

I think I linked to some issues above regarding this, so it's documented in the PR.

We can keep this PR open as is until the ubuntu + mssql limitation is fixed, and then decide what to do. I'm sorry it's taking that long 😞 
author_association: CONTRIBUTOR
user: login: mdelapenya
created_at: 2024-12-12T14:05:45Z
body: BTW, I can remove MSSQL from this PR, and move on with the rest of the storages, wdyt?
author_association: CONTRIBUTOR
user: login: mdelapenya
created_at: 2024-12-12T14:06:36Z
body: Another question: given the amount of commits here, what's the preferred way of sending PRs: squashing commits to just one, or they will be squashed when merged?
author_association: CONTRIBUTOR
user: login: mdelapenya
created_at: 2024-12-12T15:39:15Z
body: @ReneWerner87 the benchmarks for the modules I modified here are passing, the current failure is in the S3 module, so I _guess_ it's certain flakiness.

Could you please re-run the benchmarks build? I think, now that MSSQL server is back to the original state, we are really close to merge this one 😄 
author_association: CONTRIBUTOR
user: login: ReneWerner87
created_at: 2024-12-12T15:39:41Z
body: sure
author_association: MEMBER
user: login: mdelapenya
created_at: 2024-12-31T08:24:38Z
body: Relates #1536, so I'd postpone the review of this one after the other is approved & merged.
author_association: CONTRIBUTOR
user: login: mdelapenya
created_at: 2025-01-30T16:52:39Z
body: Hi folks @ReneWerner87 @gaby ! 👋  I've updated this PR with current main, and I see that the current client code "could" come with certain flakiness, as I do not see deterministic failures in the tests: they can fail when creating the client connection to the given store, so I'm not sure if the given package should handle retries 🤔 

E.g. the clickhouse tests pass in 1.22, but they fail in 1.23 (because of a failed handshake)

Another feasible thing is the container is not reliable enough (or not yet), maybe because the current default wait strategy is not enough. I could look more in depth about this adding some retries at the test code, or defining more consistent wait strategies (like for the health-check http endpoint for the given store, if it exits).

Thoughts?
author_association: CONTRIBUTOR
user: login: ReneWerner87
created_at: 2025-02-12T11:06:08Z
body: @mdelapenya 
> I could look more in depth about this adding some retries at the test code, or defining more consistent wait strategies (like for the health-check http endpoint for the given store, if it exits).

that would be good
thank you for your continuous help
author_association: MEMBER
user: login: mdelapenya
created_at: 2025-02-28T13:05:16Z
body: Hi again, sorry for taking that long for this PR, too many tasks on my plate 🤦 

In any case, I improved the wait strategies in the modules in the project, which potential additions for the upstream modules in testcontainers-go. It's failing for couchbase because the pipeline takes more than the 120s that are defined in the GH workflow.

Is increasing that timeout an issue for you?
author_association: CONTRIBUTOR
user: login: gaby
created_at: 2025-02-28T13:06:31Z
body: @mdelapenya Make it 300s (5mins)
author_association: MEMBER
user: login: mdelapenya
created_at: 2025-02-28T13:29:12Z
body: In my Mac M1:
```
go test ./... -timeout 600s -benchmem -run=^$ -bench .
goos: darwin
goarch: arm64
pkg: github.com/gofiber/storage/couchbase/v2
cpu: Apple M1 Pro
Benchmark_Couchbase_Set-8                     32          35257534 ns/op           16723 B/op        250 allocs/op
Benchmark_Couchbase_Get-8                     37          31788931 ns/op            7061 B/op        128 allocs/op
Benchmark_Couchbase_SetAndDelete-8            14          72472684 ns/op           39245 B/op        549 allocs/op
PASS
ok      github.com/gofiber/storage/couchbase/v2 337.864s
```
author_association: CONTRIBUTOR
user: login: mdelapenya
created_at: 2025-03-17T12:35:59Z
body: @gaby @ReneWerner87 this branch is now green!

It took time, but we finally made it. Major highlight here was a timeout for the couchbase benchmarks. I increased the timeout to 500s to bypass it. In general, all benchmarks take 1-2 minutes, but for some reason couchbase not.

I rebased the branch to cover the recent changes in the postgres module, so I think it's ready for start the review.

As always, please let me know anything you need here.
author_association: CONTRIBUTOR
user: login: gaby
created_at: 2025-03-17T12:46:26Z
body: Will review today after work, thanks 💪
author_association: MEMBER