Skip to content

Commit 90a4be1

Browse files
authored
Merge pull request #513 from hack-a-chain-software/develop
Merge 'develop' into 'main'
2 parents 04c97f3 + 7a6031a commit 90a4be1

File tree

12 files changed

+70
-73
lines changed

12 files changed

+70
-73
lines changed

CHANGELOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,15 @@
11
# Changelog
22

3+
## Sep 12 - Oct 9, 2025
4+
5+
v1.1.1
6+
7+
- fix: silencing error throw from retried functions
8+
- fix: closing idle connections on the db pool
9+
- fix: reduced sentry sample ratio
10+
- refactor: removed unused import and function
11+
- feat: tracking memory usage every thirty minutes
12+
313
## Aug 13 - Sep 11, 2025
414

515
- fix: remove unnecessary error throwing in dataloaders

indexer/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@kadena-indexer/indexer",
33
"description": "Indexer for the Kadena blockchain",
4-
"version": "1.0.0",
4+
"version": "1.1.1",
55
"main": "index.js",
66
"author": "Hackachain team",
77
"license": "ISC",

indexer/src/cache/init.ts

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -76,10 +76,7 @@ export default async function initCache(context: ResolverContext) {
7676
};
7777
MEMORY_CACHE.set(HASH_RATE_AND_TOTAL_DIFFICULTY_KEY, newValue);
7878
} catch (err) {
79-
console.error(
80-
'[ERROR][CACHE][CONN_TIMEOUT] Failed to get hash rate and total difficulty',
81-
err,
82-
);
79+
console.warn('[WARN][CACHE][DB] Failed to get hash rate and total difficulty', err);
8380
}
8481
}
8582

@@ -94,7 +91,7 @@ export default async function initCache(context: ResolverContext) {
9491
const networkStatistics = await networkRepository.getNetworkStatistics();
9592
MEMORY_CACHE.set(NETWORK_STATISTICS_KEY, networkStatistics);
9693
} catch (err) {
97-
console.error('[ERROR][CACHE][CONN_TIMEOUT] Failed to get network statistics', err);
94+
console.warn('[WARN][CACHE][DB] Failed to get network statistics', err);
9895
}
9996
}
10097

@@ -109,23 +106,20 @@ export default async function initCache(context: ResolverContext) {
109106
const nodeInfo = await networkRepository.getNodeInfo();
110107
MEMORY_CACHE.set(NODE_INFO_KEY, nodeInfo);
111108
} catch (err) {
112-
console.error('[ERROR][CACHE][CONN_TIMEOUT] Failed to get node info', err);
109+
console.warn('[WARN][CACHE][DB] Failed to get node info', err);
113110
}
114111
}
115112

116113
/**
117-
* Fetches and caches information about the blockchain node
118-
*
119-
* This includes node version, connectivity status, and other
120-
* node-specific information that helps monitor the node's health.
114+
* Fetches and caches information about number of blocks, transactions,
115+
* and total gas used in each chain.
121116
*/
122-
123117
async function getCountersOfEachChain() {
124118
try {
125119
const counters = await networkRepository.getCountersOfEachChain();
126120
MEMORY_CACHE.set(COUNTERS_OF_EACH_CHAIN_KEY, counters);
127121
} catch (err) {
128-
console.error('[ERROR][CACHE][CONN_TIMEOUT] Failed to get counters of each chain', err);
122+
console.warn('[WARN][CACHE][DB] Failed to get counters of each chain', err);
129123
}
130124
}
131125

indexer/src/config/database.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,14 @@ if (isSslEnabled) {
4444
* This provides a lower-level database access mechanism than Sequelize.
4545
*
4646
* When SSL is enabled, it uses the global certificate bundle for secure connections.
47-
*
48-
* TODO: [OPTIMIZATION] Consider implementing connection pooling metrics to monitor performance
49-
* and adjust pool settings accordingly.
5047
*/
5148
export const rootPgPool = new Pool({
5249
connectionString: DB_CONNECTION,
50+
max: 20, // Max connections
51+
idleTimeoutMillis: 30000, // Close idle connections after 30s
52+
connectionTimeoutMillis: 10000, // Fail if can't get connection in 10s
53+
statement_timeout: 30000, // Cancel queries after 30s (PostgreSQL)
54+
query_timeout: 30000, // Client-side query timeout
5355
...(isSslEnabled && {
5456
ssl: {
5557
rejectUnauthorized: rejectUnauthorized,

indexer/src/index.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import { startStreaming } from './services/streaming';
2020
import { backfillPairEvents } from './services/pair';
2121
import { setupAssociations } from './models/setup-associations';
2222
import { PriceUpdaterService } from '@/services/price/price-updater.service';
23+
import { initializeMemoryMonitoring } from '@/utils/memory-usage';
2324

2425
/**
2526
* Command-line interface configuration using Commander.
@@ -49,8 +50,9 @@ const options = program.opts();
4950
*/
5051
async function main() {
5152
try {
52-
console.info('Starting v1.1.0');
53+
console.info('Starting v1.1.1');
5354
initializeErrorMonitoring();
55+
initializeMemoryMonitoring();
5456
setupAssociations();
5557
PriceUpdaterService.getInstance();
5658

indexer/src/kadena-server/plugins/instrument.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ if (!SENTRY_DSN || SENTRY_DSN.trim() === '') {
2121
environment: SENTRY_ENVIRONMENT,
2222
release: SENTRY_RELEASE,
2323
sendDefaultPii: true,
24-
tracesSampleRate: 1.0,
25-
profileSessionSampleRate: 1.0,
24+
tracesSampleRate: 0.05,
25+
profileSessionSampleRate: 0.05,
2626
profileLifecycle: 'trace',
2727
integrations: [
2828
nodeProfilingIntegration(),

indexer/src/kadena-server/plugins/sentry-plugin.ts

Lines changed: 10 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -10,41 +10,17 @@ import { ResolverContext } from '../config/apollo-server-config';
1010
export function createSentryPlugin(): ApolloServerPlugin<ResolverContext> {
1111
return {
1212
async requestDidStart({ request, contextValue }) {
13-
Sentry.startSpan(
14-
{
15-
name: request.operationName || 'anonymous',
16-
op: 'graphql.query',
17-
attributes: {
18-
'random-test': 'test',
19-
'operation.type': 'graphql.query',
20-
'operation.name': request.operationName || 'anonymous',
21-
},
13+
// Log incoming queries to Sentry as breadcrumbs (no manual spans or profiler here)
14+
Sentry.addBreadcrumb({
15+
category: 'graphql.query',
16+
message: request.operationName || 'Anonymous GraphQL operation',
17+
level: 'info',
18+
data: {
19+
query: request.query,
20+
variables: request.variables,
21+
operationType: request.operationName ? 'named' : 'anonymous',
2222
},
23-
span => {
24-
// Set operation attributes
25-
span.setAttributes({
26-
'operation.details.type': 'graphql.query',
27-
'operation.details.name': request.operationName || 'anonymous',
28-
'operation.details.timestamp': new Date().toISOString(),
29-
'operation.details.query': request.query,
30-
});
31-
32-
// Optionally log all incoming queries to Sentry as breadcrumbs
33-
// Breadcrumbs create a historical trail that persists (query history)
34-
Sentry.profiler.startProfiler();
35-
Sentry.addBreadcrumb({
36-
category: 'graphql.query',
37-
message: request.operationName || 'Anonymous GraphQL operation',
38-
level: 'info',
39-
data: {
40-
query: request.query,
41-
variables: request.variables,
42-
operationType: request.operationName ? 'named' : 'anonymous',
43-
},
44-
});
45-
Sentry.profiler.stopProfiler();
46-
},
47-
);
23+
});
4824
return {
4925
async didEncounterErrors({ errors, operation, operationName, request }) {
5026
// Skip Apollo-specific errors that are intentionally thrown

indexer/src/kadena-server/server.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@ import {
4343
} from 'graphql';
4444

4545
import initCache from '../cache/init';
46-
import { getArrayEnvString } from '../utils/helpers';
4746
import {
4847
directiveEstimator,
4948
fieldExtensionsEstimator,

indexer/src/services/monitoring.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ export function initializeErrorMonitoring(): void {
7272
]
7373
.filter(Boolean)
7474
.join(', ');
75-
console.warn(`[WARN][MONITORING] Monitoring not initialized. Missing env: ${missing}`);
75+
console.error(`[WARN][MONITORING][ENV] Monitoring not initialized. Missing env: ${missing}`);
7676
return; // Monitoring disabled; keep local logging only
7777
}
7878

indexer/src/services/price/price-updater.service.ts

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
import axios from 'axios';
2-
31
import { PriceService } from './price.service';
42

53
export class PriceUpdaterService {
@@ -23,11 +21,26 @@ export class PriceUpdaterService {
2321

2422
private async updatePrice(): Promise<void> {
2523
try {
26-
const response = await axios.get(this.DIA_API_URL);
27-
const price = response.data.Price;
28-
this.priceService.setKdaUsdPrice(price);
24+
const response = await fetch(this.DIA_API_URL, {
25+
headers: {
26+
Accept: 'application/json',
27+
'User-Agent': 'node-fetch',
28+
},
29+
});
30+
31+
if (!response.ok) {
32+
throw new Error(`HTTP ${response.status} - ${response.statusText}`);
33+
}
34+
35+
const data = await response.json();
36+
37+
if (data?.Price === undefined) {
38+
throw new Error('Price field is missing in API response');
39+
}
40+
41+
this.priceService.setKdaUsdPrice(data.Price);
2942
} catch (error) {
30-
console.error('[ERROR][INT][INT_API] Failed to update KDA/USD price:', error);
43+
console.warn('[WARN][INT][INT_API] Failed to update KDA/USD price:', error);
3144
}
3245
}
3346

0 commit comments

Comments
 (0)