From 085bc87954769f2d71f3f7f4fb813b5d820def5c Mon Sep 17 00:00:00 2001 From: dholms Date: Tue, 30 Jan 2024 17:06:42 -0600 Subject: [PATCH 1/7] build branch --- .github/workflows/build-and-push-pds-aws.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build-and-push-pds-aws.yaml b/.github/workflows/build-and-push-pds-aws.yaml index 097f782d88e..959dbfd7e94 100644 --- a/.github/workflows/build-and-push-pds-aws.yaml +++ b/.github/workflows/build-and-push-pds-aws.yaml @@ -3,6 +3,7 @@ on: push: branches: - main + - signup-queueing-take2 env: REGISTRY: ${{ secrets.AWS_ECR_REGISTRY_USEAST2_PACKAGES_REGISTRY }} USERNAME: ${{ secrets.AWS_ECR_REGISTRY_USEAST2_PACKAGES_USERNAME }} From 5f830cb585713e405c1aca92d24a50fe359cf49a Mon Sep 17 00:00:00 2001 From: dholms Date: Tue, 30 Jan 2024 17:21:34 -0600 Subject: [PATCH 2/7] run activator --- packages/pds/src/index.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/pds/src/index.ts b/packages/pds/src/index.ts index 0d7e4fbbc4b..818584bb03a 100644 --- a/packages/pds/src/index.ts +++ b/packages/pds/src/index.ts @@ -164,6 +164,7 @@ export class PDS { await this.ctx.db.startListeningToChannels() await this.ctx.runtimeFlags.start() await this.ctx.signupLimiter.start() + await this.ctx.signupActivator.run() const server = this.app.listen(this.ctx.cfg.service.port) this.server = server this.server.keepAliveTimeout = 90000 @@ -175,6 +176,7 @@ export class PDS { async destroy(): Promise { await this.ctx.runtimeFlags.destroy() await this.ctx.signupLimiter.destroy() + await this.ctx.signupActivator.run() await this.ctx.sequencerLeader?.destroy() await this.terminator?.terminate() await this.ctx.backgroundQueue.destroy() From 64ff83aa11af5de6acfb9e715dbcddd87a7c0e5e Mon Sep 17 00:00:00 2001 From: dholms Date: Tue, 30 Jan 2024 17:22:09 -0600 Subject: [PATCH 3/7] dont run activator in dev-env --- packages/dev-env/src/pds.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/dev-env/src/pds.ts b/packages/dev-env/src/pds.ts index e9b7cd7c692..979f40e8048 100644 --- a/packages/dev-env/src/pds.ts +++ b/packages/dev-env/src/pds.ts @@ -57,6 +57,7 @@ export class TestPds { const secrets = pds.envToSecrets(env) const server = await pds.PDS.create(cfg, secrets) + await server.ctx.signupActivator.destroy() // Separate migration db on postgres in case migration changes some // connection state that we need in the tests, e.g. "alter database ... set ..." From e7bd3ff97d73ff0b7c1b850ee6389fb388e568bc Mon Sep 17 00:00:00 2001 From: dholms Date: Tue, 30 Jan 2024 17:36:51 -0600 Subject: [PATCH 4/7] run activator async --- packages/pds/src/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/pds/src/index.ts b/packages/pds/src/index.ts index 818584bb03a..b384c165e40 100644 --- a/packages/pds/src/index.ts +++ b/packages/pds/src/index.ts @@ -164,7 +164,7 @@ export class PDS { await this.ctx.db.startListeningToChannels() await this.ctx.runtimeFlags.start() await this.ctx.signupLimiter.start() - await this.ctx.signupActivator.run() + this.ctx.signupActivator.run() const server = this.app.listen(this.ctx.cfg.service.port) this.server = server this.server.keepAliveTimeout = 90000 From 258734b51125a6827fe763a4b38e67d3d57cf4f2 Mon Sep 17 00:00:00 2001 From: dholms Date: Tue, 30 Jan 2024 18:07:02 -0600 Subject: [PATCH 5/7] round estimated time --- packages/pds/src/api/com/atproto/temp/checkSignupQueue.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/pds/src/api/com/atproto/temp/checkSignupQueue.ts b/packages/pds/src/api/com/atproto/temp/checkSignupQueue.ts index cb58726b9a7..2a94c4fa558 100644 --- a/packages/pds/src/api/com/atproto/temp/checkSignupQueue.ts +++ b/packages/pds/src/api/com/atproto/temp/checkSignupQueue.ts @@ -32,9 +32,10 @@ export default function (server: Server, ctx: AppContext) { !limiterStatus.disableSignups && limiterStatus.accountsInPeriod > 0 ) { - estimatedTimeMs = + estimatedTimeMs = Math.ceil( (placeInQueue * limiterStatus.periodMs) / - limiterStatus.accountsInPeriod + limiterStatus.accountsInPeriod, + ) } return { From 6c0571d5029271400a822c4a0720d73a96a04dbc Mon Sep 17 00:00:00 2001 From: dholms Date: Tue, 30 Jan 2024 18:48:02 -0600 Subject: [PATCH 6/7] logging --- packages/pds/src/signup-queue/activator.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/pds/src/signup-queue/activator.ts b/packages/pds/src/signup-queue/activator.ts index 99cd05c1e4e..71842243725 100644 --- a/packages/pds/src/signup-queue/activator.ts +++ b/packages/pds/src/signup-queue/activator.ts @@ -79,8 +79,10 @@ export class SignupActivator { async activateBatch() { const status = await getQueueStatus(this.db) - if (status.disableSignups) return const toAdmit = status.periodAllowance - status.accountsInPeriod + log.info({ ...status, toAdmit }, 'activating accounts') + + if (status.disableSignups) return if (toAdmit < 1) return const activatedAt = new Date().toISOString() From c1bbd68f57a6830eb44d5fc72490c5b9740d72e0 Mon Sep 17 00:00:00 2001 From: dholms Date: Tue, 30 Jan 2024 19:10:11 -0600 Subject: [PATCH 7/7] real time limiter --- .../api/com/atproto/server/createAccount.ts | 2 +- .../api/com/atproto/temp/checkSignupQueue.ts | 18 ++++++++---------- packages/pds/src/signup-queue/limiter.ts | 19 ++++++++++++------- 3 files changed, 21 insertions(+), 18 deletions(-) diff --git a/packages/pds/src/api/com/atproto/server/createAccount.ts b/packages/pds/src/api/com/atproto/server/createAccount.ts index 1b322f76304..3064e6dd541 100644 --- a/packages/pds/src/api/com/atproto/server/createAccount.ts +++ b/packages/pds/src/api/com/atproto/server/createAccount.ts @@ -28,7 +28,7 @@ export default function (server: Server, ctx: AppContext) { points: 100, }, handler: async ({ input, req }) => { - const hasAvailability = ctx.signupLimiter.hasAvailability() + const hasAvailability = await ctx.signupLimiter.hasAvailability() const { did, diff --git a/packages/pds/src/api/com/atproto/temp/checkSignupQueue.ts b/packages/pds/src/api/com/atproto/temp/checkSignupQueue.ts index 2a94c4fa558..a71fe5d1dae 100644 --- a/packages/pds/src/api/com/atproto/temp/checkSignupQueue.ts +++ b/packages/pds/src/api/com/atproto/temp/checkSignupQueue.ts @@ -25,17 +25,15 @@ export default function (server: Server, ctx: AppContext) { placeInQueue = res?.count } - const limiterStatus = ctx.signupLimiter.status + const limiter = ctx.signupLimiter let estimatedTimeMs: number | undefined - if ( - placeInQueue && - !limiterStatus.disableSignups && - limiterStatus.accountsInPeriod > 0 - ) { - estimatedTimeMs = Math.ceil( - (placeInQueue * limiterStatus.periodMs) / - limiterStatus.accountsInPeriod, - ) + if (placeInQueue && !limiter.flags.disableSignups) { + const accountsInPeriod = await limiter.accountsInPeriod() + if (accountsInPeriod > 0) { + estimatedTimeMs = Math.ceil( + (placeInQueue * limiter.flags.periodMs) / accountsInPeriod, + ) + } } return { diff --git a/packages/pds/src/signup-queue/limiter.ts b/packages/pds/src/signup-queue/limiter.ts index 934d04a73da..d8a3945931e 100644 --- a/packages/pds/src/signup-queue/limiter.ts +++ b/packages/pds/src/signup-queue/limiter.ts @@ -1,19 +1,20 @@ import { SECOND } from '@atproto/common' import { limiterLogger as log } from '../logger' import Database from '../db' -import { LimiterStatus, getQueueStatus } from './util' +import { LimiterFlags, getAccountsInPeriod, getQueueStatus } from './util' export class SignupLimiter { destroyed = false promise: Promise = Promise.resolve() timer: NodeJS.Timer | undefined - status: LimiterStatus + flags: LimiterFlags constructor(private db: Database) {} - hasAvailability(): boolean { - if (this.status.disableSignups) return false - return this.status.accountsInPeriod < this.status.periodAllowance + async hasAvailability(): Promise { + if (this.flags.disableSignups) return false + const accountsInPeriod = await this.accountsInPeriod() + return accountsInPeriod < this.flags.periodAllowance } async start() { @@ -38,9 +39,13 @@ export class SignupLimiter { await this.promise } + async accountsInPeriod(): Promise { + return getAccountsInPeriod(this.db, this.flags.periodMs) + } + async refresh() { - this.status = await getQueueStatus(this.db) + this.flags = await getQueueStatus(this.db) - log.info({ ...this.status }, 'limiter refresh') + log.info({ ...this.flags }, 'limiter refresh') } }