Skip to content

Commit c0e696d

Browse files
committed
deduped tech requests
1 parent c0bcaa7 commit c0e696d

File tree

1 file changed

+69
-36
lines changed

1 file changed

+69
-36
lines changed

src/controllers/cwvtechController.js

Lines changed: 69 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,65 +1,98 @@
11
import { firestoreOld } from '../utils/db.js';
22
const firestore = firestoreOld;
33

4-
import { createSuccessResponse } from '../utils/helpers.js';
54
import {
6-
REQUIRED_PARAMS,
7-
validateRequiredParams,
8-
sendValidationError,
9-
applyDateFilters,
10-
applyStandardFilters,
11-
preprocessParams,
12-
handleControllerError
5+
getLatestDate
136
} from '../utils/controllerHelpers.js';
147

158
const TABLE = 'core_web_vitals';
169

1710
/**
18-
* List Core Web Vitals data with filtering
11+
* List Core Web Vitals data with filtering - Optimized version
1912
*/
2013
const listCWVTechData = async (req, res) => {
2114
try {
2215
const params = req.query;
2316

24-
// Validate required parameters
25-
const requiredParams = [
26-
REQUIRED_PARAMS.GEO,
27-
REQUIRED_PARAMS.RANK,
28-
REQUIRED_PARAMS.TECHNOLOGY
29-
];
30-
31-
const validationErrors = validateRequiredParams(params, requiredParams);
32-
if (validationErrors) {
33-
sendValidationError(res, validationErrors);
17+
// Validate required parameters inline for speed
18+
if (!params.geo || !params.rank || !params.technology) {
19+
res.statusCode = 400;
20+
res.end(JSON.stringify({
21+
success: false,
22+
errors: [
23+
...(!params.geo ? [{ geo: 'missing geo parameter' }] : []),
24+
...(!params.rank ? [{ rank: 'missing rank parameter' }] : []),
25+
...(!params.technology ? [{ technology: 'missing technology parameter' }] : [])
26+
]
27+
}));
3428
return;
3529
}
3630

37-
// Preprocess parameters and get technology array
38-
const { params: processedParams, techArray } = await preprocessParams(firestore, params, TABLE);
39-
const data = [];
31+
// Fast preprocessing - handle 'latest' date and technology array
32+
const techArray = params.technology ? decodeURIComponent(params.technology).split(',') : [];
33+
34+
// Handle 'latest' date with caching
35+
let startDate = params.start;
36+
if (startDate === 'latest') {
37+
startDate = await getLatestDate(firestore, TABLE);
38+
}
39+
40+
// Build optimized query
41+
let query = firestore.collection(TABLE);
4042

41-
// Query for each technology
42-
for (const technology of techArray) {
43-
let query = firestore.collection(TABLE);
43+
// Apply required filters
44+
query = query.where('geo', '==', params.geo);
45+
query = query.where('rank', '==', params.rank);
4446

45-
// Apply standard filters including version filter
46-
query = applyStandardFilters(query, processedParams, technology, techArray);
47+
// Apply technology filter efficiently
48+
if (techArray.length <= 30) {
49+
// Use 'in' operator for batch processing (Firestore limit: 30 values)
50+
query = query.where('technology', 'in', techArray);
51+
} else {
52+
// Parallel queries for >10 technologies (rare case)
53+
const queryPromises = techArray.map(async (technology) => {
54+
let individualQuery = firestore.collection(TABLE)
55+
.where('geo', '==', params.geo)
56+
.where('rank', '==', params.rank)
57+
.where('technology', '==', technology);
4758

48-
// Apply date filters
49-
query = applyDateFilters(query, processedParams);
59+
if (startDate) individualQuery = individualQuery.where('date', '>=', startDate);
60+
if (params.end) individualQuery = individualQuery.where('date', '<=', params.end);
5061

51-
// Execute query
52-
const snapshot = await query.get();
53-
snapshot.forEach(doc => {
54-
data.push(doc.data());
62+
const snapshot = await individualQuery.get();
63+
const results = [];
64+
snapshot.forEach(doc => results.push(doc.data()));
65+
return results;
5566
});
67+
68+
const results = await Promise.all(queryPromises);
69+
const data = results.flat();
70+
71+
res.statusCode = 200;
72+
res.end(JSON.stringify(data));
73+
return;
5674
}
5775

58-
// Send response
76+
// Apply date filters
77+
if (startDate) query = query.where('date', '>=', startDate);
78+
if (params.end) query = query.where('date', '<=', params.end);
79+
80+
// Execute single optimized query
81+
const snapshot = await query.get();
82+
const data = [];
83+
snapshot.forEach(doc => {
84+
data.push(doc.data());
85+
});
86+
87+
// Direct response without wrapper functions
5988
res.statusCode = 200;
60-
res.end(JSON.stringify(createSuccessResponse(data)));
89+
res.end(JSON.stringify(data));
6190
} catch (error) {
62-
handleControllerError(res, error, 'fetching Core Web Vitals data');
91+
console.error('Error fetching Core Web Vitals data:', error);
92+
res.statusCode = 500;
93+
res.end(JSON.stringify({
94+
errors: [{ error: 'Failed to fetch Core Web Vitals data' }]
95+
}));
6396
}
6497
};
6598

0 commit comments

Comments
 (0)