feat: Добавить кэширование ответов GET с использованием ETag для повышения производительности и улучшения обработки запросов; обновить обработку ошибок в API для более информативных ответов
Publish Fast Tabler Docker image / build-and-push-fast (push) Successful in 1m38s
Publish Fast Tabler Docker image / build-and-push-fast (push) Successful in 1m38s
This commit is contained in:
+18
-15
@@ -518,7 +518,8 @@ app.post('/api/domains', async (req, res) => {
|
||||
if (etag) {
|
||||
const current = await headS3ObjectEtag(FILE_KEY).catch(() => undefined);
|
||||
if (current && current.replace(/\"/g, '"') !== String(etag)) {
|
||||
return res.status(412).json({ message: 'Precondition Failed: ETag mismatch' });
|
||||
const meta = await headMeta(FILE_KEY);
|
||||
return sendError(res, 412, 'Precondition Failed: ETag mismatch', 'E_ETAG_MISMATCH', { currentEtag: current, meta });
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
@@ -555,11 +556,11 @@ app.get('/api/asns', async (req, res) => {
|
||||
|
||||
try {
|
||||
if (countOnly === 'true') {
|
||||
// только количество
|
||||
const { total } = await streamPaginatedText({
|
||||
key: 'bgp_data/asns.txt', q, offset: 0, limit: 0,
|
||||
mapLine: (line) => ({})
|
||||
});
|
||||
const cacheKey = `asns:count:${q}`;
|
||||
const cached = getCountOnlyCache(cacheKey);
|
||||
if (cached != null) return res.json(format === 'std' ? { items: [], total: cached, meta: {} } : { total: cached });
|
||||
const { total } = await streamPaginatedText({ key: 'bgp_data/asns.txt', q, offset: 0, limit: 0, mapLine: () => ({}) });
|
||||
setCountOnlyCache(cacheKey, total);
|
||||
return res.json(format === 'std' ? { items: [], total, meta: {} } : { total });
|
||||
} else if (limit !== undefined) {
|
||||
const { items, total } = await streamPaginatedText({
|
||||
@@ -652,10 +653,11 @@ app.get('/api/domains-new', async (req, res) => {
|
||||
|
||||
try {
|
||||
if (countOnly === 'true') {
|
||||
const { total } = await streamPaginatedText({
|
||||
key: 'bgp_data/domains_community.txt', q, offset: 0, limit: 0,
|
||||
mapLine: (line) => ({})
|
||||
});
|
||||
const cacheKey = `domains-new:count:${q}`;
|
||||
const cached = getCountOnlyCache(cacheKey);
|
||||
if (cached != null) return res.json(format === 'std' ? { items: [], total: cached, meta: {} } : { total: cached });
|
||||
const { total } = await streamPaginatedText({ key: 'bgp_data/domains_community.txt', q, offset: 0, limit: 0, mapLine: () => ({}) });
|
||||
setCountOnlyCache(cacheKey, total);
|
||||
return res.json(format === 'std' ? { items: [], total, meta: {} } : { total });
|
||||
} else if (limit !== undefined) {
|
||||
const { items, total } = await streamPaginatedText({
|
||||
@@ -748,10 +750,11 @@ app.get('/api/ip-ranges', async (req, res) => {
|
||||
|
||||
try {
|
||||
if (countOnly === 'true') {
|
||||
const { total } = await streamPaginatedText({
|
||||
key: 'bgp_data/ips.txt', q, offset: 0, limit: 0,
|
||||
mapLine: (line) => ({})
|
||||
});
|
||||
const cacheKey = `ip-ranges:count:${q}`;
|
||||
const cached = getCountOnlyCache(cacheKey);
|
||||
if (cached != null) return res.json(format === 'std' ? { items: [], total: cached, meta: {} } : { total: cached });
|
||||
const { total } = await streamPaginatedText({ key: 'bgp_data/ips.txt', q, offset: 0, limit: 0, mapLine: () => ({}) });
|
||||
setCountOnlyCache(cacheKey, total);
|
||||
return res.json(format === 'std' ? { items: [], total, meta: {} } : { total });
|
||||
} else if (limit !== undefined) {
|
||||
const { items, total } = await streamPaginatedText({
|
||||
@@ -1219,7 +1222,7 @@ app.post('/api/locks/:resource', (req, res) => {
|
||||
const now = Date.now();
|
||||
const existing = locks.get(resource);
|
||||
if (existing && existing.expiresAt > now && existing.owner !== owner) {
|
||||
return res.status(423).json({ message: 'Resource is locked by another user', owner: existing.owner, expiresAt: existing.expiresAt });
|
||||
return sendError(res, 423, 'Resource is locked by another user', 'E_RESOURCE_LOCKED', { owner: existing.owner, expiresAt: existing.expiresAt });
|
||||
}
|
||||
const expiresAt = now + Math.max(30, Math.min(600, Number(ttlSeconds) || 120)) * 1000;
|
||||
locks.set(resource, { owner, expiresAt });
|
||||
|
||||
Reference in New Issue
Block a user