• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

safe-global / safe-client-gateway / 20091945613

10 Dec 2025 08:19AM UTC coverage: 89.03% (-1.2%) from 90.212%
20091945613

push

github

web-flow
refactor(cache): change Zerion cache keys to be per address only (#2839)

* refactor(cache): change Zerion cache keys to be per address only

Remove chainId from Zerion cache keys for balances, collectibles, and positions.
This changes the caching strategy from per-chain-per-address to per-address only,
allowing data to be shared across chains for the same address.

Cache key changes:
- Before: {chainId}_zerion_balances_{safeAddress}
- After: zerion_balances_{safeAddress}

Similar changes applied to positions and collectibles cache keys.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

Prettier

* refactor: remove unused chainId parameter from clear methods

Remove chainId parameter from clearBalances and clearCollectibles methods
in IBalancesApi interface and implementations. After the refactoring to
per-address cache keys, chainId is no longer needed by the API methods:

- ZerionBalancesApi uses address-only cache keys
- SafeBalancesApi uses its instance chainId variable

The repositories still accept chainId (needed to select the correct API)
but no longer pass it to the clear methods.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* Fix tests: Separate unit tests from integration/e2e tests

- Renamed tests requiring real infrastructure (.spec.ts -> .integration.spec.ts or .e2e-spec.ts)
- Updated package.json Jest config to exclude integration and e2e tests from default 'yarn test' run
- Tests requiring Redis, Postgres, or full app bootstrap are now properly categorized
- All 308 unit test suites now pass without requiring external services

Renamed files:
- Redis cache service test -> integration test
- Postgres database module tests (v1 & v2) -> integration tests
- Postgres database service test -> integration test
- Auth decorator test -> e2e test
- Spaces-related controller tests -> e2e tests
- ... (continued)

2835 of 3551 branches covered (79.84%)

Branch coverage included in aggregate %.

4 of 8 new or added lines in 5 files covered. (50.0%)

199 existing lines in 34 files now uncovered.

13616 of 14927 relevant lines covered (91.22%)

564.15 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

96.3
/src/datasources/db/v1/postgres-database.migration.hook.ts
1
import { Inject, Injectable, OnModuleInit } from '@nestjs/common';
96✔
2
import { ILoggingService, LoggingService } from '@/logging/logging.interface';
96✔
3
import postgres from 'postgres';
96✔
4
import { PostgresDatabaseMigrator } from '@/datasources/db/v1/postgres-database.migrator';
96✔
5
import { IConfigurationService } from '@/config/configuration.service.interface';
96✔
6
import { asError } from '@/logging/utils';
96✔
7

8
/**
9
 * The {@link PostgresDatabaseMigrationHook} is a Module Init hook meaning
10
 * that it will be executed once the dependencies are resolved.
11
 *
12
 * This happens before the Application Bootstraps, so route listeners are not
13
 * initiated and potentially generating queries.
14
 */
15
@Injectable({})
16
export class PostgresDatabaseMigrationHook implements OnModuleInit {
96✔
17
  private static LOCK_MAGIC_NUMBER = 132;
96✔
18
  private readonly runMigrations: boolean;
19

20
  constructor(
21
    @Inject('DB_INSTANCE') private readonly sql: postgres.Sql,
6✔
22
    @Inject(PostgresDatabaseMigrator)
23
    private readonly migrator: PostgresDatabaseMigrator,
6✔
24
    @Inject(LoggingService) private readonly loggingService: ILoggingService,
6✔
25
    @Inject(IConfigurationService)
26
    private readonly configurationService: IConfigurationService,
6✔
27
  ) {
28
    this.runMigrations = this.configurationService.getOrThrow<boolean>(
6✔
29
      'application.runMigrations',
30
    );
31
  }
32

33
  /**
34
   * Function executed when the module is initialized.
35
   *
36
   * This function will check if the migrations are enabled and if so, it will
37
   * acquire a lock to perform a migration. If the lock is not acquired, then
38
   * a migration is being executed by another instance.
39
   *
40
   * If the lock is acquired, the migration will be executed and the lock will
41
   * be released.
42
   */
43
  async onModuleInit(): Promise<void> {
44
    if (!this.runMigrations) {
4✔
45
      return this.loggingService.info('Database migrations are disabled');
2✔
46
    }
47

48
    try {
2✔
49
      this.loggingService.info('Checking migrations');
2✔
50
      await this.acquireLock();
2✔
51
      const executed = await this.migrator.migrate();
2✔
52
      await this.releaseLock();
2✔
53
      this.loggingService.info(
2✔
54
        `Pending migrations executed: [${executed.map((m) => m.name).join(', ')}]`,
4✔
55
      );
56
    } catch (e) {
UNCOV
57
      this.loggingService.error(`Error running migrations: ${asError(e)}`);
×
58
    }
59
  }
60

61
  private async acquireLock(): Promise<void> {
62
    await this
2✔
63
      .sql`SELECT pg_advisory_lock(${PostgresDatabaseMigrationHook.LOCK_MAGIC_NUMBER})`;
64
  }
65

66
  private async releaseLock(): Promise<void> {
67
    await this
2✔
68
      .sql`SELECT pg_advisory_unlock(${PostgresDatabaseMigrationHook.LOCK_MAGIC_NUMBER})`;
69
  }
70
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc