Skip to content

Commit 5f8f094

Browse files
authored
Entryway: non-transactional createAccount (#2109)
make create account non transactional
1 parent c7d95e9 commit 5f8f094

File tree

1 file changed

+46
-23
lines changed

1 file changed

+46
-23
lines changed

packages/pds/src/api/com/atproto/server/createAccount.ts

+46-23
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import Database from '../../../../db'
2020
import { didDocForSession } from './util'
2121
import { getPdsEndpoint } from '../../../../pds-agents'
2222
import { isThisPds } from '../../../proxy'
23+
import { dbLogger as log } from '../../../../logger'
2324

2425
export default function (server: Server, ctx: AppContext) {
2526
server.com.atproto.server.createAccount({
@@ -96,19 +97,6 @@ export default function (server: Server, ctx: AppContext) {
9697
throw err
9798
}
9899

99-
// Generate a real did with PLC
100-
if (plcOp && !entrywayAssignedPds) {
101-
try {
102-
await ctx.plcClient.sendOperation(did, plcOp)
103-
} catch (err) {
104-
req.log.error(
105-
{ didKey: ctx.plcRotationKey.did(), handle },
106-
'failed to create did:plc',
107-
)
108-
throw err
109-
}
110-
}
111-
112100
// insert invite code use
113101
if (ctx.cfg.invites.required && inviteCode) {
114102
await ensureCodeIsAvailable(dbTxn, inviteCode, true)
@@ -132,6 +120,10 @@ export default function (server: Server, ctx: AppContext) {
132120
.execute()
133121
}
134122

123+
if (!entrywayAssignedPds) {
124+
await repoTxn.createRepo(did, [], now)
125+
}
126+
135127
const { access, refresh } = await ctx.services
136128
.auth(dbTxn)
137129
.createSession({
@@ -140,6 +132,15 @@ export default function (server: Server, ctx: AppContext) {
140132
appPasswordName: null,
141133
})
142134

135+
return {
136+
did,
137+
pdsDid: entrywayAssignedPds?.did ?? null,
138+
accessJwt: access,
139+
refreshJwt: refresh,
140+
}
141+
})
142+
143+
try {
143144
if (entrywayAssignedPds) {
144145
const agent = ctx.pdsAgents.get(entrywayAssignedPds.host)
145146
await agent.com.atproto.server.createAccount({
@@ -149,17 +150,21 @@ export default function (server: Server, ctx: AppContext) {
149150
recoveryKey: input.body.recoveryKey,
150151
})
151152
} else {
152-
// Setup repo root
153-
await repoTxn.createRepo(did, [], now)
154-
}
155-
156-
return {
157-
did,
158-
pdsDid: entrywayAssignedPds?.did ?? null,
159-
accessJwt: access,
160-
refreshJwt: refresh,
153+
assert(plcOp)
154+
try {
155+
await ctx.plcClient.sendOperation(did, plcOp)
156+
} catch (err) {
157+
req.log.error(
158+
{ didKey: ctx.plcRotationKey.did(), handle },
159+
'failed to create did:plc',
160+
)
161+
throw err
162+
}
161163
}
162-
})
164+
} catch (err) {
165+
await cleanupUncreatedAccount(ctx, did)
166+
throw err
167+
}
163168

164169
const didDoc = await didDocForSession(ctx, result)
165170

@@ -496,3 +501,21 @@ const randomIndexByWeight = (weights) => {
496501
const rand = Math.random() * sum
497502
return cumulative.findIndex((item) => item >= rand)
498503
}
504+
505+
const cleanupUncreatedAccount = async (
506+
ctx: AppContext,
507+
did: string,
508+
tries = 0,
509+
) => {
510+
if (tries > 3) return
511+
try {
512+
await Promise.all([
513+
ctx.services.account(ctx.db).deleteAccount(did),
514+
ctx.services.record(ctx.db).deleteForActor(did),
515+
ctx.services.repo(ctx.db).deleteRepo(did),
516+
])
517+
} catch (err) {
518+
log.error({ err, did, tries }, 'failed to clean up partially created user')
519+
return cleanupUncreatedAccount(ctx, did, tries + 1)
520+
}
521+
}

0 commit comments

Comments
 (0)