@itd-api/cache 0.0.1 → 0.1.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 +48 -28
- package/dist/index.cjs +792 -653
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +171 -251
- package/dist/index.d.ts +171 -251
- package/dist/index.js +787 -648
- 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.5.0 <1.0.0`: cache использует namespace
|
|
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,20 @@ const first = await itd.posts.get(postId); // запрос к API
|
|
|
27
33
|
const second = await itd.posts.get(postId); // ответ из кэша
|
|
28
34
|
```
|
|
29
35
|
|
|
30
|
-
Кэшируются только перечисленные
|
|
36
|
+
Кэшируются только перечисленные операции. Query, path и body входят в ключ, поэтому
|
|
31
37
|
разные страницы ленты, профили и наборы идентификаторов хранятся отдельно. Одинаковые
|
|
32
38
|
запросы, запущенные одновременно, выполняют один сетевой вызов.
|
|
33
39
|
|
|
40
|
+
Имена в `operations` — стабильные `operationId`, а не HTTP-пути. Поэтому перенос endpoint не ломает
|
|
41
|
+
правила кэша. Низкоуровневый `itd.request()` без явного ID считается операцией `raw`: одно лишь
|
|
42
|
+
совпадение его URL со встроенным resource не включает кэш автоматически.
|
|
43
|
+
|
|
34
44
|
## Настройки
|
|
35
45
|
|
|
36
46
|
```ts
|
|
37
47
|
const cached = cache({
|
|
38
48
|
ttl: 60_000,
|
|
39
|
-
|
|
49
|
+
operations: ['users.get', 'posts.get'],
|
|
40
50
|
maxEntries: 500,
|
|
41
51
|
deduplicate: true,
|
|
42
52
|
});
|
|
@@ -45,7 +55,7 @@ const cached = cache({
|
|
|
45
55
|
| Поле | Значение |
|
|
46
56
|
|---|---|
|
|
47
57
|
| `ttl` | срок хранения успешного ответа в миллисекундах |
|
|
48
|
-
| `
|
|
58
|
+
| `operations` | операции, ответы которых нужно кэшировать |
|
|
49
59
|
| `maxEntries` | предел LRU-кэша; по умолчанию `500` |
|
|
50
60
|
| `deduplicate` | объединение одновременных запросов; по умолчанию `true` |
|
|
51
61
|
|
|
@@ -55,8 +65,8 @@ const cached = cache({
|
|
|
55
65
|
## Управление отдельным запросом
|
|
56
66
|
|
|
57
67
|
```ts
|
|
58
|
-
await itd.posts.get(postId, { cache: 'reload' });
|
|
59
|
-
await itd.posts.get(postId, { cache: 'no-store' });
|
|
68
|
+
await itd.posts.get(postId, { extensions: { cache: 'reload' } });
|
|
69
|
+
await itd.posts.get(postId, { extensions: { cache: 'no-store' } });
|
|
60
70
|
```
|
|
61
71
|
|
|
62
72
|
- `reload` пропускает готовый ответ, запрашивает новый и заменяет запись;
|
|
@@ -68,11 +78,12 @@ await itd.posts.get(postId, { cache: 'no-store' });
|
|
|
68
78
|
|
|
69
79
|
## Инвалидация
|
|
70
80
|
|
|
71
|
-
После успешной мутации плагин удаляет связанные читающие
|
|
81
|
+
После успешной мутации плагин удаляет связанные читающие операции. Например, реакция на
|
|
72
82
|
пост сбрасывает кэш постов и статистики, но не затрагивает профили, файлы и настройки
|
|
73
|
-
платформы.
|
|
74
|
-
поста одним аккаунтом должно быть видно остальным. Персональные
|
|
75
|
-
|
|
83
|
+
платформы. Операции с общими данными инвалидируются во всех аккаунтах экземпляра: изменение
|
|
84
|
+
поста одним аккаунтом должно быть видно остальным. Персональные настройки и уведомления
|
|
85
|
+
инвалидируются у всех копий клиента с тем же пользователем. Изменение сессий сбрасывает все
|
|
86
|
+
варианты `auth.sessions` этого аккаунта, включая варианты других сессий.
|
|
76
87
|
|
|
77
88
|
Известные запросы без зависимостей, включая telemetry и создание жалобы, кэш не меняют.
|
|
78
89
|
|
|
@@ -85,7 +96,7 @@ cached.invalidate('posts.get', 'posts.list');
|
|
|
85
96
|
cached.clear();
|
|
86
97
|
```
|
|
87
98
|
|
|
88
|
-
`invalidate()` удаляет все варианты выбранных
|
|
99
|
+
`invalidate()` удаляет все варианты выбранных операций во всех подключённых клиентах.
|
|
89
100
|
`clear()` очищает всё хранилище. Оба метода защищены от гонки: запрос, начатый до очистки,
|
|
90
101
|
не запишет устаревший результат после неё.
|
|
91
102
|
|
|
@@ -102,9 +113,13 @@ detachCache();
|
|
|
102
113
|
stream.disconnect();
|
|
103
114
|
```
|
|
104
115
|
|
|
105
|
-
Привязка сразу очищает `notifications.list` и `notifications.count
|
|
106
|
-
|
|
107
|
-
|
|
116
|
+
Привязка сразу очищает `notifications.list` и `notifications.count` аккаунта, который
|
|
117
|
+
создал поток. Новое уведомление сбрасывает обе операции во всех копиях клиента с тем же
|
|
118
|
+
пользователем, событие `unreadCount` — их счётчик. Кэш других аккаунтов и остальные операции
|
|
119
|
+
поток не изменяет.
|
|
120
|
+
|
|
121
|
+
У стороннего realtime-объекта без доступных идентификатора пользователя и базового URL
|
|
122
|
+
используется безопасный fallback: операции уведомлений инвалидируются во всех аккаунтах.
|
|
108
123
|
|
|
109
124
|
## Несколько клиентов
|
|
110
125
|
|
|
@@ -125,21 +140,26 @@ clientB.use(shared);
|
|
|
125
140
|
// либо accounts.use(shared)
|
|
126
141
|
```
|
|
127
142
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
143
|
+
Копии клиента с одинаковыми базовым URL и пользователем используют общий раздел: готовые
|
|
144
|
+
ответы и одновременные запросы между ними объединяются. Это безопасно для персонализированных
|
|
145
|
+
полей `isLiked`, `isFollowing` и `isReposted`, потому что их значения принадлежат аккаунту,
|
|
146
|
+
а не конкретному access token.
|
|
147
|
+
|
|
148
|
+
Разные пользователи изолированы. Только `auth.sessions` дополнительно разделяется по сессии,
|
|
149
|
+
поскольку ответ отмечает текущую серверную сессию. Если идентификаторов пользователя или
|
|
150
|
+
сессии в токене нет, плагин использует безопасный уникальный раздел установки и ничего между
|
|
151
|
+
копиями не объединяет.
|
|
132
152
|
|
|
133
|
-
`maxEntries` ограничивает весь экземпляр `shared`, а `clear()
|
|
134
|
-
|
|
135
|
-
|
|
153
|
+
`maxEntries` ограничивает весь экземпляр `shared`, а `clear()` и `invalidate()` управляют
|
|
154
|
+
всеми его разделами. `attachRealtime()` затрагивает аккаунт создавшего поток клиента.
|
|
155
|
+
Смена сессии сохраняет общий кэш, смена пользователя автоматически выбирает другой раздел.
|
|
136
156
|
|
|
137
157
|
## Ключ
|
|
138
158
|
|
|
139
159
|
В ключ входят:
|
|
140
160
|
|
|
141
|
-
- имя
|
|
142
|
-
-
|
|
161
|
+
- имя операции, HTTP-метод и path;
|
|
162
|
+
- базовый URL и идентификатор пользователя; для `auth.sessions` также идентификатор сессии;
|
|
143
163
|
- `service` или разовый `baseUrl`;
|
|
144
164
|
- query и JSON-body;
|
|
145
165
|
- режим `raw`, `skipAuth` и опции других плагинов, влияющие на ответ.
|
|
@@ -150,9 +170,9 @@ clientB.use(shared);
|
|
|
150
170
|
Ответ хранится как независимая копия: изменение полученного объекта не меняет следующие
|
|
151
171
|
результаты.
|
|
152
172
|
|
|
153
|
-
## Доступные
|
|
173
|
+
## Доступные операции
|
|
154
174
|
|
|
155
|
-
| Раздел |
|
|
175
|
+
| Раздел | Операции |
|
|
156
176
|
|---|---|
|
|
157
177
|
| Auth | `auth.sessions` |
|
|
158
178
|
| 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` |
|
|
@@ -166,14 +186,14 @@ clientB.use(shared);
|
|
|
166
186
|
| Verification | `verification.status` |
|
|
167
187
|
| Platform | `platform.changelog`, `platform.announcements`, `platform.portal`, `platform.status` |
|
|
168
188
|
|
|
169
|
-
Страницы, загружаемые итераторами, используют
|
|
189
|
+
Страницы, загружаемые итераторами, используют операцию соответствующего списочного метода:
|
|
170
190
|
`posts.iterate()` — `posts.list`, `users.iterateFollowers()` — `users.followers` и так
|
|
171
191
|
далее.
|
|
172
192
|
|
|
173
193
|
Каталог доступен программно:
|
|
174
194
|
|
|
175
195
|
```ts
|
|
176
|
-
import {
|
|
196
|
+
import { CACHE_OPERATIONS } from '@itd-api/cache';
|
|
177
197
|
|
|
178
|
-
console.log(
|
|
198
|
+
console.log(CACHE_OPERATIONS.map(({ id }) => id));
|
|
179
199
|
```
|