Каждая точка ingest (~1/сек) broadcast'илась SSE всем клиентам орг., клиент на каждое событие делал invalidateQueries без throttle → 2+ GET/сек → исчерпание per-user бакета apiLimiter (1500/15мин) → все API устройства 429 (формы не грузились). Модель теперь как у нормальных трекеров: точки пишутся в БД, карта читает по интервалу. +4 unit-теста троттла (server/gps/sse-throttle.ts)
31 lines
1.3 KiB
TypeScript
31 lines
1.3 KiB
TypeScript
import { describe, it, expect } from 'vitest';
|
|
import { shouldPublishGpsAssetMoved } from '../server/gps/sse-throttle';
|
|
|
|
describe('shouldPublishGpsAssetMoved', () => {
|
|
it('первое событие объекта публикуется сразу', () => {
|
|
expect(shouldPublishGpsAssetMoved(1, 10_000)).toBe(true);
|
|
});
|
|
|
|
it('события чаще 3 секунд подряд пропускаются', () => {
|
|
const assetId = 2;
|
|
expect(shouldPublishGpsAssetMoved(assetId, 100_000)).toBe(true);
|
|
expect(shouldPublishGpsAssetMoved(assetId, 101_000)).toBe(false);
|
|
expect(shouldPublishGpsAssetMoved(assetId, 102_999)).toBe(false);
|
|
});
|
|
|
|
it('после окна в 3 секунды событие снова публикуется', () => {
|
|
const assetId = 3;
|
|
expect(shouldPublishGpsAssetMoved(assetId, 200_000)).toBe(true);
|
|
expect(shouldPublishGpsAssetMoved(assetId, 203_000)).toBe(true);
|
|
expect(shouldPublishGpsAssetMoved(assetId, 204_000)).toBe(false);
|
|
});
|
|
|
|
it('throttle независим между объектами', () => {
|
|
const now = 300_000;
|
|
expect(shouldPublishGpsAssetMoved(4, now)).toBe(true);
|
|
expect(shouldPublishGpsAssetMoved(5, now)).toBe(true);
|
|
expect(shouldPublishGpsAssetMoved(4, now + 1_000)).toBe(false);
|
|
expect(shouldPublishGpsAssetMoved(5, now + 1_000)).toBe(false);
|
|
});
|
|
});
|