Skip to content

Commit da6dde6

Browse files
committed
track
1 parent 7e24ca1 commit da6dde6

File tree

3 files changed

+89
-2
lines changed

3 files changed

+89
-2
lines changed

packages/global/common/middle/tracks/constants.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,6 @@ export enum TrackEnum {
99
datasetSearch = 'datasetSearch',
1010
readSystemAnnouncement = 'readSystemAnnouncement',
1111
clickOperationalAd = 'clickOperationalAd',
12-
closeOperationalAd = 'closeOperationalAd'
12+
closeOperationalAd = 'closeOperationalAd',
13+
teamChatQPM = 'teamChatQPM'
1314
}
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
import { getGlobalRedisConnection } from '../../redis';
2+
import { TrackModel } from './schema';
3+
import { TrackEnum } from '@fastgpt/global/common/middle/tracks/constants';
4+
import { addLog } from '../../system/log';
5+
6+
const getCurrentMinuteBoundary = (): Date => {
7+
const now = new Date();
8+
const boundary = new Date(now);
9+
boundary.setSeconds(0, 0);
10+
return boundary;
11+
};
12+
13+
export const recordTeamQPM = async () => {
14+
try {
15+
const redis = getGlobalRedisConnection();
16+
17+
const keysWithPrefix = await redis.keys('fastgpt:frequency:chat:*');
18+
19+
if (keysWithPrefix.length === 0) {
20+
addLog.info('No team chat activity in the last minute');
21+
return;
22+
}
23+
24+
addLog.info(`Recording QPM for ${keysWithPrefix.length} teams`);
25+
26+
// Batch read all counts using pipeline for efficiency
27+
const pipeline = redis.pipeline();
28+
keysWithPrefix.forEach((key) => {
29+
const keyWithoutPrefix = key.replace(/^fastgpt:/, '');
30+
pipeline.get(keyWithoutPrefix);
31+
});
32+
const results = await pipeline.exec();
33+
34+
if (!results) {
35+
addLog.error('Failed to read QPM data from Redis');
36+
return;
37+
}
38+
39+
// Prepare bulk write operations
40+
const currentMinute = getCurrentMinuteBoundary();
41+
const bulkOps = keysWithPrefix
42+
.map((key, index) => {
43+
const teamId = key.replace(/^fastgpt:frequency:chat:/, '');
44+
const [error, count] = results[index];
45+
46+
if (error || !count) {
47+
addLog.warn(`Failed to read count for team ${teamId}`, { error });
48+
return null;
49+
}
50+
51+
const requestCount = parseInt(count as string, 10);
52+
53+
if (requestCount > 0) {
54+
return {
55+
updateOne: {
56+
filter: {
57+
event: TrackEnum.teamChatQPM,
58+
teamId,
59+
createTime: currentMinute
60+
},
61+
update: {
62+
$set: {
63+
event: TrackEnum.teamChatQPM,
64+
teamId,
65+
createTime: currentMinute,
66+
data: {
67+
requestCount
68+
}
69+
}
70+
},
71+
upsert: true
72+
}
73+
};
74+
}
75+
return null;
76+
})
77+
.filter((op): op is NonNullable<typeof op> => op !== null);
78+
79+
if (bulkOps.length > 0) {
80+
await TrackModel.bulkWrite(bulkOps);
81+
}
82+
} catch (error) {
83+
addLog.error('Error recording team QPM', error);
84+
}
85+
};

packages/service/common/system/timerLock/constants.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ export enum TimerIdEnum {
99

1010
clearExpiredRawTextBuffer = 'clearExpiredRawTextBuffer',
1111
clearExpiredDatasetImage = 'clearExpiredDatasetImage',
12-
clearExpiredMinioFiles = 'clearExpiredMinioFiles'
12+
clearExpiredMinioFiles = 'clearExpiredMinioFiles',
13+
recordTeamQPM = 'recordTeamQPM'
1314
}
1415

1516
export enum LockNotificationEnum {

0 commit comments

Comments
 (0)