Skip to content

Conversation

@stalniy
Copy link
Contributor

@stalniy stalniy commented Jan 31, 2026

Why

to get rid of side effects inside src/db/dbConnection.ts and improve testability

Summary by CodeRabbit

Release Notes

  • Chores
    • Refactored internal database access and service initialization architecture for improved maintainability and testability.
    • Restructured application startup sequences to ensure proper initialization ordering.
    • Updated test infrastructure to align with service initialization patterns.

✏️ Tip: You can customize this high-level summary in your review settings.

@stalniy stalniy requested a review from a team as a code owner January 31, 2026 16:01
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 31, 2026

📝 Walkthrough

Walkthrough

This pull request migrates the codebase from direct module-scoped chainDb references to a dependency injection (DI) pattern using tsyringe. It introduces CHAIN_DB and USER_DB as InjectionToken symbols, updates services and repositories to inject these tokens, removes global database authentication from CLI startup, and exports a new initDb() function for test initialization.

Changes

Cohort / File(s) Summary
Core DI Infrastructure
apps/api/src/chain/providers/sequelize.provider.ts, apps/api/src/chain/index.ts
Introduces CHAIN_DB and USER_DB as InjectionToken exports; reworks database factory registrations to support per-container Sequelize instances; removes direct chainDb/userDb exports; rearranges connectUsingSequelize to authenticate via container-resolved tokens.
Startup & Initialization
apps/api/src/app/console.ts, apps/api/src/app/index.ts, apps/api/src/rest-app.ts, apps/api/src/core/providers/raw-app-config.provider.ts
Removes chainDb authentication from CLI startup sequence; adds side-effect import of @src/chain; updates connectUsingSequelize import source; removes comment from provider registration.
Billing Module
apps/api/src/billing/repositories/usage/usage.repository.ts, apps/api/src/billing/repositories/usage/usage.repository.spec.ts, apps/api/src/billing/services/financial-stats/financial-stats.service.ts
Injects CHAIN_DB dependency; updates constructor signatures to accept injected Sequelize instance; replaces direct chainDb usage with injected field references in queries.
Dashboard Services
apps/api/src/dashboard/services/stats/stats.service.ts, apps/api/src/dashboard/services/stats/stats.service.spec.ts
Injects CHAIN_DB as constructor parameter; updates test setup to resolve CHAIN_DB via container; replaces module-scoped chainDb with injected instance field.
GPU & Provider Repositories/Services
apps/api/src/gpu/repositories/gpu.repository.ts, apps/api/src/provider/repositories/provider/provider.repository.spec.ts, apps/api/src/provider/services/provider-graph-data/provider-graph-data.service.ts, apps/api/src/provider/services/provider-dashboard/provider-dashboard.service.spec.ts, apps/api/src/provider/services/provider-regions/provider-regions.service.spec.ts, apps/api/src/provider/services/provider-stats/provider-stats.service.ts, apps/api/src/provider/services/provider-versions/provider-versions.service.ts, apps/api/src/provider/services/provider-versions/provider-versions.service.spec.ts
Injects CHAIN_DB token into constructors; updates test files to use container.resolve(CHAIN_DB) instead of direct imports; replaces direct chainDb references with injected Sequelize fields.
Transaction & Stats Services
apps/api/src/transaction/repositories/transaction/transaction.repository.ts, apps/api/src/services/db/statsService.ts
Injects CHAIN_DB dependency into TransactionRepository; updates statsService to use container.resolve(CHAIN_DB) for database queries; extends query result types to include additional storage fields.
Functional Tests
apps/api/test/functional/addresses.spec.ts, apps/api/test/functional/blocks.spec.ts, apps/api/test/functional/managed-api-deployment-flow.spec.ts, apps/api/test/functional/provider-deployments.spec.ts, apps/api/test/functional/usage.spec.ts, apps/api/test/functional/validators.spec.ts
Updates test setup to import and await new initDb() function from @src/rest-app; moves database initialization to beforeAll/beforeEach hooks; removes direct connectUsingSequelize calls.

Sequence Diagram

sequenceDiagram
    participant App as Application Startup
    participant Container as DI Container
    participant SeqProvider as Sequelize Provider
    participant ChainDB as CHAIN_DB Token
    participant Service as Service/Repository
    participant DB as Database

    App->>Container: Initialize container
    App->>SeqProvider: Register CHAIN_DB factory
    SeqProvider->>Container: Register factory with CHAIN_DB token
    
    App->>Service: Instantiate service with `@inject`(CHAIN_DB)
    Service->>Container: Resolve CHAIN_DB token
    Container->>SeqProvider: Execute CHAIN_DB factory
    SeqProvider->>DB: Create Sequelize instance
    DB-->>SeqProvider: Instance created
    SeqProvider-->>Container: Return Sequelize instance
    Container-->>Service: Inject Sequelize instance
    
    Service->>Service: Store in private `#chainDb` field
    Service->>DB: Execute query via this.#chainDb
    DB-->>Service: Query result
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Possibly related PRs

Suggested reviewers

  • ygrishajev
  • baktun14

Poem

🐰 The container now holds each database tight,
No more global chainDb in the night!
Each service requests what it needs with grace,
Dependency injection finds its place,
Tests initialize cleanly, one by one—
The refactor hops on, and the journey's begun! 🌟

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 14.29% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main refactoring objective of moving Sequelize creation from direct imports into DI container factories across the codebase.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch refactor/sequelize

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

Copy link
Contributor

@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: 4

🤖 Fix all issues with AI agents
In `@apps/api/src/app/console.ts`:
- Line 81: The CLI startup removed the DB authentication so commands fail;
restore DB auth by calling chainDb.authenticate() before running migratePG() and
other initializers or add an APP_INITIALIZER that calls chainDb.authenticate()
on startup. Concretely, ensure chainDb.authenticate() is invoked (or wrapped in
a promise-returning initializer registered with APP_INITIALIZER that implements
ON_APP_START) so that database authentication completes before migratePG() and
container.resolveAll(APP_INITIALIZER).map(initializer =>
initializer[ON_APP_START]()) run; reference the chainDb.authenticate() call or
create an initializer service that performs chainDb.authenticate() to guarantee
the DB is connected prior to CLI execution.

In `@apps/api/src/dashboard/services/stats/stats.service.spec.ts`:
- Around line 4-7: The test is resolving a real chainDb from the DI container
(CHAIN_DB) instead of using a mock, which can cause side effects; replace the
container.resolve(CHAIN_DB) usage in stats.service.spec.ts with a
jest-mock-extended mock (e.g., mockDeep<Type>() or mock<...>()) named
mockChainDb, and inject that mock into the StatsService under test the same way
cosmosHttpService and coinGeckoHttpService are mocked and passed in—ensure you
import mock/mocDeep from jest-mock-extended, create mockChainDb, and provide it
to the service constructor or test DI registration instead of resolving CHAIN_DB
from tsyringe.

In `@apps/api/src/provider/repositories/provider/provider.repository.spec.ts`:
- Around line 276-277: The height fallback in the createProvider helper
incorrectly uses || which treats createdHeight = 0 as falsy; update the
expression in createProvider so it uses the nullish coalescing operator (??) to
only fall back to the DB max height when overrides.createdHeight is null or
undefined, preserving a zero value; locate the createProvider function and
replace the || fallback for overrides.createdHeight with ?? when computing
height.

In `@apps/api/test/functional/provider-deployments.spec.ts`:
- Around line 112-114: The beforeEach hook is calling initDb() which
reinitializes/truncates the database and therefore destroys the seeded data
created in beforeAll; either remove the beforeEach hook that calls initDb() or
move the seeding logic from beforeAll into beforeEach so that initDb() runs
before creating providers/deployments/leases/blocks; update or remove the
beforeEach(async () => { await initDb(); }) accordingly and ensure tests
reference the seeding functions (the setup in beforeAll or the new beforeEach)
so each test sees the expected records.
🧹 Nitpick comments (4)
apps/api/test/functional/managed-api-deployment-flow.spec.ts (1)

576-579: Consider using LoggerService instead of console.error.

The coding guidelines specify using LoggerService for logging instead of console.error. While this is in a test file for debugging purposes, consider using the project's logging infrastructure for consistency.

Suggested change
     if (!data?.data?.leases) {
-      console.error("Cannot create lease", data);
+      // Consider injecting or importing a logger if detailed error logging is needed
       return undefined;
     }

As per coding guidelines: "Use LoggerService instead of console.log, console.warn, or console.error for logging"

apps/api/src/provider/services/provider-dashboard/provider-dashboard.service.spec.ts (3)

12-12: Use ProviderDashboardService.name for the root suite.

♻️ Proposed change
-describe("Provider Dashboard", () => {
+describe(ProviderDashboardService.name, () => {

As per coding guidelines, Use <Subject>.name in the root describe suite description instead of hardcoded class/service name strings to enable automated refactoring tools to find all references.


38-38: Prefer a method name or a “when …” condition for nested suites.

♻️ Proposed change
-describe("GET /v1/provider-dashboard/{owner}", () => {
+describe("getProviderDashboard", () => {

As per coding guidelines, Use either a method name or a condition starting with 'when' for nested suite descriptions in tests.


55-57: Move setup to the root describe bottom and accept an inline-typed param.

♻️ Proposed change
-    function setup() {
-      return new ProviderDashboardService();
-    }
   });
+
+  function setup(_: {} = {}) {
+    return new ProviderDashboardService();
+  }
 });

As per coding guidelines, Use setup function instead of beforeEach in test files. The setup function must be at the bottom of the root describe block, should create an object under test and return it, accept a single parameter with inline type definition, avoid shared state, and not have a specified return type.

@stalniy stalniy force-pushed the refactor/sequelize branch from 4aba56a to 207018b Compare January 31, 2026 22:00
Copy link
Contributor

@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: 0

Caution

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

⚠️ Outside diff range comments (1)
apps/api/src/billing/repositories/usage/usage.repository.spec.ts (1)

414-423: ⚠️ Potential issue | 🟡 Minor

Update setup() signature and mocks to match test guidelines.

setup() should accept a single parameter with an inline type definition, and mocks should come from jest-mock-extended rather than manual jest.fn() + casting.

🔧 Suggested refactor
+import { mock } from "jest-mock-extended";
 ...
-  function setup() {
-    const userWalletRepository = {
-      findOneByAddress: jest.fn().mockResolvedValue(undefined)
-    } as unknown as UserWalletRepository;
-
-    const txManagerService = {
-      getDerivedWalletAddress: jest.fn().mockResolvedValue("")
-    } as unknown as TxManagerService;
+  function setup({
+    userWalletRepository: userWalletRepositoryOverrides,
+    txManagerService: txManagerServiceOverrides
+  }: {
+    userWalletRepository?: Partial<UserWalletRepository>;
+    txManagerService?: Partial<TxManagerService>;
+  } = {}) {
+    const userWalletRepository = mock<UserWalletRepository>();
+    userWalletRepository.findOneByAddress.mockResolvedValue(undefined);
+    Object.assign(userWalletRepository, userWalletRepositoryOverrides);
+
+    const txManagerService = mock<TxManagerService>();
+    txManagerService.getDerivedWalletAddress.mockResolvedValue("");
+    Object.assign(txManagerService, txManagerServiceOverrides);
 
     const usageRepository = new UsageRepository(container.resolve(CHAIN_DB), userWalletRepository, txManagerService);

As per coding guidelines: "Don't use jest.mock() in test files. Instead, use jest-mock-extended to create mocks and pass mocks as dependencies to the service under test" and "Use setup function instead of beforeEach in test files. The setup function must be at the bottom of the root describe block, should create an object under test and return it, accept a single parameter with inline type definition, avoid shared state, and not have a specified return type."

🧹 Nitpick comments (2)
apps/api/test/functional/addresses.spec.ts (1)

214-215: Consider moving initDb() to beforeAll for consistency and efficiency.

In validators.spec.ts, initDb() is called once in beforeAll. Here, it's called inside setup() which runs for every test (~11 times). This creates an inconsistency and may cause redundant initialization overhead.

♻️ Suggested refactor

Add a beforeAll block and remove initDb() from setup():

 describe("Addresses API", () => {
+  beforeAll(async () => {
+    await initDb();
+  });
+
   afterEach(async () => {

Then remove from setup:

   const setup = async () => {
-    await initDb();
-
     const address = createAkashAddress();
apps/api/src/provider/services/provider-versions/provider-versions.service.spec.ts (1)

11-11: Use ProviderVersionsService.name instead of a hardcoded string.

The root describe block should use the class name reference for better refactoring support.

-describe("Provider Dashboard", () => {
+describe(ProviderVersionsService.name, () => {

As per coding guidelines: "Use <Subject>.name in the root describe suite description instead of hardcoded class/service name strings to enable automated refactoring tools to find all references."

@codecov
Copy link

codecov bot commented Jan 31, 2026

Codecov Report

❌ Patch coverage is 95.31250% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 50.16%. Comparing base (4665f2b) to head (207018b).
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
...ervices/financial-stats/financial-stats.service.ts 60.00% 2 Missing ⚠️
apps/api/src/chain/providers/sequelize.provider.ts 94.44% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2636      +/-   ##
==========================================
- Coverage   50.91%   50.16%   -0.75%     
==========================================
  Files        1055     1020      -35     
  Lines       29781    28965     -816     
  Branches     6713     6599     -114     
==========================================
- Hits        15162    14531     -631     
+ Misses      14335    14034     -301     
- Partials      284      400     +116     
Flag Coverage Δ *Carryforward flag
api 78.30% <95.31%> (+0.02%) ⬆️
deploy-web 32.24% <ø> (ø) Carriedforward from 4665f2b
log-collector ?
notifications 87.94% <ø> (ø) Carriedforward from 4665f2b
provider-console 81.48% <ø> (ø) Carriedforward from 4665f2b
provider-proxy 84.35% <ø> (ø) Carriedforward from 4665f2b
tx-signer ?

*This pull request uses carry forward flags. Click here to find out more.

Files with missing lines Coverage Δ
...src/billing/repositories/usage/usage.repository.ts 90.32% <100.00%> (+0.32%) ⬆️
.../api/src/core/providers/raw-app-config.provider.ts 100.00% <ø> (ø)
.../api/src/dashboard/services/stats/stats.service.ts 97.61% <100.00%> (+0.01%) ⬆️
apps/api/src/gpu/repositories/gpu.repository.ts 79.06% <100.00%> (+0.49%) ⬆️
...provider-graph-data/provider-graph-data.service.ts 96.77% <100.00%> (+0.10%) ⬆️
.../services/provider-stats/provider-stats.service.ts 92.85% <100.00%> (+1.19%) ⬆️
...ces/provider-versions/provider-versions.service.ts 100.00% <100.00%> (ø)
apps/api/src/services/db/statsService.ts 83.33% <100.00%> (+0.98%) ⬆️
...repositories/transaction/transaction.repository.ts 95.00% <100.00%> (+0.12%) ⬆️
apps/api/src/chain/providers/sequelize.provider.ts 89.13% <94.44%> (ø)
... and 1 more

... and 73 files with indirect coverage changes

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants