Skip to content

feat(mongo): migrate from mongo-driver v1 to v2#487

Merged
jeffersonrodrigues92 merged 3 commits into
developfrom
feat/mongo-driver-v2
May 20, 2026
Merged

feat(mongo): migrate from mongo-driver v1 to v2#487
jeffersonrodrigues92 merged 3 commits into
developfrom
feat/mongo-driver-v2

Conversation

@jeffersonrodrigues92
Copy link
Copy Markdown
Contributor

@jeffersonrodrigues92 jeffersonrodrigues92 commented May 20, 2026

Summary

In-place upgrade of the MongoDB driver across commons/mongo, commons/outbox/mongo, commons/tenant-manager/core, and commons/tenant-manager/mongo.

  • Module path stays at /v5 — no major bump
  • Public function signatures unchanged (e.g., tmcore.GetMBContext still returns *mongo.Database, just from v2 now)
  • Driver pinned at go.mongodb.org/mongo-driver/v2 v2.6.0 (latest stable)

Why v2

The migration is motivated by the v2 driver itself — not by any specific defect in v1:

  • New builder-style options API (*XxxOptionsBuilder)
  • Type-safe results (*DistinctResult instead of ([]any, error))
  • Consolidated BSON surface (primitive package merged into bson)
  • Cleaner transaction callbacks (no more mongo.SessionContext)
  • Alignment with the MongoDB-supported driver line (v1 is on a sunset trajectory)

What consumer services need to know

The lib-commons API surface is unchanged, but the concrete *mongo.Database / *mongo.Client types now resolve to v2. Any code that holds these values and calls MongoDB methods on them needs to adapt:

v1 v2
coll.Distinct(ctx, ...) returns ([]any, error) returns *DistinctResult — use .Err() + .Decode(&values)
mongo.Connect(ctx, opts) validates reachability no longer pings — add explicit client.Ping(ctx, nil) if you relied on Connect to fail
primitive.DateTime, primitive.ObjectID, primitive.NewObjectID(), etc. moved to bson root: bson.DateTime, bson.ObjectID, bson.NewObjectID()
WithTransaction(ctx, func(sessCtx mongo.SessionContext) ...) callback receives context.Context; use mongo.SessionFromContext(ctx) if you need the session
options.UpdateOne() returns *UpdateOneOptions returns *UpdateOneOptionsBuilder — fluent .SetX() chain is identical

Services consuming lib-commons via tmcore.GetMBContext, tmcore.ContextWithMB, tmmongo.Manager.GetDatabase*, or commons/mongo.Client.Database() will need to update their query code accordingly.

Note: disconnectClient helper is unrelated to v2

The refactor(mongo): use bounded context for all Disconnect call sites commit introduces a disconnectClient helper and applies it to every Disconnect call in tenant-manager/mongo/manager.go. This is a defensive hygiene fix, not a v2 motivator. The issue (passing a possibly-canceled request context to Client.Disconnect leaks topology/monitoring goroutines) exists identically on v1 and v2 — the MongoDB driver has always required a non-canceled context for graceful shutdown.

The fix lives in this PR because CodeRabbit surfaced the issue while reviewing the new connectWithTLS code path we added to compensate for v2's removal of implicit pinging at Connect. Once flagged, it was easier to address all 7 sites consistently here than to open a follow-up PR.

The v2 migration would still be worth doing without this commit, and this commit would still be worth doing without the v2 migration.

Files changed

20 files, +70/-59 lines (driver migration) plus the disconnectClient refactor:

  • 17 source files (mongo, outbox/mongo, tenant-manager/core, tenant-manager/mongo)
  • go.mod (drop v1, promote v2 from indirect to direct)
  • go.sum (regenerated by go mod tidy)
  • CHANGELOG.md (entry under [5.3.0])

Validation

  • go test -tags=unit ./...4534 pass, 0 fail
  • go test -tags=integration ./...142 pass, 0 fail (testcontainers mongo:7)
  • go vet ./... → clean
  • golangci-lint run ./... → 0 issues
  • gofmt -l ./commons → clean

Tag to follow

After merge: v5.3.0.

Test plan

  • CI green
  • Smoke test against one consumer service (e.g., midaz ledger) on a feature branch — verify the v2 API differences listed above are caught at compile time and fixed

🤖 Generated with Claude Code

In-place upgrade of the MongoDB driver across commons/mongo, commons/outbox/mongo,
commons/tenant-manager/core, and commons/tenant-manager/mongo. Module path stays at
/v5; public function signatures are unchanged. Consumer services that hold the
returned *mongo.Database/*mongo.Client will need to update their own MongoDB calls
to the v2 driver (notably: Collection.Distinct now returns *DistinctResult,
mongo.Connect no longer pings, primitive types live under bson, WithTransaction
callback receives context.Context instead of mongo.SessionContext).

Driver pinned at go.mongodb.org/mongo-driver/v2 v2.6.0. Unit (4534) and integration
(142) suites pass. Lint clean.

X-Lerian-Ref: 0x1
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 20, 2026

Review Change Stack

Walkthrough

Migrates the codebase from MongoDB Go driver v1 to v2: update go.mod, replace imports across modules, adapt API changes (mongo.Connect signature, Collection.Distinct result decoding, DateTime type mapping, WithTransaction callback context), and add explicit Ping/disconnect handling for TLS connections.

Changes

MongoDB Driver v1 to v2 Migration

Layer / File(s) Summary
Dependency Version Update
go.mod
Updates MongoDB Go driver dependency from v1.17.9 to v2.6.0 in the primary require block and removes now-unneeded indirect dependencies.
Core client imports & default connect
commons/mongo/mongo.go, commons/mongo/mongo_integration_test.go, commons/mongo/mongo_test.go
Switches imports to v2 module paths and changes defaultDeps().connect to call mongo.Connect with options only (incoming context is accepted but not forwarded).
Outbox BSON imports & DateTime changes
commons/outbox/mongo/document.go, commons/outbox/mongo/coverage_boost_test.go, commons/outbox/mongo/*
Replace primitive.DateTime usage with bson.DateTime, update parsing switches, and update tests to construct datetimes via bson.NewDateTimeFromTime(now); update outbox imports to v2.
Distinct API & transaction callback changes
commons/outbox/mongo/repository.go, commons/outbox/mongo/repository_integration_test.go
Adapt Collection.Distinct usage to the v2 result object + Decode(&values) pattern; update integration tests for options-only mongo.Connect and WithTransaction callback signature receiving context.Context.
Outbox module import updates
commons/outbox/mongo/claim.go, commons/outbox/mongo/extra_test.go, commons/outbox/mongo/helpers.go, commons/outbox/mongo/indexes.go, commons/outbox/mongo/pure_functions_test.go, commons/outbox/mongo/repository_test.go
Update remaining outbox/mongo files and tests to use v2 import paths for bson, mongo, and options.
Tenant Manager core import updates
commons/tenant-manager/core/context.go, commons/tenant-manager/core/context_test.go
Update imports to go.mongodb.org/mongo-driver/v2/mongo so *mongo.Database types reference the v2 driver.
Tenant Manager connection lifecycle & tests
commons/tenant-manager/mongo/manager.go, commons/tenant-manager/mongo/manager_test.go, commons/tenant-manager/mongo/coverage_boost_test.go
Introduce disconnectClient using a background timeout, call mongo.Connect(clientOptions) then mongoClient.Ping(ctx, nil) and disconnect on failure; update swap/evict/Close paths to use disconnectClient; update tests to use options-style Connect and extend goleak ignores for v2 topology goroutines.
Release Notes Documentation
CHANGELOG.md
Add 5.3.0 entry documenting the MongoDB driver v2 migration and enumerating concrete API/type changes.

Comment @coderabbitai help to get the list of available commands and usage tips.

@lerian-studio
Copy link
Copy Markdown
Contributor

lerian-studio commented May 20, 2026

🔒 Security Scan Results — lib-commons

✅ PR Mergeable — no blocking findings

Stage Status Blocking?
Filesystem Scan ✅ Clean
Docker Image Scan ➖ Skipped
Docker Hub Health Score ➖ Skipped
Pre-release Version Check ✅ Clean

Trivy

Filesystem Scan

✅ No vulnerabilities or secrets found.


Pre-release Version Check

✅ No unstable version pins found.


🔍 View full scan logs

@lerian-studio lerian-studio added size/S PR changes 50–199 lines docs Documentation and markdown content mongo MongoDB connector outbox Outbox pattern tenant-manager Tenant manager tests Unit, integration and end-to-end tests deps Go module dependencies (usually opened by Dependabot) labels May 20, 2026
@lerian-studio
Copy link
Copy Markdown
Contributor

lerian-studio commented May 20, 2026

🔍 PR Validation Summary

✅ PR Mergeable — no blocking failures

Check Status Blocking
Source Branch ✅ success yes
PR Title ✅ success yes
PR Description ✅ success yes
PR Size ✅ success no
Auto Labels ✅ success no
PR Metadata ✅ success no

🔍 View workflow run

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@CHANGELOG.md`:
- Around line 5-6: The long parenthetical in the CHANGELOG entry should be split
into a clear bulleted list of the individual breaking changes: extract and list
each item (options.UpdateOne(), options.Find(), options.Index() now return
*XxxOptionsBuilder; primitive.ObjectID → bson.ObjectID; primitive.DateTime →
bson.DateTime; mongo.Connect no longer takes context.Context;
Collection.Distinct returns *DistinctResult instead of ([]any, error);
WithTransaction callbacks receive context.Context instead of
mongo.SessionContext) as separate bullets under the mongo migration note so
readers can scan each migration step easily while preserving the surrounding
explanation and version context.
- Around line 5-6: Update the changelog to mention that in v2 mongo.Connect no
longer performs an implicit ping/validation of the server, so consumers who
previously relied on that must explicitly call client.Ping(ctx, nil) (or
equivalent health-check) after mongo.Connect(...) to verify connectivity;
reference the changed symbol mongo.Connect and show the explicit call to
client.Ping(ctx, nil) as required follow-up in the migration notes so users are
aware to add that check when upgrading.

In `@commons/tenant-manager/mongo/manager.go`:
- Around line 161-163: The disconnect on Ping failure currently reuses the
incoming ctx (see mongoClient.Ping and mongoClient.Disconnect) which may be
canceled; change it to create a short-lived bounded context (e.g., via
context.WithTimeout or context.WithDeadline) specifically for the
mongoClient.Disconnect call, defer the cancel, and call Disconnect using that
new context so the driver can shut down monitoring goroutines reliably even if
the original request context is expired.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: fcb36519-94d4-4804-a024-89abe6975c99

📥 Commits

Reviewing files that changed from the base of the PR and between 5d6695a and 3398f87.

⛔ Files ignored due to path filters (1)
  • go.sum is excluded by !**/*.sum
📒 Files selected for processing (19)
  • CHANGELOG.md
  • commons/mongo/mongo.go
  • commons/mongo/mongo_integration_test.go
  • commons/mongo/mongo_test.go
  • commons/outbox/mongo/claim.go
  • commons/outbox/mongo/coverage_boost_test.go
  • commons/outbox/mongo/document.go
  • commons/outbox/mongo/extra_test.go
  • commons/outbox/mongo/helpers.go
  • commons/outbox/mongo/indexes.go
  • commons/outbox/mongo/pure_functions_test.go
  • commons/outbox/mongo/repository.go
  • commons/outbox/mongo/repository_integration_test.go
  • commons/outbox/mongo/repository_test.go
  • commons/tenant-manager/core/context.go
  • commons/tenant-manager/core/context_test.go
  • commons/tenant-manager/mongo/manager.go
  • commons/tenant-manager/mongo/manager_test.go
  • go.mod

Comment thread CHANGELOG.md Outdated
Comment thread commons/tenant-manager/mongo/manager.go
@lerian-studio
Copy link
Copy Markdown
Contributor

lerian-studio commented May 20, 2026

📊 Unit Test Coverage Report: app

Metric Value
Overall Coverage 87.0% ✅ PASS
Threshold 80%

Coverage by Package

Package Coverage
github.com/LerianStudio/lib-commons/v5/commons/backoff 91.1%
github.com/LerianStudio/lib-commons/v5/commons/certificate 88.8%
github.com/LerianStudio/lib-commons/v5/commons/circuitbreaker 86.8%
github.com/LerianStudio/lib-commons/v5/commons/cron 94.2%
github.com/LerianStudio/lib-commons/v5/commons/crypto 95.6%
github.com/LerianStudio/lib-commons/v5/commons/dlq 81.0%
github.com/LerianStudio/lib-commons/v5/commons/errgroup 86.1%
github.com/LerianStudio/lib-commons/v5/commons/internal/nilcheck 100.0%
github.com/LerianStudio/lib-commons/v5/commons/jwt 89.4%
github.com/LerianStudio/lib-commons/v5/commons/license 96.9%
github.com/LerianStudio/lib-commons/v5/commons/mongo 89.0%
github.com/LerianStudio/lib-commons/v5/commons/net/http/idempotency 93.0%
github.com/LerianStudio/lib-commons/v5/commons/net/http/ratelimit 90.8%
github.com/LerianStudio/lib-commons/v5/commons/net/http 96.1%
github.com/LerianStudio/lib-commons/v5/commons/outbox 91.9%
github.com/LerianStudio/lib-commons/v5/commons/pointers 100.0%
github.com/LerianStudio/lib-commons/v5/commons/postgres 84.6%
github.com/LerianStudio/lib-commons/v5/commons/rabbitmq 89.3%
github.com/LerianStudio/lib-commons/v5/commons/redis 89.5%
github.com/LerianStudio/lib-commons/v5/commons/safe 99.6%
github.com/LerianStudio/lib-commons/v5/commons/secretsmanager 98.7%
github.com/LerianStudio/lib-commons/v5/commons/security/ssrf 95.9%
github.com/LerianStudio/lib-commons/v5/commons/security 100.0%
github.com/LerianStudio/lib-commons/v5/commons/server 88.0%
github.com/LerianStudio/lib-commons/v5/commons/tenant-manager/cache 97.9%
github.com/LerianStudio/lib-commons/v5/commons/tenant-manager/client 93.0%
github.com/LerianStudio/lib-commons/v5/commons/tenant-manager/consumer 87.9%
github.com/LerianStudio/lib-commons/v5/commons/tenant-manager/core 99.0%
github.com/LerianStudio/lib-commons/v5/commons/tenant-manager/event 95.7%
github.com/LerianStudio/lib-commons/v5/commons/tenant-manager/internal/eviction 100.0%
github.com/LerianStudio/lib-commons/v5/commons/tenant-manager/log 100.0%
github.com/LerianStudio/lib-commons/v5/commons/tenant-manager/middleware 92.3%
github.com/LerianStudio/lib-commons/v5/commons/tenant-manager/mongo 76.3%
github.com/LerianStudio/lib-commons/v5/commons/tenant-manager/postgres 86.8%
github.com/LerianStudio/lib-commons/v5/commons/tenant-manager/rabbitmq 82.6%
github.com/LerianStudio/lib-commons/v5/commons/tenant-manager/redis 93.8%
github.com/LerianStudio/lib-commons/v5/commons/tenant-manager/s3 96.3%
github.com/LerianStudio/lib-commons/v5/commons/tenant-manager/tenantcache 98.4%
github.com/LerianStudio/lib-commons/v5/commons/tenant-manager/valkey 100.0%
github.com/LerianStudio/lib-commons/v5/commons/transaction 95.1%
github.com/LerianStudio/lib-commons/v5/commons/webhook 91.5%
github.com/LerianStudio/lib-commons/v5/commons 96.4%

Generated by Go PR Analysis workflow

- manager.go: use bounded context for Disconnect on Ping failure. Reusing the
  request context risked carrying an already-canceled ctx into Disconnect,
  which prevents the driver from cleanly tearing down topology/monitoring
  goroutines.
- CHANGELOG: split the v5.3.0 migration notes into a scannable bulleted list
  and document that v2 mongo.Connect no longer pings the server implicitly —
  callers that relied on Connect-time reachability validation must add an
  explicit client.Ping(ctx, nil) after connecting.

X-Lerian-Ref: 0x1
The pattern of passing a request-scoped context to mongo.Client.Disconnect
risks leaking topology/monitoring goroutines when the caller's context has
already been canceled. The driver requires a non-canceled context to
complete its graceful shutdown sequence.

Centralize the fix in a disconnectClient helper that always derives a fresh
bounded context from context.Background() with a 10s timeout. Apply it to
all 7 Disconnect call sites in tenant-manager/mongo/manager.go:

- connectWithTLS (Ping-failure cleanup, addressed earlier in this PR)
- swapMongoConnection (config-change replacement)
- cacheConnection (closed-manager and excess-connection branches)
- evictLRU (LRU pool eviction)
- Close (Manager shutdown)
- CloseConnection (per-tenant disconnect)

The swapMongoConnection signature drops its unused ctx parameter as a
consequence; updated the single test caller accordingly.

X-Lerian-Ref: 0x1
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
commons/tenant-manager/mongo/manager.go (1)

828-844: ⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

Avoid disconnecting Mongo clients while p.mu is held.

These branches perform network teardown under the manager write lock, and disconnectClient can wait up to 10 seconds. One slow shutdown here will serialize unrelated GetConnection/CloseConnection work across all tenants. Snapshot the client to close under the lock, release the lock, then disconnect outside.

Applies to cacheConnection (lines 828–836, 838–848) and evictLRU (line 878).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@commons/tenant-manager/mongo/manager.go` around lines 828 - 844, In
cacheConnection and evictLRU, avoid calling disconnectClient while holding the
manager lock p.mu; instead, under the lock snapshot and remove the client (e.g.,
read and delete p.connections[tenantID] and clear conn.DB) and store the DB
client reference in a local variable, release the lock, then call
disconnectClient on that local client; update the cacheConnection and evictLRU
code paths to follow this pattern so that network teardown (disconnectClient)
happens outside the locked region and p.mu only protects mutations of
p.connections and related state.
♻️ Duplicate comments (1)
commons/tenant-manager/mongo/manager.go (1)

40-53: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Route the remaining Disconnect paths through this helper.

This helper fixes only part of the file: disconnectMongo and disconnectUnhealthyConnection still call Client.Disconnect with request-scoped contexts, so reconnect cleanup and stale-connection cleanup can still short-circuit when the caller context is already canceled.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@commons/tenant-manager/mongo/manager.go` around lines 40 - 53, The file still
calls Client.Disconnect with request-scoped contexts in disconnectMongo and
disconnectUnhealthyConnection; update both to route all disconnects through the
helper disconnectClient(*mongo.Client) so the driver always uses a fresh bounded
context. Concretely, replace any calls like client.Disconnect(ctx) inside
disconnectMongo and disconnectUnhealthyConnection with disconnectClient(client)
(preserve nil checks and propagate returned errors unchanged) so the helper's
contextWithTimeout behavior is used for all disconnect paths.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@commons/tenant-manager/mongo/manager.go`:
- Around line 828-844: In cacheConnection and evictLRU, avoid calling
disconnectClient while holding the manager lock p.mu; instead, under the lock
snapshot and remove the client (e.g., read and delete p.connections[tenantID]
and clear conn.DB) and store the DB client reference in a local variable,
release the lock, then call disconnectClient on that local client; update the
cacheConnection and evictLRU code paths to follow this pattern so that network
teardown (disconnectClient) happens outside the locked region and p.mu only
protects mutations of p.connections and related state.

---

Duplicate comments:
In `@commons/tenant-manager/mongo/manager.go`:
- Around line 40-53: The file still calls Client.Disconnect with request-scoped
contexts in disconnectMongo and disconnectUnhealthyConnection; update both to
route all disconnects through the helper disconnectClient(*mongo.Client) so the
driver always uses a fresh bounded context. Concretely, replace any calls like
client.Disconnect(ctx) inside disconnectMongo and disconnectUnhealthyConnection
with disconnectClient(client) (preserve nil checks and propagate returned errors
unchanged) so the helper's contextWithTimeout behavior is used for all
disconnect paths.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: e99d270d-761d-4a8b-9486-a29cbfb40c09

📥 Commits

Reviewing files that changed from the base of the PR and between 6d21937 and 624ca67.

📒 Files selected for processing (2)
  • commons/tenant-manager/mongo/coverage_boost_test.go
  • commons/tenant-manager/mongo/manager.go

@jeffersonrodrigues92 jeffersonrodrigues92 merged commit d350b1a into develop May 20, 2026
22 checks passed
@github-actions github-actions Bot deleted the feat/mongo-driver-v2 branch May 20, 2026 03:16
@lerian-studio lerian-studio added size/XS PR changes < 50 lines and removed size/S PR changes 50–199 lines labels May 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

deps Go module dependencies (usually opened by Dependabot) docs Documentation and markdown content mongo MongoDB connector outbox Outbox pattern size/XS PR changes < 50 lines tenant-manager Tenant manager tests Unit, integration and end-to-end tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants