Skip to content

imp(limiter): notificaitons on project ban and unban#408

Merged
e11sy merged 33 commits intomasterfrom
notify-about-project-ban
Jun 4, 2025
Merged

imp(limiter): notificaitons on project ban and unban#408
e11sy merged 33 commits intomasterfrom
notify-about-project-ban

Conversation

@e11sy
Copy link
Copy Markdown
Member

@e11sy e11sy commented May 5, 2025

Workspaces Block / Unblock flow

Previous realisation

Limiter

  1. Regular - could block project if event limit reached
  2. Single - updates redis list to make data in redis consistent with mongo (blocks all projects that are in blocked workspaces in mongo)
    it could also block project in mongo by event limit and then update redis.

Important

Limiter can not unblock workspace in db if it is blocked because in report isBlocked: isAlreadyBlocked || shouldBeBlocked

Paymaster (everything in one flow)

  1. Blocks project in db if it has plan in month and three days after lastChargeDate
  2. Unblocks project if it is free and month passed

Important

Paymaster can not unblock workspace in db if it has tariff plan

API Cloudpayments

  1. On pay it changes the plan
 {
    tariffPlanId: this.tariffPlanId,
    billingPeriodEventsCount: 0,
    isBlocked: false,
    lastChargeDate: new Date(),
},

and then calls Limiter Single

Problems

  • isBlocked is inconsistent in redis and db until the moment Limiter is called (in case with manual db updates it could break smth)
  • Limiter rewrites the whole redis set each time regular check passes even if nothing is changed
  • Seems like a mess overall

Who can block?

Database Redis
Limiter, Paymaster Limiter

Who can unblock?

Database Redis
API Cloudpayments, Paymaster Limiter

Note

Limiter rewrites the whole set so we can't track which project was actually unblocked

New Block / Unblock flow

Limiter

  1. Handle block-workspace
  • If workspace is blocked in db - do nothing
  • Otherwise block in Redis and in Db
  1. Handle unblock-workspace
  • If workspace is unblocked in db - do nothing
  • Count events since last charge date - unblock if workspace fits in limits (unblock in Redis and in Db)
  1. Handle regular-workspaces-check
    For each workspace
  • If workspace is already blocked - do nothing
  • Count events since last charge date, ban if workspace does not fit in limits (block in Redis and in Db)

Paymaster

isBlocked never changes here

  1. Payed workspaces
  • If month and 3 days passed since last charge date - call Limiter Block
  • If it is time to pay and workspace has no subscriptionId - call Limiter Block
  • If it is not time to pay but workspace is blocked - call Limiter Unblock case for manual unblocking, recharge unneeded
  1. Free workspaces
  • If month passed since last charge date - recharge and call Limiter Unblock

API Cloudpayments note that this changes will be in a different repo

  • On pay recharge isBlocked never changes here
{
    tariffPlanId: this.tariffPlanId,
    billingPeriodEventsCount: 0,
    lastChargeDate: new Date(),
},

Results

Every Block and Unblock happens simultaneously in redis and mongo, and only Limiter controls it

All Workspaces are blocked by

  • Paymaster - by time
  • Limiter - by event count

All Workspaces are unblocked by

  • Cloudpayments - on payment
  • Paymaster - on regular check if could be unblocked by time and by events

Important

If you unblock workspace manually do not change isBlocked, just recharge
isBlocked should be fully controlled by Limiter

Free Workspaces are Unblocked

  • Paymaster - month after lastChargeDate

Additional

  • Added telegram util for reports sending, available for all workers
  • Moved mongo methods DbHelper in for limiter worker
  • yarn test:limiter add --runInBand because added new dbHelper.test.ts it connects to mongo repl set, so should be in same test pipeline with index.test.ts to avoid initialisation of mongo twice

Comment thread lib/utils/telegram.ts Outdated
Comment thread workers/limiter/src/index.ts Outdated
Comment thread workers/limiter/src/index.ts Outdated
Comment thread workers/limiter/src/dbHelper.ts
Comment thread workers/limiter/src/dbHelper.ts
@neSpecc neSpecc requested a review from Copilot May 17, 2025 16:33
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR refactors the workspace block/unblock flow to use explicit limiter events, centralizes database logic, and introduces Telegram-based reporting.

  • Adds block-workspace and unblock-workspace events to the Limiter worker with Telegram notifications.
  • Updates Paymaster to enqueue Limiter and Email tasks instead of modifying the database directly.
  • Extracts DB operations into DbHelper and adds a Telegram utility for sending reports; test suites are updated accordingly.

Reviewed Changes

Copilot reviewed 13 out of 13 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
workers/paymaster/src/index.ts Refactored Paymaster to enqueue limiter/unblock tasks via addTask
workers/paymaster/tests/index.test.ts Updated tests to spy on addTask calls and adjust queue names
workers/limiter/src/index.ts Implemented block-workspace/unblock-workspace handlers, Telegram reports, and regular checks
workers/limiter/src/dbHelper.ts Moved MongoDB operations into a new helper class
workers/limiter/types/reportData.ts Renamed report field isBlockedshouldBeBlockedByQuota
lib/utils/telegram.ts Added Telegram utility for sending reports via sendMessage
Comments suppressed due to low confidence (2)

workers/paymaster/src/index.ts:360

  • The JSDoc for unblockWorkspace still says 'workspace for block'. Please update it to 'workspace to unblock' to match the method's behavior.
* @param workspace - workspace for block

workers/limiter/types/reportData.ts:9

  • The comment refers to isBlocked but the field is now shouldBeBlockedByQuota. Update the comment to describe the new field name and semantics.
 * Is workspace get blocked

Comment thread workers/paymaster/tests/index.test.ts Outdated
const updatedWorkspace = await workspacesCollection.findOne({ _id: workspace._id });

expect(updatedWorkspace.isBlocked).toEqual(false);
expect(blockWorkspaceSpy).not.toHaveBeenCalledWith('limiter', {
Copy link

Copilot AI May 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test checks for calls to the queue named 'limiter', but Paymaster enqueues tasks to 'cron-tasks/limiter'. Update this assertion to use the correct queue name.

Suggested change
expect(blockWorkspaceSpy).not.toHaveBeenCalledWith('limiter', {
expect(blockWorkspaceSpy).not.toHaveBeenCalledWith('cron-tasks/limiter', {

Copilot uses AI. Check for mistakes.
Comment thread workers/paymaster/tests/index.test.ts Outdated
},
});

expect(blockWorkspaceSpy).not.toHaveBeenCalledWith('email', {
Copy link

Copilot AI May 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test asserts against the queue 'email', but Paymaster uses 'sender/email'. Update this to match the actual WorkerNames.EMAIL queue name.

Suggested change
expect(blockWorkspaceSpy).not.toHaveBeenCalledWith('email', {
expect(blockWorkspaceSpy).not.toHaveBeenCalledWith('sender/email', {

Copilot uses AI. Check for mistakes.
Comment thread workers/limiter/src/index.ts
Comment thread workers/paymaster/src/index.ts Outdated
Comment thread workers/limiter/tests/index.test.ts Outdated
Comment thread workers/limiter/tests/dbHelper.test.ts Outdated
@e11sy e11sy merged commit aa5b232 into master Jun 4, 2025
4 checks passed
@e11sy e11sy deleted the notify-about-project-ban branch June 4, 2025 14:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants