Skip to content

Commit

Permalink
Logical separation of app view (bluesky-social#572)
Browse files Browse the repository at this point in the history
* Separate app.bsky methods out into app view

* Fix websocket issue while splitting-out app view

* Start organizing app-view tables out of pds

* Move feed service, getTimeline, vote table into app-view

* Move record processing/indexing logically out of pds and into app-view

* Pull actor service functionality into app-view

* Factor app-view user functionality out of pds, replace actor w/ account service

* Tidy
  • Loading branch information
devinivy authored Feb 24, 2023
1 parent fea90cb commit 8826ada
Show file tree
Hide file tree
Showing 78 changed files with 705 additions and 433 deletions.
8 changes: 6 additions & 2 deletions packages/pds/src/api/app/bsky/actor/updateProfile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export default function (server: Server, ctx: AppContext) {
const uri = AtUri.make(did, profileNsid, 'self')
const current = (await recordTxn.getRecord(uri, null, true))?.value
if (current) {
if (!recordTxn.records.profile.matchesSchema(current)) {
if (!isProfile(current)) {
// @TODO need a way to get a profile out of a broken state
throw new InvalidRequestError('could not parse current profile')
}
Expand All @@ -54,7 +54,7 @@ export default function (server: Server, ctx: AppContext) {
}
}
updated = common.noUndefinedVals(updated)
if (!recordTxn.records.profile.matchesSchema(updated)) {
if (!isProfile(updated)) {
throw new InvalidRequestError(
'requested updates do not produce a valid profile doc',
)
Expand Down Expand Up @@ -125,3 +125,7 @@ function unsetIfNull<T>(x: T | null | undefined, y?: T): T | undefined {
if (x === null) return undefined
return x ?? y
}

function isProfile(obj: unknown): obj is Profile.Record {
return Profile.validateRecord(obj).success
}
7 changes: 4 additions & 3 deletions packages/pds/src/api/app/bsky/graph/getMutes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,14 @@ export default function (server: Server, ctx: AppContext) {

const mutesRes = await mutesReq.execute()

// @NOTE calling into app-view, will eventually be replaced
const actorService = services.appView.actor(db)

return {
encoding: 'application/json',
body: {
cursor: keyset.packFromResult(mutesRes),
mutes: await services
.actor(db)
.views.actorWithInfo(mutesRes, requester),
mutes: await actorService.views.actorWithInfo(mutesRes, requester),
},
}
},
Expand Down
6 changes: 3 additions & 3 deletions packages/pds/src/api/app/bsky/graph/mute.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Server } from '../../../../lexicon'
import { InvalidRequestError } from '@atproto/xrpc-server'
import { Server } from '../../../../lexicon'
import AppContext from '../../../../context'

export default function (server: Server, ctx: AppContext) {
Expand All @@ -10,15 +10,15 @@ export default function (server: Server, ctx: AppContext) {
const requester = auth.credentials.did
const { db, services } = ctx

const subject = await services.actor(db).getUser(user)
const subject = await services.account(db).getUser(user)
if (!subject) {
throw new InvalidRequestError(`Actor not found: ${user}`)
}
if (subject.did === requester) {
throw new InvalidRequestError('Cannot mute oneself')
}

await services.actor(db).mute({
await services.account(db).mute({
did: subject.did,
mutedByDid: requester,
})
Expand Down
4 changes: 2 additions & 2 deletions packages/pds/src/api/app/bsky/graph/unmute.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ export default function (server: Server, ctx: AppContext) {
const requester = auth.credentials.did
const { db, services } = ctx

const subject = await services.actor(db).getUser(user)
const subject = await services.account(db).getUser(user)
if (!subject) {
throw new InvalidRequestError(`Actor not found: ${user}`)
}

await services.actor(db).unmute({
await services.account(db).unmute({
did: subject.did,
mutedByDid: requester,
})
Expand Down
24 changes: 0 additions & 24 deletions packages/pds/src/api/app/bsky/index.ts
Original file line number Diff line number Diff line change
@@ -1,45 +1,21 @@
import { Server } from '../../../lexicon'
import AppContext from '../../../context'
import getTimeline from './feed/getTimeline'
import getAuthorFeed from './feed/getAuthorFeed'
import getVotes from './feed/getVotes'
import setVote from './feed/setVote'
import getPostThread from './feed/getPostThread'
import getProfile from './actor/getProfile'
import getProfiles from './actor/getProfiles'
import updateProfile from './actor/updateProfile'
import getRepostedBy from './feed/getRepostedBy'
import getFollowers from './graph/getFollowers'
import getFollows from './graph/getFollows'
import mute from './graph/mute'
import unmute from './graph/unmute'
import getMutes from './graph/getMutes'
import getUsersSearch from './actor/search'
import getUsersTypeahead from './actor/searchTypeahead'
import getNotifications from './notification/list'
import getNotificationCount from './notification/getCount'
import getSuggestions from './actor/getSuggestions'
import postNotificationsSeen from './notification/updateSeen'

export default function (server: Server, ctx: AppContext) {
getTimeline(server, ctx)
getAuthorFeed(server, ctx)
getVotes(server, ctx)
setVote(server, ctx)
getPostThread(server, ctx)
getProfile(server, ctx)
getProfiles(server, ctx)
updateProfile(server, ctx)
getRepostedBy(server, ctx)
getFollowers(server, ctx)
getFollows(server, ctx)
mute(server, ctx)
unmute(server, ctx)
getMutes(server, ctx)
getUsersSearch(server, ctx)
getUsersTypeahead(server, ctx)
getNotifications(server, ctx)
getNotificationCount(server, ctx)
getSuggestions(server, ctx)
postNotificationsSeen(server, ctx)
}
3 changes: 2 additions & 1 deletion packages/pds/src/api/app/bsky/notification/list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,8 @@ export default function (server: Server, ctx: AppContext) {
throw new InvalidRequestError(`Could not find user: ${requester}`)
}

const actorService = ctx.services.actor(ctx.db)
// @NOTE calling into app-view, will eventually be replaced
const actorService = ctx.services.appView.actor(ctx.db)
const authors = await actorService.views.actorWithInfo(
notifs.map((notif) => ({
did: notif.authorDid,
Expand Down
2 changes: 1 addition & 1 deletion packages/pds/src/api/app/bsky/notification/updateSeen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export default function (server: Server, ctx: AppContext) {
throw new InvalidRequestError('Invalid date')
}

const user = await ctx.services.actor(ctx.db).getUser(requester)
const user = await ctx.services.account(ctx.db).getUser(requester)
if (!user) {
throw new InvalidRequestError(`Could not find user: ${requester}`)
}
Expand Down
4 changes: 2 additions & 2 deletions packages/pds/src/api/com/atproto/account/create.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { Server, APP_BSKY_SYSTEM } from '../../../../lexicon'
import { countAll } from '../../../../db/util'
import * as lex from '../../../../lexicon/lexicons'
import * as repo from '../../../../repo'
import { UserAlreadyExistsError } from '../../../../services/actor'
import { UserAlreadyExistsError } from '../../../../services/account'
import AppContext from '../../../../context'

export default function (server: Server, ctx: AppContext) {
Expand All @@ -30,7 +30,7 @@ export default function (server: Server, ctx: AppContext) {
const now = new Date().toISOString()

const result = await ctx.db.transaction(async (dbTxn) => {
const actorTxn = ctx.services.actor(dbTxn)
const actorTxn = ctx.services.account(dbTxn)
const repoTxn = ctx.services.repo(dbTxn)
if (ctx.cfg.inviteRequired) {
if (!inviteCode) {
Expand Down
4 changes: 2 additions & 2 deletions packages/pds/src/api/com/atproto/account/delete.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export default function (server: Server, ctx: AppContext) {
server.com.atproto.account.delete(async ({ input }) => {
const { did, password, token } = input.body
const validPass = await ctx.services
.actor(ctx.db)
.account(ctx.db)
.verifyUserPassword(did, password)
if (!validPass) {
throw new AuthRequiredError('Invalid did or password')
Expand Down Expand Up @@ -41,7 +41,7 @@ export default function (server: Server, ctx: AppContext) {
await removeDeleteToken(dbTxn, did)
await ctx.services.record(dbTxn).deleteForUser(did)
await ctx.services.repo(dbTxn).deleteRepo(did)
await ctx.services.actor(dbTxn).deleteUser(did)
await ctx.services.account(dbTxn).deleteUser(did)
})
})
}
Expand Down
2 changes: 1 addition & 1 deletion packages/pds/src/api/com/atproto/account/requestDelete.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export default function (server: Server, ctx: AppContext) {
const did = auth.credentials.did
const token = getSixDigitToken()
const requestedAt = new Date().toISOString()
const user = await ctx.services.actor(ctx.db).getUser(did)
const user = await ctx.services.account(ctx.db).getUser(did)
if (!user) {
throw new InvalidRequestError('user not found')
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export default function (server: Server, ctx: AppContext) {
server.com.atproto.account.requestPasswordReset(async ({ input }) => {
const email = input.body.email.toLowerCase()

const user = await ctx.services.actor(ctx.db).getUserByEmail(email)
const user = await ctx.services.account(ctx.db).getUserByEmail(email)

if (user) {
const token = getSixDigitToken()
Expand Down
2 changes: 1 addition & 1 deletion packages/pds/src/api/com/atproto/account/resetPassword.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export default function (server: Server, ctx: AppContext) {
await ctx.db.transaction(async (dbTxn) => {
await unsetResetToken(dbTxn, tokenInfo.did)
await ctx.services
.actor(dbTxn)
.account(dbTxn)
.updateUserPassword(tokenInfo.did, password)
})
})
Expand Down
2 changes: 1 addition & 1 deletion packages/pds/src/api/com/atproto/admin/getRepo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export default function (server: Server, ctx: AppContext) {
handler: async ({ params }) => {
const { db, services } = ctx
const { did } = params
const result = await services.actor(db).getUser(did, true)
const result = await services.account(db).getUser(did, true)
if (!result) throw new InvalidRequestError('Repo not found')
return {
encoding: 'application/json',
Expand Down
6 changes: 3 additions & 3 deletions packages/pds/src/api/com/atproto/admin/searchRepos.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Server } from '../../../../lexicon'
import AppContext from '../../../../context'
import { SearchKeyset } from '../../../../services/util/search'
import { sql } from 'kysely'
import { ListKeyset } from '../../../../services/actor'
import { ListKeyset } from '../../../../services/account'

export default function (server: Server, ctx: AppContext) {
server.com.atproto.admin.searchRepos({
Expand All @@ -14,7 +14,7 @@ export default function (server: Server, ctx: AppContext) {

if (!term) {
const results = await services
.actor(db)
.account(db)
.list({ limit, before, includeSoftDeleted: true })
const keyset = new ListKeyset(sql``, sql``)

Expand All @@ -28,7 +28,7 @@ export default function (server: Server, ctx: AppContext) {
}

const results = await services
.actor(db)
.account(db)
.search({ term, limit, before, includeSoftDeleted: true })
const keyset = new SearchKeyset(sql``, sql``)

Expand Down
6 changes: 3 additions & 3 deletions packages/pds/src/api/com/atproto/handle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { InvalidRequestError } from '@atproto/xrpc-server'
import * as handleLib from '@atproto/handle'
import { Server } from '../../../lexicon'
import AppContext from '../../../context'
import { UserAlreadyExistsError } from '../../../services/actor'
import { UserAlreadyExistsError } from '../../../services/account'
import { httpLogger as log } from '../../../logger'
import { XRPCError } from '@atproto/xrpc'

Expand All @@ -16,7 +16,7 @@ export default function (server: Server, ctx: AppContext) {
// self
did = ctx.cfg.serverDid
} else {
const user = await ctx.services.actor(ctx.db).getUser(handle, true)
const user = await ctx.services.account(ctx.db).getUser(handle, true)
if (user) {
did = user.did
} else {
Expand Down Expand Up @@ -80,7 +80,7 @@ export default function (server: Server, ctx: AppContext) {

await ctx.db.transaction(async (dbTxn) => {
try {
await ctx.services.actor(dbTxn).updateHandle(requester, handle)
await ctx.services.account(dbTxn).updateHandle(requester, handle)
} catch (err) {
if (err instanceof UserAlreadyExistsError) {
throw new InvalidRequestError(`Handle already taken: ${handle}`)
Expand Down
8 changes: 4 additions & 4 deletions packages/pds/src/api/com/atproto/repo.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { InvalidRequestError, AuthRequiredError } from '@atproto/xrpc-server'
import { AtUri } from '@atproto/uri'
import { WriteOpAction } from '@atproto/repo'
import * as didResolver from '@atproto/did-resolver'
import * as repo from '../../../repo'
import { Server } from '../../../lexicon'
Expand All @@ -9,13 +10,12 @@ import {
PreparedWrite,
} from '../../../repo'
import AppContext from '../../../context'
import { WriteOpAction } from '@atproto/repo'

export default function (server: Server, ctx: AppContext) {
server.com.atproto.repo.describe(async ({ params }) => {
const { user } = params

const userObj = await ctx.services.actor(ctx.db).getUser(user)
const userObj = await ctx.services.account(ctx.db).getUser(user)
if (userObj === null) {
throw new InvalidRequestError(`Could not find user: ${user}`)
}
Expand Down Expand Up @@ -49,7 +49,7 @@ export default function (server: Server, ctx: AppContext) {
server.com.atproto.repo.listRecords(async ({ params }) => {
const { user, collection, limit, before, after, reverse } = params

const did = await ctx.services.actor(ctx.db).getDidForActor(user)
const did = await ctx.services.account(ctx.db).getDidForActor(user)
if (!did) {
throw new InvalidRequestError(`Could not find user: ${user}`)
}
Expand Down Expand Up @@ -81,7 +81,7 @@ export default function (server: Server, ctx: AppContext) {
server.com.atproto.repo.getRecord(async ({ params }) => {
const { user, collection, rkey, cid } = params

const did = await ctx.services.actor(ctx.db).getDidForActor(user)
const did = await ctx.services.account(ctx.db).getDidForActor(user)
if (!did) {
throw new InvalidRequestError(`Could not find user: ${user}`)
}
Expand Down
6 changes: 3 additions & 3 deletions packages/pds/src/api/com/atproto/session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export default function (server: Server, ctx: AppContext) {
auth: ctx.accessVerifier,
handler: async ({ auth }) => {
const did = auth.credentials.did
const user = await ctx.services.actor(ctx.db).getUser(did)
const user = await ctx.services.account(ctx.db).getUser(did)
if (!user) {
throw new InvalidRequestError(
`Could not find user info for account: ${did}`,
Expand All @@ -30,7 +30,7 @@ export default function (server: Server, ctx: AppContext) {
''
).toLowerCase()
const authService = ctx.services.auth(ctx.db)
const actorService = ctx.services.actor(ctx.db)
const actorService = ctx.services.account(ctx.db)

const user = identifier.includes('@')
? await actorService.getUserByEmail(identifier, true)
Expand Down Expand Up @@ -72,7 +72,7 @@ export default function (server: Server, ctx: AppContext) {
auth: ctx.refreshVerifier,
handler: async ({ req, auth }) => {
const did = auth.credentials.did
const user = await ctx.services.actor(ctx.db).getUser(did, true)
const user = await ctx.services.account(ctx.db).getUser(did, true)
if (!user) {
throw new InvalidRequestError(
`Could not find user info for account: ${did}`,
Expand Down
6 changes: 2 additions & 4 deletions packages/pds/src/api/index.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
import { Options } from '@atproto/xrpc-server'
import { createServer } from '../lexicon'
import { Server } from '../lexicon'
import comAtproto from './com/atproto'
import appBsky from './app/bsky'
import AppContext from '../context'

export * as health from './health'

export default function (ctx: AppContext, options: Options) {
const server = createServer(options)
export default function (server: Server, ctx: AppContext) {
comAtproto(server, ctx)
appBsky(server, ctx)
return server
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Server } from '../../../../lexicon'
import { InvalidRequestError } from '@atproto/xrpc-server'
import { softDeleted } from '../../../../db/util'
import AppContext from '../../../../context'
import { Server } from '../../../../../lexicon'
import { softDeleted } from '../../../../../db/util'
import AppContext from '../../../../../context'

export default function (server: Server, ctx: AppContext) {
server.app.bsky.actor.getProfile({
Expand All @@ -10,7 +10,7 @@ export default function (server: Server, ctx: AppContext) {
const { actor } = params
const requester = auth.credentials.did
const { db, services } = ctx
const actorService = services.actor(db)
const actorService = services.appView.actor(db)

const user = await actorService.getUser(actor, true)

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Server } from '../../../../lexicon'
import AppContext from '../../../../context'
import { Server } from '../../../../../lexicon'
import AppContext from '../../../../../context'

export default function (server: Server, ctx: AppContext) {
server.app.bsky.actor.getProfiles({
Expand All @@ -8,7 +8,7 @@ export default function (server: Server, ctx: AppContext) {
const { actors } = params
const requester = auth.credentials.did
const { db, services } = ctx
const actorService = services.actor(db)
const actorService = services.appView.actor(db)

const users = await actorService.getUsers(actors)

Expand Down
Loading

0 comments on commit 8826ada

Please sign in to comment.