Skip to content

[PB-6472]: feat/track-user-mail-usage#220

Open
jzunigax2 wants to merge 5 commits into
feat/mail-bucket-provisioningfrom
feat/track-user-mail-usage
Open

[PB-6472]: feat/track-user-mail-usage#220
jzunigax2 wants to merge 5 commits into
feat/mail-bucket-provisioningfrom
feat/track-user-mail-usage

Conversation

@jzunigax2

@jzunigax2 jzunigax2 commented Jun 3, 2026

Copy link
Copy Markdown

What

Adds per-message storage accounting for Mail into the network, so a user's totalUsedSpaceBytes reflects Drive + Mail as a single real total. Mail writes one shard-less, version-2 BucketEntry per ingested message (keyed by accountId:documentId) and increments totalUsedSpaceBytes on first insert; deletes remove the entry and decrement.

Mail provisions one bucket per mail account #221 and periodically reports that account's usage from Stalwart here.

Why

Bridge needs to track each user's mail storage usage next to their Drive usage so the two can be checked against a single quota. This replaces the previous "report aggregate mail usage to a separate field" approach, which was rejected because that figure was not part of totalUsedSpaceBytes and therefore couldn't gate Drive uploads

The current design folds Mail into the same counter Drive already enforces against, using the same per-object metadata model as Drive's /finish.

Mail bodies and attachments are stored by Stalwart's own blob store and never traverse the network upload->shard->mirror path. There are therefore no real shards to record.

How

  • Stalwart fires a message-ingest.* event after storing a message and posts it, the handler resolves accountId and POST /v2/gateway/users/:uuid/buckets/:bucketId/entries
  • createEntryByKey hashes the key (index = sha256(key)) and does an idempotent findOneOrCreate on (bucket, index), writing a BucketEntry. Only on first insert it calls addTotalUsedSpaceBytes(uuid, size).

@jzunigax2 jzunigax2 added the enhancement New feature or request label Jun 3, 2026
@jzunigax2 jzunigax2 self-assigned this Jun 3, 2026
@jzunigax2 jzunigax2 changed the title feat/track-user-mail-usage [PB-6472]: feat/track-user-mail-usage Jun 5, 2026
@sg-gs

sg-gs commented Jun 5, 2026

Copy link
Copy Markdown
Member

The totalUsedSpaceBytes was a convenience field as an aggregation of everything. I find buckets the entity more suitable to have the same field or a similar one and relate all the content generated by mail to a specific bucket in the network, the same way we do with Drive and Backups' content.

This makes the network less coupled to mail/drive/any product we may release in the future that consumes space while gaining standarisation of the calculus of the used space on a bucket. WDYT @apsantiso @jzunigax2 ?

This may be even useful for Photos or the same Drive in any foreseeable future.

@jzunigax2 jzunigax2 force-pushed the feat/track-user-mail-usage branch from 02b5882 to 6f17e6b Compare June 9, 2026 20:03
@jzunigax2 jzunigax2 changed the base branch from master to feat/mail-bucket-provisioning June 9, 2026 20:04
@jzunigax2 jzunigax2 marked this pull request as ready for review June 11, 2026 03:38
@jzunigax2 jzunigax2 requested a review from sg-gs as a code owner June 11, 2026 03:38
Comment thread lib/core/users/usecase.ts Outdated
Comment thread lib/server/http/gateway/controller.ts Outdated
Add a usedSpaceBytes field to buckets and a gateway endpoint to set it, so products whose content lives outside the network (mail/Stalwart) can report the space they consume against a network bucket.
Add a new method to sum used space bytes in MongoDBBucketsRepository and update the UsersUsecase to return a UserSpaceSnapshot when setting bucket usage. Update HTTPGatewayController to send the snapshot in the response. Include tests to verify the new functionality.
Add methods to create and delete bucket entries in the MongoDBBucketEntriesRepository and BucketEntriesUsecase. Introduce a new endpoint in the HTTPGatewayController for creating entries, which includes validation for entry keys and sizes. Update tests to cover the new functionality
@jzunigax2 jzunigax2 force-pushed the feat/track-user-mail-usage branch from 3ab3f05 to c8aa165 Compare June 17, 2026 00:34
@jzunigax2 jzunigax2 marked this pull request as ready for review June 17, 2026 04:34
@jzunigax2 jzunigax2 requested a review from sg-gs June 17, 2026 04:34
Comment thread lib/server/http/gateway/controller.ts
Comment thread lib/core/bucketEntries/usecase.ts
Comment thread lib/core/bucketEntries/usecase.ts Outdated
Comment thread lib/core/bucketEntries/usecase.ts Outdated
maxSpaceBytes: user.maxSpaceBytes,
totalUsedSpaceBytes: created
? user.totalUsedSpaceBytes + size
: user.totalUsedSpaceBytes,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It's possible to update the size? Because in that case, you should consider the sum of it to the total. If this is not possible, close the comment. I would personally get what the database returns regarding the user totalUsedSpaceBytes field — if possible — and use the value directly to make this far simpler

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

right, now using what's returned by findOneAndUpdate

const user = await this.findUserAndOwnedBucket(userUuid, bucketId);

const index = this.hashEntryKey(key);
const entry = await this.bucketEntriesRepository.findOne({ bucket: bucketId, index });

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Why are u using the index? It's any kind of workaround to relate the mail blob with the bucketEntry?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

yes its a sort of workaround, mail blobs have neither shards nor an encryption index but these were still required. index stores sha256(key) which allows lookups

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The index is not a field for this, sincerely. How drive does it is by holding the reference to the network file, rather than coupling the network to a specific service. Mail should be the one holding the pointer to here, not the other way around

… addTotalUsedSpaceBytes to return total used space
@jzunigax2 jzunigax2 requested a review from sg-gs June 19, 2026 14:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request ready-for-preview

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants