@itd-api/cache 0.0.2 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +44 -26
- package/dist/index.cjs +817 -696
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +206 -264
- package/dist/index.d.ts +206 -264
- package/dist/index.js +810 -691
- package/dist/index.js.map +1 -1
- package/package.json +11 -10
package/README.md
CHANGED
|
@@ -3,12 +3,18 @@
|
|
|
3
3
|
TTL/LRU-кэш и дедупликация одновременных запросов для
|
|
4
4
|
[`itd-api`](https://github.com/KiowDev/itd-api).
|
|
5
5
|
|
|
6
|
+
[Руководство](https://kiowdev.github.io/itd-api/packages/cache) ·
|
|
7
|
+
[API из TSDoc](https://kiowdev.github.io/itd-api/api/generated/cache/)
|
|
8
|
+
|
|
6
9
|
## Установка
|
|
7
10
|
|
|
8
11
|
```bash
|
|
9
12
|
npm install itd-api @itd-api/cache
|
|
10
13
|
```
|
|
11
14
|
|
|
15
|
+
Поддерживается `itd-api >=0.8.0 <1.0.0`: пакет использует отдельное поле
|
|
16
|
+
`RequestOptions.extensions` и стабильный `operationId` запроса.
|
|
17
|
+
|
|
12
18
|
## Быстрый старт
|
|
13
19
|
|
|
14
20
|
```ts
|
|
@@ -18,7 +24,7 @@ import { ItdClient } from 'itd-api';
|
|
|
18
24
|
const itd = new ItdClient({ auth: process.env.ITD_TOKEN });
|
|
19
25
|
const cached = cache({
|
|
20
26
|
ttl: 60_000,
|
|
21
|
-
|
|
27
|
+
operations: ['users.get', 'posts.get', 'posts.list'],
|
|
22
28
|
});
|
|
23
29
|
|
|
24
30
|
itd.use(cached);
|
|
@@ -27,16 +33,24 @@ const first = await itd.posts.get(postId); // запрос к API
|
|
|
27
33
|
const second = await itd.posts.get(postId); // ответ из кэша
|
|
28
34
|
```
|
|
29
35
|
|
|
30
|
-
|
|
36
|
+
Операции подключаемых модулей тоже можно кэшировать. Например, модуль Pixel Battle задаёт
|
|
37
|
+
`CachePolicyKind.Query` в `annotations.cache`, а пользователь добавляет полный `operationId`
|
|
38
|
+
в `operations`.
|
|
39
|
+
|
|
40
|
+
Кэшируются только перечисленные операции. Query, path и body входят в ключ, поэтому
|
|
31
41
|
разные страницы ленты, профили и наборы идентификаторов хранятся отдельно. Одинаковые
|
|
32
42
|
запросы, запущенные одновременно, выполняют один сетевой вызов.
|
|
33
43
|
|
|
44
|
+
Имена в `operations` — постоянные `operationId`, а не HTTP-пути. Изменение маршрута не ломает
|
|
45
|
+
правила кэша. Низкоуровневый `itd.request()` без явного идентификатора операции считается
|
|
46
|
+
операцией `raw`; совпадение URL со встроенным ресурсом не включает кэш автоматически.
|
|
47
|
+
|
|
34
48
|
## Настройки
|
|
35
49
|
|
|
36
50
|
```ts
|
|
37
51
|
const cached = cache({
|
|
38
52
|
ttl: 60_000,
|
|
39
|
-
|
|
53
|
+
operations: ['users.get', 'posts.get'],
|
|
40
54
|
maxEntries: 500,
|
|
41
55
|
deduplicate: true,
|
|
42
56
|
});
|
|
@@ -45,7 +59,7 @@ const cached = cache({
|
|
|
45
59
|
| Поле | Значение |
|
|
46
60
|
|---|---|
|
|
47
61
|
| `ttl` | срок хранения успешного ответа в миллисекундах |
|
|
48
|
-
| `
|
|
62
|
+
| `operations` | операции, ответы которых нужно кэшировать |
|
|
49
63
|
| `maxEntries` | предел LRU-кэша; по умолчанию `500` |
|
|
50
64
|
| `deduplicate` | объединение одновременных запросов; по умолчанию `true` |
|
|
51
65
|
|
|
@@ -55,8 +69,8 @@ const cached = cache({
|
|
|
55
69
|
## Управление отдельным запросом
|
|
56
70
|
|
|
57
71
|
```ts
|
|
58
|
-
await itd.posts.get(postId, { cache: 'reload' });
|
|
59
|
-
await itd.posts.get(postId, { cache: 'no-store' });
|
|
72
|
+
await itd.posts.get(postId, { extensions: { cache: 'reload' } });
|
|
73
|
+
await itd.posts.get(postId, { extensions: { cache: 'no-store' } });
|
|
60
74
|
```
|
|
61
75
|
|
|
62
76
|
- `reload` пропускает готовый ответ, запрашивает новый и заменяет запись;
|
|
@@ -68,9 +82,9 @@ await itd.posts.get(postId, { cache: 'no-store' });
|
|
|
68
82
|
|
|
69
83
|
## Инвалидация
|
|
70
84
|
|
|
71
|
-
После успешной мутации плагин удаляет связанные читающие
|
|
85
|
+
После успешной мутации плагин удаляет связанные читающие операции. Например, реакция на
|
|
72
86
|
пост сбрасывает кэш постов и статистики, но не затрагивает профили, файлы и настройки
|
|
73
|
-
платформы.
|
|
87
|
+
платформы. Операции с общими данными инвалидируются во всех аккаунтах экземпляра: изменение
|
|
74
88
|
поста одним аккаунтом должно быть видно остальным. Персональные настройки и уведомления
|
|
75
89
|
инвалидируются у всех копий клиента с тем же пользователем. Изменение сессий сбрасывает все
|
|
76
90
|
варианты `auth.sessions` этого аккаунта, включая варианты других сессий.
|
|
@@ -86,15 +100,15 @@ cached.invalidate('posts.get', 'posts.list');
|
|
|
86
100
|
cached.clear();
|
|
87
101
|
```
|
|
88
102
|
|
|
89
|
-
`invalidate()` удаляет все варианты выбранных
|
|
103
|
+
`invalidate()` удаляет все варианты выбранных операций во всех подключённых клиентах.
|
|
90
104
|
`clear()` очищает всё хранилище. Оба метода защищены от гонки: запрос, начатый до очистки,
|
|
91
105
|
не запишет устаревший результат после неё.
|
|
92
106
|
|
|
93
|
-
##
|
|
107
|
+
## События
|
|
94
108
|
|
|
95
109
|
```ts
|
|
96
|
-
const stream = itd.
|
|
97
|
-
const detachCache = cached.
|
|
110
|
+
const stream = itd.notifications.events;
|
|
111
|
+
const detachCache = cached.attachNotificationEvents(stream);
|
|
98
112
|
|
|
99
113
|
await stream.connect();
|
|
100
114
|
|
|
@@ -104,12 +118,16 @@ stream.disconnect();
|
|
|
104
118
|
```
|
|
105
119
|
|
|
106
120
|
Привязка сразу очищает `notifications.list` и `notifications.count` аккаунта, который
|
|
107
|
-
создал поток. Новое уведомление сбрасывает
|
|
108
|
-
пользователем, событие `unreadCount` — их счётчик. Кэш других аккаунтов и остальные
|
|
121
|
+
создал поток. Новое уведомление сбрасывает обе операции во всех копиях клиента с тем же
|
|
122
|
+
пользователем, событие `unreadCount` — их счётчик. Кэш других аккаунтов и остальные операции
|
|
109
123
|
поток не изменяет.
|
|
110
124
|
|
|
111
|
-
|
|
112
|
-
|
|
125
|
+
Инвалидация подключается как промежуточный обработчик. Вызывайте
|
|
126
|
+
`attachNotificationEvents()` до прикладных обработчиков, которые могут не вызвать `next()`:
|
|
127
|
+
тогда отфильтрованное для интерфейса обновление всё равно не оставит устаревший кэш.
|
|
128
|
+
|
|
129
|
+
У стороннего событийного объекта без доступных идентификатора пользователя и базового URL
|
|
130
|
+
операции уведомлений инвалидируются во всех аккаунтах.
|
|
113
131
|
|
|
114
132
|
## Несколько клиентов
|
|
115
133
|
|
|
@@ -141,28 +159,28 @@ clientB.use(shared);
|
|
|
141
159
|
копиями не объединяет.
|
|
142
160
|
|
|
143
161
|
`maxEntries` ограничивает весь экземпляр `shared`, а `clear()` и `invalidate()` управляют
|
|
144
|
-
всеми его разделами. `
|
|
162
|
+
всеми его разделами. `attachNotificationEvents()` затрагивает аккаунт создавшего поток клиента.
|
|
145
163
|
Смена сессии сохраняет общий кэш, смена пользователя автоматически выбирает другой раздел.
|
|
146
164
|
|
|
147
165
|
## Ключ
|
|
148
166
|
|
|
149
167
|
В ключ входят:
|
|
150
168
|
|
|
151
|
-
- имя
|
|
169
|
+
- имя операции, HTTP-метод и path;
|
|
152
170
|
- базовый URL и идентификатор пользователя; для `auth.sessions` также идентификатор сессии;
|
|
153
171
|
- `service` или разовый `baseUrl`;
|
|
154
|
-
-
|
|
172
|
+
- параметры строки запроса и JSON-тело;
|
|
155
173
|
- режим `raw`, `skipAuth` и опции других плагинов, влияющие на ответ.
|
|
156
174
|
|
|
157
175
|
Токен и заголовки в ключ не входят. Также не учитываются `signal`, `timeout` и настройки
|
|
158
|
-
повторов.
|
|
176
|
+
повторов. Запрос с несериализуемым JSON-телом выполняется без кэширования.
|
|
159
177
|
|
|
160
178
|
Ответ хранится как независимая копия: изменение полученного объекта не меняет следующие
|
|
161
179
|
результаты.
|
|
162
180
|
|
|
163
|
-
## Доступные
|
|
181
|
+
## Доступные операции
|
|
164
182
|
|
|
165
|
-
| Раздел |
|
|
183
|
+
| Раздел | Операции |
|
|
166
184
|
|---|---|
|
|
167
185
|
| Auth | `auth.sessions` |
|
|
168
186
|
| Users | `users.me`, `users.get`, `users.checkUsername`, `users.search`, `users.whoToFollow`, `users.topClans`, `users.followers`, `users.following`, `users.blocked`, `users.getPrivacy`, `users.pins`, `users.followStatus` |
|
|
@@ -174,16 +192,16 @@ clientB.use(shared);
|
|
|
174
192
|
| Files | `files.get` |
|
|
175
193
|
| Subscription | `subscription.status`, `subscription.methods` |
|
|
176
194
|
| Verification | `verification.status` |
|
|
177
|
-
| Platform | `platform.changelog`, `platform.announcements`, `platform.portal`, `
|
|
195
|
+
| Platform | `platform.changelog`, `platform.announcements`, `platform.portal`, `status.get` |
|
|
178
196
|
|
|
179
|
-
Страницы, загружаемые итераторами, используют
|
|
197
|
+
Страницы, загружаемые итераторами, используют операцию соответствующего списочного метода:
|
|
180
198
|
`posts.iterate()` — `posts.list`, `users.iterateFollowers()` — `users.followers` и так
|
|
181
199
|
далее.
|
|
182
200
|
|
|
183
201
|
Каталог доступен программно:
|
|
184
202
|
|
|
185
203
|
```ts
|
|
186
|
-
import {
|
|
204
|
+
import { CACHE_OPERATIONS } from '@itd-api/cache';
|
|
187
205
|
|
|
188
|
-
console.log(
|
|
206
|
+
console.log(CACHE_OPERATIONS.map(({ id }) => id));
|
|
189
207
|
```
|