@atproto/bsky 0.0.243 → 0.0.244
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/CHANGELOG.md +19 -0
- package/dist/api/app/bsky/actor/searchActorsTypeahead.js +5 -3
- package/dist/api/app/bsky/actor/searchActorsTypeahead.js.map +1 -1
- package/dist/api/app/bsky/notification/putPreferencesV2.js +4 -1
- package/dist/api/app/bsky/notification/putPreferencesV2.js.map +1 -1
- package/dist/api/app/bsky/notification/util.d.ts +1 -0
- package/dist/api/app/bsky/notification/util.d.ts.map +1 -1
- package/dist/api/app/bsky/notification/util.js +7 -7
- package/dist/api/app/bsky/notification/util.js.map +1 -1
- package/dist/api/blob-dispatcher.d.ts.map +1 -1
- package/dist/api/blob-dispatcher.js +9 -8
- package/dist/api/blob-dispatcher.js.map +1 -1
- package/dist/api/blob-resolver.d.ts +1 -1
- package/dist/api/blob-resolver.d.ts.map +1 -1
- package/dist/api/blob-resolver.js +0 -1
- package/dist/api/blob-resolver.js.map +1 -1
- package/dist/data-plane/bsync/index.d.ts +2 -0
- package/dist/data-plane/bsync/index.d.ts.map +1 -1
- package/dist/data-plane/bsync/index.js +7 -10
- package/dist/data-plane/bsync/index.js.map +1 -1
- package/dist/data-plane/server/background.d.ts +12 -8
- package/dist/data-plane/server/background.d.ts.map +1 -1
- package/dist/data-plane/server/background.js +32 -14
- package/dist/data-plane/server/background.js.map +1 -1
- package/dist/data-plane/server/index.d.ts +2 -0
- package/dist/data-plane/server/index.d.ts.map +1 -1
- package/dist/data-plane/server/index.js +7 -10
- package/dist/data-plane/server/index.js.map +1 -1
- package/dist/data-plane/server/indexing/index.d.ts +2 -2
- package/dist/data-plane/server/indexing/index.d.ts.map +1 -1
- package/dist/data-plane/server/indexing/index.js.map +1 -1
- package/dist/data-plane/server/indexing/plugins/block.d.ts +1 -1
- package/dist/data-plane/server/indexing/plugins/block.d.ts.map +1 -1
- package/dist/data-plane/server/indexing/plugins/block.js.map +1 -1
- package/dist/data-plane/server/indexing/plugins/chat-declaration.d.ts +1 -1
- package/dist/data-plane/server/indexing/plugins/chat-declaration.d.ts.map +1 -1
- package/dist/data-plane/server/indexing/plugins/chat-declaration.js.map +1 -1
- package/dist/data-plane/server/indexing/plugins/feed-generator.d.ts +1 -1
- package/dist/data-plane/server/indexing/plugins/feed-generator.d.ts.map +1 -1
- package/dist/data-plane/server/indexing/plugins/feed-generator.js.map +1 -1
- package/dist/data-plane/server/indexing/plugins/follow.d.ts +1 -1
- package/dist/data-plane/server/indexing/plugins/follow.d.ts.map +1 -1
- package/dist/data-plane/server/indexing/plugins/follow.js.map +1 -1
- package/dist/data-plane/server/indexing/plugins/germ-declaration.d.ts +1 -1
- package/dist/data-plane/server/indexing/plugins/germ-declaration.d.ts.map +1 -1
- package/dist/data-plane/server/indexing/plugins/germ-declaration.js.map +1 -1
- package/dist/data-plane/server/indexing/plugins/labeler.d.ts +1 -1
- package/dist/data-plane/server/indexing/plugins/labeler.d.ts.map +1 -1
- package/dist/data-plane/server/indexing/plugins/labeler.js.map +1 -1
- package/dist/data-plane/server/indexing/plugins/like.d.ts +1 -1
- package/dist/data-plane/server/indexing/plugins/like.d.ts.map +1 -1
- package/dist/data-plane/server/indexing/plugins/like.js.map +1 -1
- package/dist/data-plane/server/indexing/plugins/list-block.d.ts +1 -1
- package/dist/data-plane/server/indexing/plugins/list-block.d.ts.map +1 -1
- package/dist/data-plane/server/indexing/plugins/list-block.js.map +1 -1
- package/dist/data-plane/server/indexing/plugins/list-item.d.ts +1 -1
- package/dist/data-plane/server/indexing/plugins/list-item.d.ts.map +1 -1
- package/dist/data-plane/server/indexing/plugins/list-item.js.map +1 -1
- package/dist/data-plane/server/indexing/plugins/list.d.ts +1 -1
- package/dist/data-plane/server/indexing/plugins/list.d.ts.map +1 -1
- package/dist/data-plane/server/indexing/plugins/list.js.map +1 -1
- package/dist/data-plane/server/indexing/plugins/notif-declaration.d.ts +1 -1
- package/dist/data-plane/server/indexing/plugins/notif-declaration.d.ts.map +1 -1
- package/dist/data-plane/server/indexing/plugins/notif-declaration.js.map +1 -1
- package/dist/data-plane/server/indexing/plugins/post-gate.d.ts +1 -1
- package/dist/data-plane/server/indexing/plugins/post-gate.d.ts.map +1 -1
- package/dist/data-plane/server/indexing/plugins/post-gate.js.map +1 -1
- package/dist/data-plane/server/indexing/plugins/post.d.ts +1 -1
- package/dist/data-plane/server/indexing/plugins/post.d.ts.map +1 -1
- package/dist/data-plane/server/indexing/plugins/post.js.map +1 -1
- package/dist/data-plane/server/indexing/plugins/profile.d.ts +1 -1
- package/dist/data-plane/server/indexing/plugins/profile.d.ts.map +1 -1
- package/dist/data-plane/server/indexing/plugins/profile.js.map +1 -1
- package/dist/data-plane/server/indexing/plugins/repost.d.ts +1 -1
- package/dist/data-plane/server/indexing/plugins/repost.d.ts.map +1 -1
- package/dist/data-plane/server/indexing/plugins/repost.js.map +1 -1
- package/dist/data-plane/server/indexing/plugins/starter-pack.d.ts +1 -1
- package/dist/data-plane/server/indexing/plugins/starter-pack.d.ts.map +1 -1
- package/dist/data-plane/server/indexing/plugins/starter-pack.js.map +1 -1
- package/dist/data-plane/server/indexing/plugins/status.d.ts +1 -1
- package/dist/data-plane/server/indexing/plugins/status.d.ts.map +1 -1
- package/dist/data-plane/server/indexing/plugins/status.js.map +1 -1
- package/dist/data-plane/server/indexing/plugins/thread-gate.d.ts +1 -1
- package/dist/data-plane/server/indexing/plugins/thread-gate.d.ts.map +1 -1
- package/dist/data-plane/server/indexing/plugins/thread-gate.js.map +1 -1
- package/dist/data-plane/server/indexing/plugins/verification.d.ts +1 -1
- package/dist/data-plane/server/indexing/plugins/verification.d.ts.map +1 -1
- package/dist/data-plane/server/indexing/plugins/verification.js.map +1 -1
- package/dist/data-plane/server/indexing/processor.d.ts +1 -1
- package/dist/data-plane/server/indexing/processor.d.ts.map +1 -1
- package/dist/data-plane/server/indexing/processor.js.map +1 -1
- package/dist/data-plane/server/routes/notifs.d.ts.map +1 -1
- package/dist/data-plane/server/routes/notifs.js +1 -8
- package/dist/data-plane/server/routes/notifs.js.map +1 -1
- package/dist/data-plane/server/routes/search.js +2 -2
- package/dist/data-plane/server/routes/search.js.map +1 -1
- package/dist/data-plane/server/subscription.d.ts +13 -12
- package/dist/data-plane/server/subscription.d.ts.map +1 -1
- package/dist/data-plane/server/subscription.js +59 -26
- package/dist/data-plane/server/subscription.js.map +1 -1
- package/dist/feature-gates/index.d.ts +2 -1
- package/dist/feature-gates/index.d.ts.map +1 -1
- package/dist/feature-gates/index.js +9 -6
- package/dist/feature-gates/index.js.map +1 -1
- package/dist/feature-gates/metrics.d.ts +3 -3
- package/dist/feature-gates/metrics.d.ts.map +1 -1
- package/dist/feature-gates/metrics.js +8 -8
- package/dist/feature-gates/metrics.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +16 -7
- package/dist/index.js.map +1 -1
- package/dist/lexicons/app/bsky/notification/defs.defs.d.ts +5 -0
- package/dist/lexicons/app/bsky/notification/defs.defs.d.ts.map +1 -1
- package/dist/lexicons/app/bsky/notification/defs.defs.js +1 -0
- package/dist/lexicons/app/bsky/notification/defs.defs.js.map +1 -1
- package/dist/lexicons/chat/bsky/notification/defs.d.ts +2 -0
- package/dist/lexicons/chat/bsky/notification/defs.d.ts.map +1 -0
- package/dist/lexicons/chat/bsky/notification/defs.defs.d.ts +20 -0
- package/dist/lexicons/chat/bsky/notification/defs.defs.d.ts.map +1 -0
- package/dist/lexicons/chat/bsky/notification/defs.defs.js +19 -0
- package/dist/lexicons/chat/bsky/notification/defs.defs.js.map +1 -0
- package/dist/lexicons/chat/bsky/notification/defs.js +5 -0
- package/dist/lexicons/chat/bsky/notification/defs.js.map +1 -0
- package/dist/lexicons/chat/bsky/notification/getPreferences.d.ts +3 -0
- package/dist/lexicons/chat/bsky/notification/getPreferences.d.ts.map +1 -0
- package/dist/lexicons/chat/bsky/notification/getPreferences.defs.d.ts +18 -0
- package/dist/lexicons/chat/bsky/notification/getPreferences.defs.d.ts.map +1 -0
- package/dist/lexicons/chat/bsky/notification/getPreferences.defs.js +16 -0
- package/dist/lexicons/chat/bsky/notification/getPreferences.defs.js.map +1 -0
- package/dist/lexicons/chat/bsky/notification/getPreferences.js +6 -0
- package/dist/lexicons/chat/bsky/notification/getPreferences.js.map +1 -0
- package/dist/lexicons/chat/bsky/notification/putPreferences.d.ts +3 -0
- package/dist/lexicons/chat/bsky/notification/putPreferences.d.ts.map +1 -0
- package/dist/lexicons/chat/bsky/notification/putPreferences.defs.d.ts +27 -0
- package/dist/lexicons/chat/bsky/notification/putPreferences.defs.d.ts.map +1 -0
- package/dist/lexicons/chat/bsky/notification/putPreferences.defs.js +22 -0
- package/dist/lexicons/chat/bsky/notification/putPreferences.defs.js.map +1 -0
- package/dist/lexicons/chat/bsky/notification/putPreferences.js +6 -0
- package/dist/lexicons/chat/bsky/notification/putPreferences.js.map +1 -0
- package/dist/lexicons/chat/bsky/notification.d.ts +4 -0
- package/dist/lexicons/chat/bsky/notification.d.ts.map +1 -0
- package/dist/lexicons/chat/bsky/notification.js +7 -0
- package/dist/lexicons/chat/bsky/notification.js.map +1 -0
- package/dist/lexicons/chat/bsky.d.ts +1 -0
- package/dist/lexicons/chat/bsky.d.ts.map +1 -1
- package/dist/lexicons/chat/bsky.js +1 -0
- package/dist/lexicons/chat/bsky.js.map +1 -1
- package/dist/lexicons/tools/ozone/report/defs.defs.d.ts +4 -0
- package/dist/lexicons/tools/ozone/report/defs.defs.d.ts.map +1 -1
- package/dist/lexicons/tools/ozone/report/defs.defs.js +2 -0
- package/dist/lexicons/tools/ozone/report/defs.defs.js.map +1 -1
- package/dist/lexicons/tools/ozone/report/queryActivities.d.ts +3 -0
- package/dist/lexicons/tools/ozone/report/queryActivities.d.ts.map +1 -0
- package/dist/lexicons/tools/ozone/report/queryActivities.defs.d.ts +42 -0
- package/dist/lexicons/tools/ozone/report/queryActivities.defs.d.ts.map +1 -0
- package/dist/lexicons/tools/ozone/report/queryActivities.defs.js +31 -0
- package/dist/lexicons/tools/ozone/report/queryActivities.defs.js.map +1 -0
- package/dist/lexicons/tools/ozone/report/queryActivities.js +6 -0
- package/dist/lexicons/tools/ozone/report/queryActivities.js.map +1 -0
- package/dist/lexicons/tools/ozone/report.d.ts +1 -0
- package/dist/lexicons/tools/ozone/report.d.ts.map +1 -1
- package/dist/lexicons/tools/ozone/report.js +1 -0
- package/dist/lexicons/tools/ozone/report.js.map +1 -1
- package/dist/proto/bsky_pb.d.ts +47 -53
- package/dist/proto/bsky_pb.d.ts.map +1 -1
- package/dist/proto/bsky_pb.js +62 -71
- package/dist/proto/bsky_pb.js.map +1 -1
- package/package.json +10 -10
- package/proto/bsky.proto +19 -17
- package/src/api/app/bsky/actor/searchActorsTypeahead.ts +5 -3
- package/src/api/app/bsky/notification/putPreferencesV2.ts +4 -1
- package/src/api/app/bsky/notification/util.ts +7 -11
- package/src/api/blob-dispatcher.ts +12 -8
- package/src/api/blob-resolver.ts +0 -1
- package/src/data-plane/bsync/index.ts +12 -10
- package/src/data-plane/server/background.ts +49 -18
- package/src/data-plane/server/index.ts +12 -10
- package/src/data-plane/server/indexing/index.ts +1 -1
- package/src/data-plane/server/indexing/plugins/block.ts +4 -1
- package/src/data-plane/server/indexing/plugins/chat-declaration.ts +4 -1
- package/src/data-plane/server/indexing/plugins/feed-generator.ts +4 -1
- package/src/data-plane/server/indexing/plugins/follow.ts +4 -1
- package/src/data-plane/server/indexing/plugins/germ-declaration.ts +4 -1
- package/src/data-plane/server/indexing/plugins/labeler.ts +4 -1
- package/src/data-plane/server/indexing/plugins/like.ts +4 -1
- package/src/data-plane/server/indexing/plugins/list-block.ts +4 -1
- package/src/data-plane/server/indexing/plugins/list-item.ts +4 -1
- package/src/data-plane/server/indexing/plugins/list.ts +4 -1
- package/src/data-plane/server/indexing/plugins/notif-declaration.ts +4 -1
- package/src/data-plane/server/indexing/plugins/post-gate.ts +4 -1
- package/src/data-plane/server/indexing/plugins/post.ts +4 -1
- package/src/data-plane/server/indexing/plugins/profile.ts +4 -1
- package/src/data-plane/server/indexing/plugins/repost.ts +4 -1
- package/src/data-plane/server/indexing/plugins/starter-pack.ts +4 -1
- package/src/data-plane/server/indexing/plugins/status.ts +4 -1
- package/src/data-plane/server/indexing/plugins/thread-gate.ts +4 -1
- package/src/data-plane/server/indexing/plugins/verification.ts +4 -1
- package/src/data-plane/server/indexing/processor.ts +1 -1
- package/src/data-plane/server/routes/notifs.ts +0 -14
- package/src/data-plane/server/routes/search.ts +2 -2
- package/src/data-plane/server/subscription.ts +74 -31
- package/src/feature-gates/index.ts +10 -6
- package/src/feature-gates/metrics.test.ts +12 -12
- package/src/feature-gates/metrics.ts +8 -8
- package/src/index.ts +16 -9
- package/tests/_util.ts +8 -25
- package/tests/admin/admin-auth.test.ts +2 -2
- package/tests/admin/moderation.test.ts +1 -1
- package/tests/auth.test.ts +4 -6
- package/tests/blob-resolver.test.ts +4 -5
- package/tests/data-plane/db.test.ts +1 -1
- package/tests/data-plane/duplicate-records.test.ts +1 -1
- package/tests/data-plane/handle-invalidation.test.ts +2 -2
- package/tests/data-plane/indexing.test.ts +24 -21
- package/tests/data-plane/subscription.test.ts +1 -1
- package/tests/data-plane/thread-mutes.test.ts +2 -2
- package/tests/entryway-auth.test.ts +4 -5
- package/tests/feed-generation.test.ts +5 -5
- package/tests/image/server.test.ts +1 -1
- package/tests/label-hydration.test.ts +3 -5
- package/tests/postgates.test.ts +3 -6
- package/tests/query-labels.test.ts +3 -5
- package/tests/redis-cache.test.ts +1 -3
- package/tests/server.test.ts +11 -16
- package/tests/sitemap.test.ts +3 -4
- package/tests/stash.test.ts +12 -8
- package/tests/utils.test.ts +3 -13
- package/tests/views/account-deactivation.test.ts +3 -5
- package/tests/views/actor-likes.test.ts +3 -5
- package/tests/views/actor-search.test.ts +6 -7
- package/tests/views/age-assurance-v2.test.ts +9 -6
- package/tests/views/age-assurance.test.ts +30 -36
- package/tests/views/author-feed.test.ts +4 -6
- package/tests/views/block-lists.test.ts +3 -5
- package/tests/views/blocks.test.ts +3 -5
- package/tests/views/bookmarks.test.ts +4 -4
- package/tests/views/drafts.test.ts +7 -14
- package/tests/views/feed-hidden-replies.test.ts +3 -6
- package/tests/views/feed-view-post.test.ts +3 -6
- package/tests/views/follows.test.ts +4 -6
- package/tests/views/get-config.test.ts +4 -7
- package/tests/views/get-suggested-onboarding-users.test.ts +11 -9
- package/tests/views/get-suggested-starter-packs.test.ts +11 -9
- package/tests/views/get-trends.test.ts +15 -9
- package/tests/views/internal-actor.test.ts +3 -6
- package/tests/views/known-followers.test.ts +3 -6
- package/tests/views/labeler-service.test.ts +3 -5
- package/tests/views/labels-needs-review.test.ts +3 -6
- package/tests/views/labels-takedown.test.ts +3 -4
- package/tests/views/likes.test.ts +4 -6
- package/tests/views/list-feed.test.ts +3 -5
- package/tests/views/lists.test.ts +3 -5
- package/tests/views/mute-lists.test.ts +3 -5
- package/tests/views/mutes.test.ts +4 -5
- package/tests/views/notifications.test.ts +12 -11
- package/tests/views/post-search.test.ts +3 -24
- package/tests/views/posts-debug.test.ts +11 -6
- package/tests/views/posts.test.ts +3 -4
- package/tests/views/profile-debug.test.ts +11 -5
- package/tests/views/profile.test.ts +11 -5
- package/tests/views/quotes.test.ts +4 -6
- package/tests/views/reposts.test.ts +4 -6
- package/tests/views/starter-packs.test.ts +3 -6
- package/tests/views/suggestions.test.ts +9 -13
- package/tests/views/thread-v2.test.ts +3 -5
- package/tests/views/thread.test.ts +3 -7
- package/tests/views/threadgating.test.ts +3 -5
- package/tests/views/timeline.test.ts +4 -5
- package/tests/views/verification.test.ts +4 -6
- package/tsconfig.build.tsbuildinfo +1 -1
- package/vitest.config.ts +1 -0
|
@@ -37,7 +37,7 @@ type Notif = Insertable<Notification>
|
|
|
37
37
|
export class RecordProcessor<TSchema extends l.RecordSchema, TRow> {
|
|
38
38
|
constructor(
|
|
39
39
|
private appDb: Database,
|
|
40
|
-
private background: BackgroundQueue
|
|
40
|
+
private background: BackgroundQueue<Database>,
|
|
41
41
|
private options: RecordProcessorOptions<TSchema, TRow>,
|
|
42
42
|
) {}
|
|
43
43
|
|
|
@@ -6,8 +6,6 @@ import { lexParse } from '@atproto/lex'
|
|
|
6
6
|
import { app } from '../../../lexicons/index.js'
|
|
7
7
|
import { Service } from '../../../proto/bsky_connect.js'
|
|
8
8
|
import {
|
|
9
|
-
ChatNotificationInclude,
|
|
10
|
-
ChatNotificationPreference,
|
|
11
9
|
FilterableNotificationPreference,
|
|
12
10
|
NotificationInclude,
|
|
13
11
|
NotificationPreference,
|
|
@@ -203,17 +201,6 @@ export const notificationPreferencesLexToProtobuf = (
|
|
|
203
201
|
p: app.bsky.notification.defs.Preferences,
|
|
204
202
|
json: string,
|
|
205
203
|
): NotificationPreferences => {
|
|
206
|
-
const lexChatPreferenceToProtobuf = (
|
|
207
|
-
p: app.bsky.notification.defs.ChatPreference,
|
|
208
|
-
): ChatNotificationPreference =>
|
|
209
|
-
new ChatNotificationPreference({
|
|
210
|
-
include:
|
|
211
|
-
p.include === 'accepted'
|
|
212
|
-
? ChatNotificationInclude.ACCEPTED
|
|
213
|
-
: ChatNotificationInclude.ALL,
|
|
214
|
-
push: { enabled: p.push ?? true },
|
|
215
|
-
})
|
|
216
|
-
|
|
217
204
|
const lexFilterablePreferenceToProtobuf = (
|
|
218
205
|
p: app.bsky.notification.defs.FilterablePreference,
|
|
219
206
|
): FilterableNotificationPreference =>
|
|
@@ -236,7 +223,6 @@ export const notificationPreferencesLexToProtobuf = (
|
|
|
236
223
|
|
|
237
224
|
return new NotificationPreferences({
|
|
238
225
|
entry: Buffer.from(json),
|
|
239
|
-
chat: lexChatPreferenceToProtobuf(p.chat),
|
|
240
226
|
follow: lexFilterablePreferenceToProtobuf(p.follow),
|
|
241
227
|
like: lexFilterablePreferenceToProtobuf(p.like),
|
|
242
228
|
likeViaRepost: lexFilterablePreferenceToProtobuf(p.likeViaRepost),
|
|
@@ -139,8 +139,8 @@ export default (db: Database): Partial<ServiceImpl<typeof Service>> => {
|
|
|
139
139
|
|
|
140
140
|
async searchActorsTypeahead(req) {
|
|
141
141
|
const { dids } = await searchActorsImpl({
|
|
142
|
-
term: req.query,
|
|
143
|
-
limit: req.limit || 10,
|
|
142
|
+
term: req.params?.query ?? '',
|
|
143
|
+
limit: req.params?.limit || 10,
|
|
144
144
|
})
|
|
145
145
|
return {
|
|
146
146
|
actors: dids.map((did) => ({ did, score: 0 })),
|
|
@@ -7,52 +7,95 @@ import { Database } from './db/index.js'
|
|
|
7
7
|
import { IndexingService } from './indexing/index.js'
|
|
8
8
|
|
|
9
9
|
export class RepoSubscription {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
background: BackgroundQueue
|
|
13
|
-
indexingSvc: IndexingService
|
|
10
|
+
private readonly abortController = new AbortController()
|
|
11
|
+
private current?: ReturnType<typeof createFirehose>
|
|
12
|
+
readonly background: BackgroundQueue<Database>
|
|
13
|
+
readonly indexingSvc: IndexingService
|
|
14
|
+
private readonly service: string
|
|
15
|
+
private readonly idResolver: IdResolver
|
|
14
16
|
|
|
15
|
-
constructor(
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
constructor({
|
|
18
|
+
service,
|
|
19
|
+
db,
|
|
20
|
+
idResolver,
|
|
21
|
+
}: {
|
|
22
|
+
service: string
|
|
23
|
+
db: Database
|
|
24
|
+
idResolver: IdResolver
|
|
25
|
+
}) {
|
|
26
|
+
this.service = service
|
|
27
|
+
this.idResolver = idResolver
|
|
28
|
+
this.background = new BackgroundQueue(db, {
|
|
29
|
+
// @TODO This has historically been using the default concurrency
|
|
30
|
+
// (Infinity) but we may want to limit this in the future to avoid
|
|
31
|
+
// overloading the database with indexing tasks.
|
|
32
|
+
concurrency: Number.POSITIVE_INFINITY,
|
|
33
|
+
})
|
|
20
34
|
this.indexingSvc = new IndexingService(db, idResolver, this.background)
|
|
35
|
+
}
|
|
21
36
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
service,
|
|
25
|
-
indexingSvc: this.indexingSvc,
|
|
26
|
-
})
|
|
27
|
-
this.runner = runner
|
|
28
|
-
this.firehose = firehose
|
|
37
|
+
get destroyed() {
|
|
38
|
+
return this.abortController.signal.aborted
|
|
29
39
|
}
|
|
30
40
|
|
|
31
|
-
|
|
32
|
-
this.
|
|
41
|
+
get running() {
|
|
42
|
+
return this.current != null
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
getCursor() {
|
|
46
|
+
return this.current?.runner.getCursor()
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
async start() {
|
|
50
|
+
this.abortController.signal.throwIfAborted()
|
|
51
|
+
|
|
52
|
+
if (!this.current) {
|
|
53
|
+
this.current = createFirehose({
|
|
54
|
+
idResolver: this.idResolver,
|
|
55
|
+
service: this.service,
|
|
56
|
+
indexingSvc: this.indexingSvc,
|
|
57
|
+
})
|
|
58
|
+
void this.current.firehose.start()
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
async stop() {
|
|
63
|
+
try {
|
|
64
|
+
if (this.current) {
|
|
65
|
+
const { firehose, runner } = this.current
|
|
66
|
+
this.current = undefined
|
|
67
|
+
try {
|
|
68
|
+
await firehose.destroy()
|
|
69
|
+
} finally {
|
|
70
|
+
await runner.destroy()
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
} finally {
|
|
74
|
+
await this.background.processAll()
|
|
75
|
+
}
|
|
33
76
|
}
|
|
34
77
|
|
|
35
78
|
async restart() {
|
|
36
|
-
await this.
|
|
37
|
-
|
|
38
|
-
idResolver: this.opts.idResolver,
|
|
39
|
-
service: this.opts.service,
|
|
40
|
-
indexingSvc: this.indexingSvc,
|
|
41
|
-
})
|
|
42
|
-
this.runner = runner
|
|
43
|
-
this.firehose = firehose
|
|
44
|
-
this.start()
|
|
79
|
+
await this.stop()
|
|
80
|
+
void this.start()
|
|
45
81
|
}
|
|
46
82
|
|
|
47
83
|
async processAll() {
|
|
48
|
-
await this.runner.processAll()
|
|
84
|
+
await this.current?.runner.processAll()
|
|
49
85
|
await this.background.processAll()
|
|
50
86
|
}
|
|
51
87
|
|
|
52
88
|
async destroy() {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
89
|
+
this.abortController.abort()
|
|
90
|
+
try {
|
|
91
|
+
await this.stop()
|
|
92
|
+
} finally {
|
|
93
|
+
await this.background.destroy()
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
async [Symbol.asyncDispose]() {
|
|
98
|
+
await this.destroy()
|
|
56
99
|
}
|
|
57
100
|
}
|
|
58
101
|
|
|
@@ -72,10 +72,10 @@ export class FeatureGatesClient {
|
|
|
72
72
|
this.client = new GrowthBookClient({
|
|
73
73
|
apiHost: this.config.growthBookApiHost,
|
|
74
74
|
clientKey: this.config.growthBookClientKey,
|
|
75
|
-
onFeatureUsage: (feature, result, userContext) => {
|
|
75
|
+
onFeatureUsage: async (feature, result, userContext) => {
|
|
76
76
|
if (IGNORE_METRICS_FOR_GATES.has(feature as Gate)) return
|
|
77
77
|
|
|
78
|
-
this.metrics.track(
|
|
78
|
+
await this.metrics.track(
|
|
79
79
|
'feature:viewed',
|
|
80
80
|
{
|
|
81
81
|
featureId: feature,
|
|
@@ -88,7 +88,7 @@ export class FeatureGatesClient {
|
|
|
88
88
|
),
|
|
89
89
|
)
|
|
90
90
|
},
|
|
91
|
-
trackingCallback: (experiment, result, userContext) => {
|
|
91
|
+
trackingCallback: async (experiment, result, userContext) => {
|
|
92
92
|
/**
|
|
93
93
|
* Experiments are only fired in a feature gate has an Experiment
|
|
94
94
|
* attached in Growthbook. Howerver, we want to be extra sure that a
|
|
@@ -101,7 +101,7 @@ export class FeatureGatesClient {
|
|
|
101
101
|
)
|
|
102
102
|
return
|
|
103
103
|
|
|
104
|
-
this.metrics.track(
|
|
104
|
+
await this.metrics.track(
|
|
105
105
|
'experiment:viewed',
|
|
106
106
|
{
|
|
107
107
|
experimentId: experiment.key,
|
|
@@ -154,14 +154,18 @@ export class FeatureGatesClient {
|
|
|
154
154
|
}
|
|
155
155
|
}
|
|
156
156
|
|
|
157
|
-
destroy() {
|
|
157
|
+
async destroy() {
|
|
158
158
|
if (this.ready) {
|
|
159
159
|
this.ready = false
|
|
160
160
|
if (this.refreshInterval) {
|
|
161
161
|
clearInterval(this.refreshInterval)
|
|
162
162
|
}
|
|
163
163
|
}
|
|
164
|
-
this.metrics.stop()
|
|
164
|
+
await this.metrics.stop()
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
async [Symbol.asyncDispose]() {
|
|
168
|
+
await this.destroy()
|
|
165
169
|
}
|
|
166
170
|
|
|
167
171
|
/**
|
|
@@ -32,8 +32,8 @@ describe('MetricsClient', () => {
|
|
|
32
32
|
global.fetch = fetchMock
|
|
33
33
|
})
|
|
34
34
|
|
|
35
|
-
afterEach(() => {
|
|
36
|
-
client?.stop()
|
|
35
|
+
afterEach(async () => {
|
|
36
|
+
await client?.stop()
|
|
37
37
|
vi.useRealTimers()
|
|
38
38
|
vi.clearAllMocks()
|
|
39
39
|
})
|
|
@@ -42,8 +42,8 @@ describe('MetricsClient', () => {
|
|
|
42
42
|
client = new MetricsClient<TestEvents>({
|
|
43
43
|
trackingEndpoint: 'https://test.metrics.api',
|
|
44
44
|
})
|
|
45
|
-
client.track('click', { button: 'submit' })
|
|
46
|
-
client.track('view', { screen: 'home' })
|
|
45
|
+
await client.track('click', { button: 'submit' })
|
|
46
|
+
await client.track('view', { screen: 'home' })
|
|
47
47
|
|
|
48
48
|
expect(fetchRequests).toHaveLength(0)
|
|
49
49
|
|
|
@@ -65,13 +65,13 @@ describe('MetricsClient', () => {
|
|
|
65
65
|
|
|
66
66
|
// Add events up to maxBatchSize (should not flush yet)
|
|
67
67
|
for (let i = 0; i < 5; i++) {
|
|
68
|
-
client.track('click', { button: `btn-${i}` })
|
|
68
|
+
await client.track('click', { button: `btn-${i}` })
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
expect(fetchRequests).toHaveLength(0)
|
|
72
72
|
|
|
73
73
|
// One more event should trigger flush (> maxBatchSize)
|
|
74
|
-
client.track('click', { button: 'btn-trigger' })
|
|
74
|
+
await client.track('click', { button: 'btn-trigger' })
|
|
75
75
|
await flushPromises()
|
|
76
76
|
|
|
77
77
|
expect(fetchRequests).toHaveLength(1)
|
|
@@ -90,7 +90,7 @@ describe('MetricsClient', () => {
|
|
|
90
90
|
client = new MetricsClient<TestEvents>({
|
|
91
91
|
trackingEndpoint: 'https://test.metrics.api',
|
|
92
92
|
})
|
|
93
|
-
client.track('click', { button: 'submit' })
|
|
93
|
+
await client.track('click', { button: 'submit' })
|
|
94
94
|
|
|
95
95
|
// Trigger flush via interval
|
|
96
96
|
vi.advanceTimersByTime(10_000)
|
|
@@ -119,7 +119,7 @@ describe('MetricsClient', () => {
|
|
|
119
119
|
client = new MetricsClient<TestEvents>({
|
|
120
120
|
trackingEndpoint: 'https://test.metrics.api',
|
|
121
121
|
})
|
|
122
|
-
client.track('click', { button: 'submit' })
|
|
122
|
+
await client.track('click', { button: 'submit' })
|
|
123
123
|
|
|
124
124
|
// Trigger flush - should not throw
|
|
125
125
|
vi.advanceTimersByTime(10_000)
|
|
@@ -140,12 +140,12 @@ describe('MetricsClient', () => {
|
|
|
140
140
|
client = new MetricsClient<TestEvents>({
|
|
141
141
|
trackingEndpoint: 'https://test.metrics.api',
|
|
142
142
|
})
|
|
143
|
-
client.track('click', { button: 'submit' })
|
|
143
|
+
await client.track('click', { button: 'submit' })
|
|
144
144
|
|
|
145
145
|
expect(fetchRequests).toHaveLength(0)
|
|
146
146
|
|
|
147
147
|
// Stop should flush remaining events
|
|
148
|
-
client.stop()
|
|
148
|
+
await client.stop()
|
|
149
149
|
await flushPromises()
|
|
150
150
|
|
|
151
151
|
expect(fetchRequests).toHaveLength(1)
|
|
@@ -155,7 +155,7 @@ describe('MetricsClient', () => {
|
|
|
155
155
|
|
|
156
156
|
it('does not send if trackingEndpoint is not configured', async () => {
|
|
157
157
|
client = new MetricsClient<TestEvents>({})
|
|
158
|
-
client.track('click', { button: 'submit' })
|
|
158
|
+
await client.track('click', { button: 'submit' })
|
|
159
159
|
|
|
160
160
|
// Trigger flush via interval
|
|
161
161
|
vi.advanceTimersByTime(10_000)
|
|
@@ -170,7 +170,7 @@ describe('MetricsClient', () => {
|
|
|
170
170
|
})
|
|
171
171
|
|
|
172
172
|
// track() calls start() internally
|
|
173
|
-
client.track('click', { button: 'submit' })
|
|
173
|
+
await client.track('click', { button: 'submit' })
|
|
174
174
|
client.start()
|
|
175
175
|
client.start()
|
|
176
176
|
|
|
@@ -38,24 +38,24 @@ export class MetricsClient<M extends Record<string, any> = Events> {
|
|
|
38
38
|
if (this.started) return
|
|
39
39
|
this.started = true
|
|
40
40
|
this.flushInterval = setInterval(() => {
|
|
41
|
-
this.flush()
|
|
41
|
+
void this.flush()
|
|
42
42
|
}, 10_000)
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
-
stop() {
|
|
45
|
+
async stop() {
|
|
46
46
|
if (this.flushInterval) {
|
|
47
47
|
clearInterval(this.flushInterval)
|
|
48
48
|
this.flushInterval = null
|
|
49
49
|
}
|
|
50
|
-
this.flush()
|
|
50
|
+
await this.flush()
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
-
track<E extends keyof M>(
|
|
53
|
+
async track<E extends keyof M>(
|
|
54
54
|
event: E,
|
|
55
55
|
payload: M[E],
|
|
56
56
|
metadata: Record<string, any> = {},
|
|
57
57
|
) {
|
|
58
|
-
this.start()
|
|
58
|
+
await this.start()
|
|
59
59
|
|
|
60
60
|
const e = {
|
|
61
61
|
source: 'appview',
|
|
@@ -67,14 +67,14 @@ export class MetricsClient<M extends Record<string, any> = Events> {
|
|
|
67
67
|
this.queue.push(e)
|
|
68
68
|
|
|
69
69
|
if (this.queue.length > this.maxBatchSize) {
|
|
70
|
-
this.flush()
|
|
70
|
+
await this.flush()
|
|
71
71
|
}
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
-
flush() {
|
|
74
|
+
async flush() {
|
|
75
75
|
if (!this.queue.length) return
|
|
76
76
|
const events = this.queue.splice(0, this.queue.length)
|
|
77
|
-
this.sendBatch(events)
|
|
77
|
+
await this.sendBatch(events)
|
|
78
78
|
}
|
|
79
79
|
|
|
80
80
|
private async sendBatch(events: Event<M>[]) {
|
package/src/index.ts
CHANGED
|
@@ -5,11 +5,8 @@ import compression from 'compression'
|
|
|
5
5
|
import cors from 'cors'
|
|
6
6
|
import { Etcd3 } from 'etcd3'
|
|
7
7
|
import express from 'express'
|
|
8
|
-
// eslint-disable-next-line import/default
|
|
8
|
+
// eslint-disable-next-line import/default
|
|
9
9
|
import httpTerminator from 'http-terminator'
|
|
10
|
-
// eslint-disable-next-line import/no-named-as-default-member
|
|
11
|
-
const { createHttpTerminator } = httpTerminator
|
|
12
|
-
type HttpTerminator = ReturnType<typeof createHttpTerminator>
|
|
13
10
|
import { DAY, SECOND } from '@atproto/common'
|
|
14
11
|
import { Keypair } from '@atproto/crypto'
|
|
15
12
|
import { IdResolver } from '@atproto/identity'
|
|
@@ -63,7 +60,7 @@ export class BskyAppView {
|
|
|
63
60
|
public ctx: AppContext
|
|
64
61
|
public app: express.Application
|
|
65
62
|
public server?: http.Server
|
|
66
|
-
private terminator?: HttpTerminator
|
|
63
|
+
private terminator?: httpTerminator.HttpTerminator
|
|
67
64
|
|
|
68
65
|
constructor(opts: { ctx: AppContext; app: express.Application }) {
|
|
69
66
|
this.ctx = opts.ctx
|
|
@@ -288,7 +285,7 @@ export class BskyAppView {
|
|
|
288
285
|
const server = this.app.listen(this.ctx.cfg.port)
|
|
289
286
|
this.server = server
|
|
290
287
|
server.keepAliveTimeout = 90000
|
|
291
|
-
this.terminator = createHttpTerminator({ server })
|
|
288
|
+
this.terminator = httpTerminator.createHttpTerminator({ server })
|
|
292
289
|
await events.once(server, 'listening')
|
|
293
290
|
const { port } = server.address() as AddressInfo
|
|
294
291
|
this.ctx.cfg.assignPort(port)
|
|
@@ -296,9 +293,19 @@ export class BskyAppView {
|
|
|
296
293
|
}
|
|
297
294
|
|
|
298
295
|
async destroy(): Promise<void> {
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
296
|
+
try {
|
|
297
|
+
await this.ctx.featureGatesClient.destroy()
|
|
298
|
+
} finally {
|
|
299
|
+
try {
|
|
300
|
+
await this.terminator?.terminate()
|
|
301
|
+
} finally {
|
|
302
|
+
await this.ctx.etcd?.close()
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
async [Symbol.asyncDispose]() {
|
|
308
|
+
await this.destroy()
|
|
302
309
|
}
|
|
303
310
|
}
|
|
304
311
|
|
package/tests/_util.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { RequestListener, createServer } from 'node:http'
|
|
2
2
|
import { AddressInfo } from 'node:net'
|
|
3
|
-
|
|
3
|
+
// eslint-disable-next-line import/default
|
|
4
|
+
import httpTerminator from 'http-terminator'
|
|
4
5
|
import { expect } from 'vitest'
|
|
5
6
|
import {
|
|
6
7
|
$Typed,
|
|
@@ -265,19 +266,11 @@ export const stripViewerFromLabeler = (
|
|
|
265
266
|
return stripViewer(labeler)
|
|
266
267
|
}
|
|
267
268
|
|
|
268
|
-
export async function startServer(
|
|
269
|
-
return new Promise<{
|
|
270
|
-
origin: string
|
|
271
|
-
server: Server
|
|
272
|
-
stop: () => Promise<void>
|
|
273
|
-
}>((resolve, reject) => {
|
|
269
|
+
export async function startServer(listener: RequestListener) {
|
|
270
|
+
return new Promise<AsyncDisposable & { port: number }>((resolve, reject) => {
|
|
274
271
|
const onListen = () => {
|
|
275
272
|
const port = (server.address() as AddressInfo).port
|
|
276
|
-
resolve({
|
|
277
|
-
server,
|
|
278
|
-
origin: `http://localhost:${port}`,
|
|
279
|
-
stop: () => stopServer(server),
|
|
280
|
-
})
|
|
273
|
+
resolve({ port, [Symbol.asyncDispose]: () => terminator.terminate() })
|
|
281
274
|
cleanup()
|
|
282
275
|
}
|
|
283
276
|
const onError = (err: Error) => {
|
|
@@ -289,21 +282,11 @@ export async function startServer(app: Express) {
|
|
|
289
282
|
server.removeListener('error', onError)
|
|
290
283
|
}
|
|
291
284
|
|
|
292
|
-
const server =
|
|
285
|
+
const server = createServer(listener)
|
|
293
286
|
.listen(0)
|
|
294
287
|
.once('listening', onListen)
|
|
295
288
|
.once('error', onError)
|
|
296
|
-
})
|
|
297
|
-
}
|
|
298
289
|
|
|
299
|
-
|
|
300
|
-
return new Promise<void>((resolve, reject) => {
|
|
301
|
-
server.close((err) => {
|
|
302
|
-
if (err) {
|
|
303
|
-
reject(err)
|
|
304
|
-
} else {
|
|
305
|
-
resolve()
|
|
306
|
-
}
|
|
307
|
-
})
|
|
290
|
+
const terminator = httpTerminator.createHttpTerminator({ server })
|
|
308
291
|
})
|
|
309
292
|
}
|
|
@@ -62,10 +62,10 @@ describe('admin auth', () => {
|
|
|
62
62
|
$type: 'com.atproto.admin.defs#repoRef',
|
|
63
63
|
did: sc.dids.bob,
|
|
64
64
|
}
|
|
65
|
-
}
|
|
65
|
+
})
|
|
66
66
|
|
|
67
67
|
afterAll(async () => {
|
|
68
|
-
await network
|
|
68
|
+
await network?.close()
|
|
69
69
|
})
|
|
70
70
|
|
|
71
71
|
it('allows service auth requests from the configured appview did', async () => {
|
package/tests/auth.test.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { afterAll, beforeAll, describe, expect, it } from 'vitest'
|
|
1
|
+
import { afterAll, beforeAll, beforeEach, describe, expect, it } from 'vitest'
|
|
2
2
|
import { AtpAgent, ids } from '@atproto/api'
|
|
3
3
|
import { Keypair, Secp256k1Keypair } from '@atproto/crypto'
|
|
4
4
|
import { SeedClient, TestNetwork, usersSeed } from '@atproto/dev-env'
|
|
@@ -20,15 +20,13 @@ describe('auth', () => {
|
|
|
20
20
|
agent = network.bsky.getAgent()
|
|
21
21
|
sc = network.getSeedClient()
|
|
22
22
|
await usersSeed(sc)
|
|
23
|
-
await network.processAll()
|
|
24
23
|
alice = sc.dids.alice
|
|
25
24
|
bob = sc.dids.bob
|
|
26
|
-
}, 20_000) // @NOTE seeding can take a while
|
|
27
|
-
|
|
28
|
-
afterAll(async () => {
|
|
29
|
-
await network.close()
|
|
30
25
|
})
|
|
31
26
|
|
|
27
|
+
beforeEach(async () => network.processAll())
|
|
28
|
+
afterAll(async () => network?.close())
|
|
29
|
+
|
|
32
30
|
// @TODO invalidations do not originate from appview frontends: requires identity event on the repo stream.
|
|
33
31
|
it.skip('handles signing key change for service auth.', async () => {
|
|
34
32
|
const issuer = sc.dids.alice
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { request } from 'undici'
|
|
2
|
-
import { afterAll, beforeAll, describe, expect, it } from 'vitest'
|
|
2
|
+
import { afterAll, beforeAll, beforeEach, describe, expect, it } from 'vitest'
|
|
3
3
|
import { cidForCbor, verifyCidForBytes } from '@atproto/common'
|
|
4
4
|
import { randomBytes } from '@atproto/crypto'
|
|
5
5
|
import { TestNetwork, basicSeed } from '@atproto/dev-env'
|
|
@@ -17,15 +17,14 @@ describe('blob resolver', () => {
|
|
|
17
17
|
})
|
|
18
18
|
const sc = network.getSeedClient()
|
|
19
19
|
await basicSeed(sc)
|
|
20
|
-
|
|
20
|
+
|
|
21
21
|
fileDid = sc.dids.carol
|
|
22
22
|
fileCid = sc.posts[fileDid][0].images[0].image.ref
|
|
23
23
|
fileSize = sc.posts[fileDid][0].images[0].image.size
|
|
24
24
|
})
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
})
|
|
26
|
+
beforeEach(async () => network.processAll())
|
|
27
|
+
afterAll(async () => network?.close())
|
|
29
28
|
|
|
30
29
|
it('resolves blob with good signature check.', async () => {
|
|
31
30
|
const response = await request(
|
|
@@ -38,10 +38,10 @@ describe('handle invalidation', () => {
|
|
|
38
38
|
}
|
|
39
39
|
return origResolve(handle)
|
|
40
40
|
}
|
|
41
|
-
}
|
|
41
|
+
})
|
|
42
42
|
|
|
43
43
|
afterAll(async () => {
|
|
44
|
-
await network
|
|
44
|
+
await network?.close()
|
|
45
45
|
})
|
|
46
46
|
|
|
47
47
|
const backdateIndexedAt = async (did: string) => {
|