@atproto/bsky 0.0.15 → 0.0.17

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.
Files changed (236) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/dist/api/com/atproto/moderation/util.d.ts +4 -3
  3. package/dist/cache/read-through.d.ts +30 -0
  4. package/dist/config.d.ts +18 -0
  5. package/dist/context.d.ts +21 -6
  6. package/dist/daemon/config.d.ts +15 -0
  7. package/dist/daemon/context.d.ts +15 -0
  8. package/dist/daemon/index.d.ts +23 -0
  9. package/dist/daemon/logger.d.ts +3 -0
  10. package/dist/daemon/notifications.d.ts +18 -0
  11. package/dist/daemon/services.d.ts +11 -0
  12. package/dist/db/database-schema.d.ts +1 -2
  13. package/dist/db/index.js +41 -1
  14. package/dist/db/index.js.map +3 -3
  15. package/dist/db/migrations/20231003T202833377Z-create-moderation-subject-status.d.ts +3 -0
  16. package/dist/db/migrations/20231205T000257238Z-remove-did-cache.d.ts +3 -0
  17. package/dist/db/migrations/index.d.ts +2 -0
  18. package/dist/db/pagination.d.ts +2 -1
  19. package/dist/db/{periodic-moderation-action-reversal.d.ts → periodic-moderation-event-reversal.d.ts} +3 -5
  20. package/dist/db/tables/moderation.d.ts +24 -34
  21. package/dist/did-cache.d.ts +10 -7
  22. package/dist/feed-gen/types.d.ts +1 -1
  23. package/dist/index.d.ts +6 -1
  24. package/dist/index.js +4370 -2758
  25. package/dist/index.js.map +3 -3
  26. package/dist/indexer/context.d.ts +2 -0
  27. package/dist/indexer/index.d.ts +1 -0
  28. package/dist/lexicon/index.d.ts +23 -18
  29. package/dist/lexicon/lexicons.d.ts +561 -412
  30. package/dist/lexicon/types/app/bsky/feed/defs.d.ts +1 -7
  31. package/dist/lexicon/types/app/bsky/graph/defs.d.ts +1 -0
  32. package/dist/lexicon/types/com/atproto/admin/defs.d.ts +114 -48
  33. package/dist/lexicon/types/com/atproto/admin/{resolveModerationReports.d.ts → deleteAccount.d.ts} +2 -13
  34. package/dist/lexicon/types/com/atproto/admin/{takeModerationAction.d.ts → emitModerationEvent.d.ts} +5 -6
  35. package/dist/lexicon/types/com/atproto/admin/{getModerationAction.d.ts → getModerationEvent.d.ts} +1 -1
  36. package/dist/lexicon/types/com/atproto/admin/{getModerationActions.d.ts → queryModerationEvents.d.ts} +5 -1
  37. package/dist/lexicon/types/com/atproto/admin/{getModerationReports.d.ts → queryModerationStatuses.d.ts} +12 -6
  38. package/dist/lexicon/types/com/atproto/admin/sendEmail.d.ts +1 -0
  39. package/dist/lexicon/types/com/atproto/{admin/getModerationReport.d.ts → temp/importRepo.d.ts} +10 -7
  40. package/dist/lexicon/types/com/atproto/temp/pushBlob.d.ts +25 -0
  41. package/dist/lexicon/types/com/atproto/{admin/reverseModerationAction.d.ts → temp/transferAccount.d.ts} +11 -5
  42. package/dist/logger.d.ts +1 -0
  43. package/dist/migrate-moderation-data.d.ts +1 -0
  44. package/dist/redis.d.ts +10 -1
  45. package/dist/services/actor/index.d.ts +18 -4
  46. package/dist/services/actor/views.d.ts +6 -8
  47. package/dist/services/feed/index.d.ts +7 -4
  48. package/dist/services/feed/util.d.ts +9 -1
  49. package/dist/services/feed/views.d.ts +11 -21
  50. package/dist/services/graph/index.d.ts +5 -29
  51. package/dist/services/graph/types.d.ts +1 -0
  52. package/dist/services/index.d.ts +3 -7
  53. package/dist/services/label/index.d.ts +10 -4
  54. package/dist/services/moderation/index.d.ts +134 -72
  55. package/dist/services/moderation/pagination.d.ts +36 -0
  56. package/dist/services/moderation/status.d.ts +13 -0
  57. package/dist/services/moderation/types.d.ts +35 -0
  58. package/dist/services/moderation/views.d.ts +18 -14
  59. package/dist/services/types.d.ts +3 -0
  60. package/dist/services/util/notification.d.ts +5 -0
  61. package/dist/services/util/post.d.ts +6 -6
  62. package/dist/util/debug.d.ts +1 -1
  63. package/dist/util/retry.d.ts +1 -6
  64. package/package.json +11 -11
  65. package/src/api/app/bsky/feed/getActorFeeds.ts +2 -1
  66. package/src/api/app/bsky/feed/getActorLikes.ts +1 -3
  67. package/src/api/app/bsky/feed/getAuthorFeed.ts +1 -3
  68. package/src/api/app/bsky/feed/getFeed.ts +9 -9
  69. package/src/api/app/bsky/feed/getFeedGenerator.ts +3 -0
  70. package/src/api/app/bsky/feed/getFeedGenerators.ts +2 -1
  71. package/src/api/app/bsky/feed/getListFeed.ts +1 -3
  72. package/src/api/app/bsky/feed/getPostThread.ts +15 -54
  73. package/src/api/app/bsky/feed/getPosts.ts +21 -18
  74. package/src/api/app/bsky/feed/getSuggestedFeeds.ts +2 -1
  75. package/src/api/app/bsky/feed/getTimeline.ts +1 -3
  76. package/src/api/app/bsky/feed/searchPosts.ts +20 -17
  77. package/src/api/app/bsky/graph/getList.ts +6 -3
  78. package/src/api/app/bsky/graph/getListBlocks.ts +3 -2
  79. package/src/api/app/bsky/graph/getListMutes.ts +2 -1
  80. package/src/api/app/bsky/graph/getLists.ts +2 -1
  81. package/src/api/app/bsky/unspecced/getPopularFeedGenerators.ts +3 -1
  82. package/src/api/blob-resolver.ts +6 -11
  83. package/src/api/com/atproto/admin/emitModerationEvent.ts +220 -0
  84. package/src/api/com/atproto/admin/{getModerationActions.ts → getModerationEvent.ts} +5 -11
  85. package/src/api/com/atproto/admin/getRecord.ts +1 -0
  86. package/src/api/com/atproto/admin/{getModerationReports.ts → queryModerationEvents.ts} +13 -16
  87. package/src/api/com/atproto/admin/queryModerationStatuses.ts +55 -0
  88. package/src/api/com/atproto/moderation/createReport.ts +9 -7
  89. package/src/api/com/atproto/moderation/util.ts +38 -20
  90. package/src/api/index.ts +8 -14
  91. package/src/auth.ts +29 -21
  92. package/src/auto-moderator/index.ts +26 -19
  93. package/src/cache/read-through.ts +151 -0
  94. package/src/config.ts +90 -1
  95. package/src/context.ts +11 -7
  96. package/src/daemon/config.ts +60 -0
  97. package/src/daemon/context.ts +27 -0
  98. package/src/daemon/index.ts +78 -0
  99. package/src/daemon/logger.ts +6 -0
  100. package/src/daemon/notifications.ts +54 -0
  101. package/src/daemon/services.ts +22 -0
  102. package/src/db/database-schema.ts +0 -2
  103. package/src/db/migrations/20231003T202833377Z-create-moderation-subject-status.ts +123 -0
  104. package/src/db/migrations/20231205T000257238Z-remove-did-cache.ts +14 -0
  105. package/src/db/migrations/index.ts +2 -0
  106. package/src/db/pagination.ts +26 -3
  107. package/src/db/{periodic-moderation-action-reversal.ts → periodic-moderation-event-reversal.ts} +50 -46
  108. package/src/db/tables/moderation.ts +35 -52
  109. package/src/did-cache.ts +33 -56
  110. package/src/feed-gen/bsky-team.ts +1 -1
  111. package/src/feed-gen/hot-classic.ts +1 -1
  112. package/src/feed-gen/index.ts +0 -4
  113. package/src/feed-gen/mutuals.ts +6 -2
  114. package/src/feed-gen/types.ts +1 -1
  115. package/src/index.ts +57 -17
  116. package/src/indexer/context.ts +5 -0
  117. package/src/indexer/index.ts +10 -7
  118. package/src/lexicon/index.ts +80 -67
  119. package/src/lexicon/lexicons.ts +698 -507
  120. package/src/lexicon/types/app/bsky/feed/defs.ts +1 -18
  121. package/src/lexicon/types/app/bsky/graph/defs.ts +1 -0
  122. package/src/lexicon/types/com/atproto/admin/defs.ts +276 -84
  123. package/src/lexicon/types/com/atproto/admin/{resolveModerationReports.ts → deleteAccount.ts} +2 -13
  124. package/src/lexicon/types/com/atproto/admin/{takeModerationAction.ts → emitModerationEvent.ts} +13 -11
  125. package/src/lexicon/types/com/atproto/admin/{getModerationReport.ts → getModerationEvent.ts} +1 -1
  126. package/src/lexicon/types/com/atproto/admin/{getModerationActions.ts → queryModerationEvents.ts} +8 -1
  127. package/src/lexicon/types/com/atproto/admin/{getModerationReports.ts → queryModerationStatuses.ts} +21 -14
  128. package/src/lexicon/types/com/atproto/admin/sendEmail.ts +1 -0
  129. package/src/lexicon/types/com/atproto/{admin/getModerationAction.ts → temp/importRepo.ts} +11 -7
  130. package/src/lexicon/types/com/atproto/temp/pushBlob.ts +39 -0
  131. package/src/lexicon/types/com/atproto/{admin/reverseModerationAction.ts → temp/transferAccount.ts} +18 -5
  132. package/src/logger.ts +2 -0
  133. package/src/migrate-moderation-data.ts +414 -0
  134. package/src/redis.ts +43 -3
  135. package/src/services/actor/index.ts +55 -7
  136. package/src/services/actor/views.ts +18 -21
  137. package/src/services/feed/index.ts +52 -19
  138. package/src/services/feed/util.ts +47 -19
  139. package/src/services/feed/views.ts +87 -13
  140. package/src/services/graph/index.ts +21 -3
  141. package/src/services/graph/types.ts +1 -0
  142. package/src/services/index.ts +14 -14
  143. package/src/services/indexing/index.ts +7 -10
  144. package/src/services/indexing/plugins/block.ts +2 -3
  145. package/src/services/indexing/plugins/feed-generator.ts +2 -3
  146. package/src/services/indexing/plugins/follow.ts +2 -3
  147. package/src/services/indexing/plugins/like.ts +2 -3
  148. package/src/services/indexing/plugins/list-block.ts +2 -3
  149. package/src/services/indexing/plugins/list-item.ts +2 -3
  150. package/src/services/indexing/plugins/list.ts +2 -3
  151. package/src/services/indexing/plugins/post.ts +16 -4
  152. package/src/services/indexing/plugins/repost.ts +2 -3
  153. package/src/services/indexing/plugins/thread-gate.ts +2 -3
  154. package/src/services/label/index.ts +68 -25
  155. package/src/services/moderation/index.ts +380 -395
  156. package/src/services/moderation/pagination.ts +96 -0
  157. package/src/services/moderation/status.ts +241 -0
  158. package/src/services/moderation/types.ts +49 -0
  159. package/src/services/moderation/views.ts +278 -329
  160. package/src/services/types.ts +4 -0
  161. package/src/services/util/notification.ts +70 -0
  162. package/src/util/debug.ts +2 -2
  163. package/src/util/retry.ts +1 -44
  164. package/tests/__snapshots__/feed-generation.test.ts.snap +322 -6
  165. package/tests/__snapshots__/indexing.test.ts.snap +0 -6
  166. package/tests/admin/__snapshots__/get-record.test.ts.snap +30 -132
  167. package/tests/admin/__snapshots__/get-repo.test.ts.snap +14 -60
  168. package/tests/admin/__snapshots__/moderation-events.test.ts.snap +146 -0
  169. package/tests/admin/__snapshots__/moderation-statuses.test.ts.snap +64 -0
  170. package/tests/admin/__snapshots__/moderation.test.ts.snap +0 -125
  171. package/tests/admin/get-record.test.ts +5 -9
  172. package/tests/admin/get-repo.test.ts +10 -12
  173. package/tests/admin/moderation-events.test.ts +221 -0
  174. package/tests/admin/moderation-statuses.test.ts +145 -0
  175. package/tests/admin/moderation.test.ts +512 -860
  176. package/tests/admin/repo-search.test.ts +3 -3
  177. package/tests/algos/hot-classic.test.ts +1 -2
  178. package/tests/auth.test.ts +1 -1
  179. package/tests/auto-moderator/fuzzy-matcher.test.ts +2 -1
  180. package/tests/auto-moderator/labeler.test.ts +19 -20
  181. package/tests/auto-moderator/takedowns.test.ts +61 -28
  182. package/tests/blob-resolver.test.ts +4 -2
  183. package/tests/daemon.test.ts +191 -0
  184. package/tests/did-cache.test.ts +20 -5
  185. package/tests/feed-generation.test.ts +57 -9
  186. package/tests/handle-invalidation.test.ts +1 -5
  187. package/tests/indexing.test.ts +20 -13
  188. package/tests/redis-cache.test.ts +231 -0
  189. package/tests/seeds/basic.ts +3 -0
  190. package/tests/subscription/repo.test.ts +4 -7
  191. package/tests/views/__snapshots__/block-lists.test.ts.snap +3 -9
  192. package/tests/views/__snapshots__/blocks.test.ts.snap +0 -9
  193. package/tests/views/__snapshots__/mute-lists.test.ts.snap +5 -5
  194. package/tests/views/__snapshots__/mutes.test.ts.snap +0 -3
  195. package/tests/views/__snapshots__/thread.test.ts.snap +0 -30
  196. package/tests/views/actor-search.test.ts +2 -3
  197. package/tests/views/author-feed.test.ts +42 -36
  198. package/tests/views/follows.test.ts +40 -35
  199. package/tests/views/list-feed.test.ts +17 -9
  200. package/tests/views/notifications.test.ts +13 -9
  201. package/tests/views/profile.test.ts +20 -19
  202. package/tests/views/thread.test.ts +117 -94
  203. package/tests/views/threadgating.test.ts +89 -19
  204. package/tests/views/timeline.test.ts +21 -13
  205. package/dist/api/com/atproto/admin/resolveModerationReports.d.ts +0 -3
  206. package/dist/api/com/atproto/admin/reverseModerationAction.d.ts +0 -3
  207. package/dist/api/com/atproto/admin/takeModerationAction.d.ts +0 -3
  208. package/dist/db/tables/did-cache.d.ts +0 -10
  209. package/dist/feed-gen/best-of-follows.d.ts +0 -29
  210. package/dist/feed-gen/whats-hot.d.ts +0 -29
  211. package/dist/feed-gen/with-friends.d.ts +0 -3
  212. package/dist/label-cache.d.ts +0 -19
  213. package/src/api/com/atproto/admin/getModerationAction.ts +0 -44
  214. package/src/api/com/atproto/admin/getModerationReport.ts +0 -43
  215. package/src/api/com/atproto/admin/resolveModerationReports.ts +0 -24
  216. package/src/api/com/atproto/admin/reverseModerationAction.ts +0 -115
  217. package/src/api/com/atproto/admin/takeModerationAction.ts +0 -156
  218. package/src/db/tables/did-cache.ts +0 -13
  219. package/src/feed-gen/best-of-follows.ts +0 -74
  220. package/src/feed-gen/whats-hot.ts +0 -101
  221. package/src/feed-gen/with-friends.ts +0 -39
  222. package/src/label-cache.ts +0 -90
  223. package/tests/admin/__snapshots__/get-moderation-action.test.ts.snap +0 -172
  224. package/tests/admin/__snapshots__/get-moderation-actions.test.ts.snap +0 -178
  225. package/tests/admin/__snapshots__/get-moderation-report.test.ts.snap +0 -177
  226. package/tests/admin/__snapshots__/get-moderation-reports.test.ts.snap +0 -307
  227. package/tests/admin/get-moderation-action.test.ts +0 -100
  228. package/tests/admin/get-moderation-actions.test.ts +0 -164
  229. package/tests/admin/get-moderation-report.test.ts +0 -100
  230. package/tests/admin/get-moderation-reports.test.ts +0 -332
  231. package/tests/algos/whats-hot.test.ts +0 -118
  232. package/tests/algos/with-friends.test.ts +0 -145
  233. /package/dist/api/com/atproto/admin/{getModerationAction.d.ts → emitModerationEvent.d.ts} +0 -0
  234. /package/dist/api/com/atproto/admin/{getModerationActions.d.ts → getModerationEvent.d.ts} +0 -0
  235. /package/dist/api/com/atproto/admin/{getModerationReport.d.ts → queryModerationEvents.d.ts} +0 -0
  236. /package/dist/api/com/atproto/admin/{getModerationReports.d.ts → queryModerationStatuses.d.ts} +0 -0
@@ -498,7 +498,8 @@ describe('indexing', () => {
498
498
 
499
499
  it('skips invalid records.', async () => {
500
500
  const { db, services } = network.bsky.indexer.ctx
501
- const { db: pdsDb, services: pdsServices } = network.pds.ctx
501
+ const { accountManager } = network.pds.ctx
502
+ // const { db: pdsDb, services: pdsServices } = network.pds.ctx
502
503
  // Create a good and a bad post record
503
504
  const writes = await Promise.all([
504
505
  pdsRepo.prepareCreate({
@@ -513,9 +514,20 @@ describe('indexing', () => {
513
514
  validate: false,
514
515
  }),
515
516
  ])
516
- await pdsServices
517
- .repo(pdsDb)
518
- .processWrites({ did: sc.dids.alice, writes }, 1)
517
+ const writeCommit = await network.pds.ctx.actorStore.transact(
518
+ sc.dids.alice,
519
+ (store) => store.repo.processWrites(writes),
520
+ )
521
+ await accountManager.updateRepoRoot(
522
+ sc.dids.alice,
523
+ writeCommit.cid,
524
+ writeCommit.rev,
525
+ )
526
+ await network.pds.ctx.sequencer.sequenceCommit(
527
+ sc.dids.alice,
528
+ writeCommit,
529
+ writes,
530
+ )
519
531
  // Index
520
532
  const { data: commit } =
521
533
  await pdsAgent.api.com.atproto.sync.getLatestCommit({
@@ -643,15 +655,10 @@ describe('indexing', () => {
643
655
  )
644
656
  await expect(getProfileBefore).resolves.toBeDefined()
645
657
  // Delete account on pds
646
- await pdsAgent.api.com.atproto.server.requestAccountDelete(undefined, {
647
- headers: sc.getHeaders(alice),
648
- })
649
- const { token } = await network.pds.ctx.db.db
650
- .selectFrom('email_token')
651
- .selectAll()
652
- .where('purpose', '=', 'delete_account')
653
- .where('did', '=', alice)
654
- .executeTakeFirstOrThrow()
658
+ const token = await network.pds.ctx.accountManager.createEmailToken(
659
+ alice,
660
+ 'delete_account',
661
+ )
655
662
  await pdsAgent.api.com.atproto.server.deleteAccount({
656
663
  token,
657
664
  did: alice,
@@ -0,0 +1,231 @@
1
+ import { wait } from '@atproto/common'
2
+ import { Redis } from '../src/'
3
+ import { ReadThroughCache } from '../src/cache/read-through'
4
+
5
+ describe('redis cache', () => {
6
+ let redis: Redis
7
+
8
+ beforeAll(async () => {
9
+ redis = new Redis({ host: process.env.REDIS_HOST || '' })
10
+ })
11
+
12
+ afterAll(async () => {
13
+ await redis.destroy()
14
+ })
15
+
16
+ it('caches according to namespace', async () => {
17
+ const ns1 = redis.withNamespace('ns1')
18
+ const ns2 = redis.withNamespace('ns2')
19
+ await Promise.all([
20
+ ns1.set('key', 'a'),
21
+ ns2.set('key', 'b'),
22
+ redis.set('key', 'c'),
23
+ ])
24
+ const got = await Promise.all([
25
+ ns1.get('key'),
26
+ ns2.get('key'),
27
+ redis.get('key'),
28
+ ])
29
+ expect(got[0]).toEqual('a')
30
+ expect(got[1]).toEqual('b')
31
+ expect(got[2]).toEqual('c')
32
+
33
+ await Promise.all([
34
+ ns1.setMulti({ key1: 'a', key2: 'b' }),
35
+ ns2.setMulti({ key1: 'c', key2: 'd' }),
36
+ redis.setMulti({ key1: 'e', key2: 'f' }),
37
+ ])
38
+ const gotMany = await Promise.all([
39
+ ns1.getMulti(['key1', 'key2']),
40
+ ns2.getMulti(['key1', 'key2']),
41
+ redis.getMulti(['key1', 'key2']),
42
+ ])
43
+ expect(gotMany[0]['key1']).toEqual('a')
44
+ expect(gotMany[0]['key2']).toEqual('b')
45
+ expect(gotMany[1]['key1']).toEqual('c')
46
+ expect(gotMany[1]['key2']).toEqual('d')
47
+ expect(gotMany[2]['key1']).toEqual('e')
48
+ expect(gotMany[2]['key2']).toEqual('f')
49
+ })
50
+
51
+ it('caches values when empty', async () => {
52
+ const vals = {
53
+ '1': 'a',
54
+ '2': 'b',
55
+ '3': 'c',
56
+ }
57
+ let hits = 0
58
+ const cache = new ReadThroughCache<string>(redis.withNamespace('test1'), {
59
+ staleTTL: 60000,
60
+ maxTTL: 60000,
61
+ fetchMethod: async (key) => {
62
+ hits++
63
+ return vals[key]
64
+ },
65
+ })
66
+ const got = await Promise.all([
67
+ cache.get('1'),
68
+ cache.get('2'),
69
+ cache.get('3'),
70
+ ])
71
+ expect(got[0]).toEqual('a')
72
+ expect(got[1]).toEqual('b')
73
+ expect(got[2]).toEqual('c')
74
+ expect(hits).toBe(3)
75
+
76
+ const refetched = await Promise.all([
77
+ cache.get('1'),
78
+ cache.get('2'),
79
+ cache.get('3'),
80
+ ])
81
+ expect(refetched[0]).toEqual('a')
82
+ expect(refetched[1]).toEqual('b')
83
+ expect(refetched[2]).toEqual('c')
84
+ expect(hits).toBe(3)
85
+ })
86
+
87
+ it('skips and refreshes cache when requested', async () => {
88
+ let val = 'a'
89
+ let hits = 0
90
+ const cache = new ReadThroughCache<string>(redis.withNamespace('test2'), {
91
+ staleTTL: 60000,
92
+ maxTTL: 60000,
93
+ fetchMethod: async () => {
94
+ hits++
95
+ return val
96
+ },
97
+ })
98
+
99
+ const try1 = await cache.get('1')
100
+ expect(try1).toEqual('a')
101
+ expect(hits).toBe(1)
102
+
103
+ val = 'b'
104
+
105
+ const try2 = await cache.get('1')
106
+ expect(try2).toEqual('a')
107
+ expect(hits).toBe(1)
108
+
109
+ const try3 = await cache.get('1', { revalidate: true })
110
+ expect(try3).toEqual('b')
111
+ expect(hits).toBe(2)
112
+
113
+ const try4 = await cache.get('1')
114
+ expect(try4).toEqual('b')
115
+ expect(hits).toBe(2)
116
+ })
117
+
118
+ it('accurately reports stale entries & refreshes the cache', async () => {
119
+ let val = 'a'
120
+ let hits = 0
121
+ const cache = new ReadThroughCache<string>(redis.withNamespace('test3'), {
122
+ staleTTL: 1,
123
+ maxTTL: 60000,
124
+ fetchMethod: async () => {
125
+ hits++
126
+ return val
127
+ },
128
+ })
129
+
130
+ const try1 = await cache.get('1')
131
+ expect(try1).toEqual('a')
132
+
133
+ await wait(5)
134
+
135
+ val = 'b'
136
+
137
+ const try2 = await cache.get('1')
138
+ // cache gives us stale value while it revalidates
139
+ expect(try2).toEqual('a')
140
+
141
+ await wait(5)
142
+
143
+ const try3 = await cache.get('1')
144
+ expect(try3).toEqual('b')
145
+ expect(hits).toEqual(3)
146
+ })
147
+
148
+ it('does not return expired dids & refreshes the cache', async () => {
149
+ let val = 'a'
150
+ let hits = 0
151
+ const cache = new ReadThroughCache<string>(redis.withNamespace('test4'), {
152
+ staleTTL: 0,
153
+ maxTTL: 1,
154
+ fetchMethod: async () => {
155
+ hits++
156
+ return val
157
+ },
158
+ })
159
+
160
+ const try1 = await cache.get('1')
161
+ expect(try1).toEqual('a')
162
+
163
+ await wait(5)
164
+
165
+ val = 'b'
166
+
167
+ const try2 = await cache.get('1')
168
+ expect(try2).toEqual('b')
169
+ expect(hits).toBe(2)
170
+ })
171
+
172
+ it('caches negative values', async () => {
173
+ let val: string | null = null
174
+ let hits = 0
175
+ const cache = new ReadThroughCache<string>(redis.withNamespace('test5'), {
176
+ staleTTL: 60000,
177
+ maxTTL: 60000,
178
+ fetchMethod: async () => {
179
+ hits++
180
+ return val
181
+ },
182
+ })
183
+
184
+ const try1 = await cache.get('1')
185
+ expect(try1).toEqual(null)
186
+ expect(hits).toBe(1)
187
+
188
+ val = 'b'
189
+
190
+ const try2 = await cache.get('1')
191
+ // returns cached negative value
192
+ expect(try2).toEqual(null)
193
+ expect(hits).toBe(1)
194
+
195
+ const try3 = await cache.get('1', { revalidate: true })
196
+ expect(try3).toEqual('b')
197
+ expect(hits).toEqual(2)
198
+
199
+ const try4 = await cache.get('1')
200
+ expect(try4).toEqual('b')
201
+ expect(hits).toEqual(2)
202
+ })
203
+
204
+ it('times out and fails open', async () => {
205
+ let val = 'a'
206
+ let hits = 0
207
+ const cache = new ReadThroughCache<string>(redis.withNamespace('test6'), {
208
+ staleTTL: 60000,
209
+ maxTTL: 60000,
210
+ fetchMethod: async () => {
211
+ hits++
212
+ return val
213
+ },
214
+ })
215
+
216
+ const try1 = await cache.get('1')
217
+ expect(try1).toEqual('a')
218
+
219
+ const orig = cache.redis.driver.get
220
+ cache.redis.driver.get = async (key) => {
221
+ await wait(600)
222
+ return orig(key)
223
+ }
224
+
225
+ val = 'b'
226
+
227
+ const try2 = await cache.get('1')
228
+ expect(try2).toEqual('b')
229
+ expect(hits).toBe(2)
230
+ })
231
+ })
@@ -103,6 +103,8 @@ export default async (sc: SeedClient, users = true) => {
103
103
  'tests/sample-img/key-landscape-small.jpg',
104
104
  'image/jpeg',
105
105
  )
106
+ // must ensure ordering of replies in indexing
107
+ await sc.network.processAll()
106
108
  await sc.reply(
107
109
  bob,
108
110
  sc.posts[alice][1].ref,
@@ -117,6 +119,7 @@ export default async (sc: SeedClient, users = true) => {
117
119
  sc.posts[alice][1].ref,
118
120
  replies.carol[0],
119
121
  )
122
+ await sc.network.processAll()
120
123
  const alicesReplyToBob = await sc.reply(
121
124
  alice,
122
125
  sc.posts[alice][1].ref,
@@ -1,7 +1,6 @@
1
1
  import AtpAgent from '@atproto/api'
2
2
  import { TestNetwork, SeedClient } from '@atproto/dev-env'
3
3
  import { CommitData } from '@atproto/repo'
4
- import { RepoService } from '@atproto/pds/src/services/repo'
5
4
  import { PreparedWrite } from '@atproto/pds/src/repo'
6
5
  import * as sequencer from '@atproto/pds/src/sequencer'
7
6
  import { cborDecode, cborEncode } from '@atproto/common'
@@ -84,9 +83,8 @@ describe('sync', () => {
84
83
 
85
84
  it('indexes actor when commit is unprocessable.', async () => {
86
85
  // mock sequencing to create an unprocessable commit event
87
- const afterWriteProcessingOriginal =
88
- RepoService.prototype.afterWriteProcessing
89
- RepoService.prototype.afterWriteProcessing = async function (
86
+ const sequenceCommitOrig = network.pds.ctx.sequencer.sequenceCommit
87
+ network.pds.ctx.sequencer.sequenceCommit = async function (
90
88
  did: string,
91
89
  commitData: CommitData,
92
90
  writes: PreparedWrite[],
@@ -95,7 +93,7 @@ describe('sync', () => {
95
93
  const evt = cborDecode(seqEvt.event) as sequencer.CommitEvt
96
94
  evt.blocks = new Uint8Array() // bad blocks
97
95
  seqEvt.event = cborEncode(evt)
98
- await sequencer.sequenceEvt(this.db, seqEvt)
96
+ await network.pds.ctx.sequencer.sequenceEvt(seqEvt)
99
97
  }
100
98
  // create account and index the initial commit event
101
99
  await sc.createAccount('jack', {
@@ -103,12 +101,11 @@ describe('sync', () => {
103
101
  email: 'jack@test.com',
104
102
  password: 'password',
105
103
  })
106
- await network.pds.ctx.sequencerLeader?.isCaughtUp()
107
104
  await network.processAll()
108
105
  // confirm jack was indexed as an actor despite the bad event
109
106
  const actors = await dumpTable(ctx.db.getPrimary(), 'actor', ['did'])
110
107
  expect(actors.map((a) => a.handle)).toContain('jack.test')
111
- RepoService.prototype.afterWriteProcessing = afterWriteProcessingOriginal
108
+ network.pds.ctx.sequencer.sequenceCommit = sequenceCommitOrig
112
109
  })
113
110
 
114
111
  async function updateProfile(
@@ -126,9 +126,6 @@ Object {
126
126
  "uri": "record(0)",
127
127
  "viewer": Object {},
128
128
  },
129
- "viewer": Object {
130
- "canReply": true,
131
- },
132
129
  },
133
130
  }
134
131
  `;
@@ -204,9 +201,6 @@ Object {
204
201
  "viewer": Object {},
205
202
  },
206
203
  "replies": Array [],
207
- "viewer": Object {
208
- "canReply": true,
209
- },
210
204
  },
211
205
  }
212
206
  `;
@@ -288,9 +282,6 @@ Object {
288
282
  "uri": "record(7)",
289
283
  },
290
284
  ],
291
- "viewer": Object {
292
- "canReply": true,
293
- },
294
285
  },
295
286
  }
296
287
  `;
@@ -498,6 +489,7 @@ Object {
498
489
  "muted": false,
499
490
  },
500
491
  },
492
+ "uri": "record(4)",
501
493
  },
502
494
  Object {
503
495
  "subject": Object {
@@ -522,6 +514,7 @@ Object {
522
514
  "muted": false,
523
515
  },
524
516
  },
517
+ "uri": "record(5)",
525
518
  },
526
519
  Object {
527
520
  "subject": Object {
@@ -550,6 +543,7 @@ Object {
550
543
  "muted": false,
551
544
  },
552
545
  },
546
+ "uri": "record(6)",
553
547
  },
554
548
  ],
555
549
  "list": Object {
@@ -126,9 +126,6 @@ Object {
126
126
  "uri": "record(0)",
127
127
  "viewer": Object {},
128
128
  },
129
- "viewer": Object {
130
- "canReply": true,
131
- },
132
129
  },
133
130
  }
134
131
  `;
@@ -204,9 +201,6 @@ Object {
204
201
  "viewer": Object {},
205
202
  },
206
203
  "replies": Array [],
207
- "viewer": Object {
208
- "canReply": true,
209
- },
210
204
  },
211
205
  }
212
206
  `;
@@ -359,9 +353,6 @@ Object {
359
353
  },
360
354
  },
361
355
  ],
362
- "viewer": Object {
363
- "canReply": true,
364
- },
365
356
  },
366
357
  }
367
358
  `;
@@ -292,9 +292,6 @@ Object {
292
292
  },
293
293
  },
294
294
  ],
295
- "viewer": Object {
296
- "canReply": true,
297
- },
298
295
  }
299
296
  `;
300
297
 
@@ -498,6 +495,7 @@ Object {
498
495
  "muted": false,
499
496
  },
500
497
  },
498
+ "uri": "record(3)",
501
499
  },
502
500
  Object {
503
501
  "subject": Object {
@@ -506,7 +504,7 @@ Object {
506
504
  "labels": Array [],
507
505
  "viewer": Object {
508
506
  "blockedBy": false,
509
- "followedBy": "record(3)",
507
+ "followedBy": "record(5)",
510
508
  "muted": true,
511
509
  "mutedByList": Object {
512
510
  "avatar": "https://bsky.public.url/img/avatar/plain/user(0)/cids(1)@jpeg",
@@ -521,6 +519,7 @@ Object {
521
519
  },
522
520
  },
523
521
  },
522
+ "uri": "record(4)",
524
523
  },
525
524
  Object {
526
525
  "subject": Object {
@@ -533,7 +532,7 @@ Object {
533
532
  "labels": Array [],
534
533
  "viewer": Object {
535
534
  "blockedBy": false,
536
- "following": "record(4)",
535
+ "following": "record(7)",
537
536
  "muted": true,
538
537
  "mutedByList": Object {
539
538
  "avatar": "https://bsky.public.url/img/avatar/plain/user(0)/cids(1)@jpeg",
@@ -548,6 +547,7 @@ Object {
548
547
  },
549
548
  },
550
549
  },
550
+ "uri": "record(6)",
551
551
  },
552
552
  ],
553
553
  "list": Object {
@@ -269,8 +269,5 @@ Object {
269
269
  },
270
270
  },
271
271
  ],
272
- "viewer": Object {
273
- "canReply": true,
274
- },
275
272
  }
276
273
  `;
@@ -195,9 +195,6 @@ Object {
195
195
  },
196
196
  },
197
197
  "replies": Array [],
198
- "viewer": Object {
199
- "canReply": true,
200
- },
201
198
  }
202
199
  `;
203
200
 
@@ -437,9 +434,6 @@ Object {
437
434
  ],
438
435
  },
439
436
  ],
440
- "viewer": Object {
441
- "canReply": true,
442
- },
443
437
  }
444
438
  `;
445
439
 
@@ -615,9 +609,6 @@ Object {
615
609
  },
616
610
  },
617
611
  ],
618
- "viewer": Object {
619
- "canReply": true,
620
- },
621
612
  }
622
613
  `;
623
614
 
@@ -771,9 +762,6 @@ Object {
771
762
  ],
772
763
  },
773
764
  ],
774
- "viewer": Object {
775
- "canReply": true,
776
- },
777
765
  }
778
766
  `;
779
767
 
@@ -826,9 +814,6 @@ Object {
826
814
  "viewer": Object {},
827
815
  },
828
816
  "replies": Array [],
829
- "viewer": Object {
830
- "canReply": true,
831
- },
832
817
  }
833
818
  `;
834
819
 
@@ -896,9 +881,6 @@ Object {
896
881
  "viewer": Object {},
897
882
  },
898
883
  "replies": Array [],
899
- "viewer": Object {
900
- "canReply": true,
901
- },
902
884
  }
903
885
  `;
904
886
 
@@ -968,9 +950,6 @@ Object {
968
950
  },
969
951
  },
970
952
  "replies": Array [],
971
- "viewer": Object {
972
- "canReply": true,
973
- },
974
953
  }
975
954
  `;
976
955
 
@@ -1040,9 +1019,6 @@ Object {
1040
1019
  },
1041
1020
  },
1042
1021
  "replies": Array [],
1043
- "viewer": Object {
1044
- "canReply": true,
1045
- },
1046
1022
  }
1047
1023
  `;
1048
1024
 
@@ -1243,9 +1219,6 @@ Object {
1243
1219
  ],
1244
1220
  },
1245
1221
  ],
1246
- "viewer": Object {
1247
- "canReply": true,
1248
- },
1249
1222
  }
1250
1223
  `;
1251
1224
 
@@ -1384,8 +1357,5 @@ Object {
1384
1357
  "replies": Array [],
1385
1358
  },
1386
1359
  ],
1387
- "viewer": Object {
1388
- "canReply": true,
1389
- },
1390
1360
  }
1391
1361
  `;
@@ -1,7 +1,6 @@
1
1
  import AtpAgent from '@atproto/api'
2
2
  import { wait } from '@atproto/common'
3
3
  import { TestNetwork, SeedClient } from '@atproto/dev-env'
4
- import { TAKEDOWN } from '@atproto/api/src/client/types/com/atproto/admin/defs'
5
4
  import { forSnapshot, paginateAll, stripViewer } from '../_util'
6
5
  import usersBulkSeed from '../seeds/users-bulk'
7
6
 
@@ -240,9 +239,9 @@ describe.skip('pds actor search views', () => {
240
239
  })
241
240
 
242
241
  it('search blocks by actor takedown', async () => {
243
- await agent.api.com.atproto.admin.takeModerationAction(
242
+ await agent.api.com.atproto.admin.emitModerationEvent(
244
243
  {
245
- action: TAKEDOWN,
244
+ event: { $type: 'com.atproto.admin.defs#modEventTakedown' },
246
245
  subject: {
247
246
  $type: 'com.atproto.admin.defs#repoRef',
248
247
  did: sc.dids['cara-wiegand69.test'],