Skip to content

Conversation

@TBonnin
Copy link
Collaborator

@TBonnin TBonnin commented Oct 27, 2025

Record counts table entries are not deleted when a connection is soft deleted (only when hard deleted) which means that records are still counted until the connection is hard deleted.
Since we delete connections from different places in the codebase it would require a big refactoring to delete the record counts table when connections is soft deleted. Main pain point is connections are soft-deleted when an integration is soft-deleted, deep inside the shared package, which hasn't any knowledge of the records packages :(
Instead I decided to account for the deleted connections when we report the record counts. The logic was already quite cumbersome and wasn't supporting pagination.


Exclude soft-deleted connections from record metrics + add pagination helpers

Soft-deleted connections were still represented in the record_counts table, so the "Records" usage metric billed/observed more data than actually active. This PR avoids modifying the underlying table and instead filters record-count rows at read-time. It introduces paginated accessors in both the Records and Connections layers and rewrites the metering cron to join these two paginated streams, aggregating only active (non-deleted) connections. Additional integration tests ensure the new iterators and counting logic behave as expected.

Key Changes

• Added records.paginateRecordCounts() – offset-based async generator that yields batches from RECORD_COUNTS_TABLE.
• Added connectionService.paginateConnections() – cursor-based async generator returning active connections with related account/env rows; supports optional connectionIds filter.
• Re-implemented observability.exportRecordsMetrics() in packages/metering/lib/crons/usage.ts to: a) page through record counts, b) fetch matching connections, c) skip deleted connections, and d) aggregate metrics per account.
• Updated unit/integration tests for Records and Connection services to cover new pagination helpers and counting logic.
• Minor cleanup: removed unused environmentService import, dropped redundant warning log in usage tracker.

Affected Areas

packages/metering/lib/crons/usage.ts
packages/shared/lib/services/connection.service.ts
packages/records/lib/models/records.ts
• Associated integration test suites
packages/account-usage/lib/usage.ts (small log change)


This summary was automatically generated by @propel-code-bot

Record counts table entries are not deleted when a connection is soft
deleted (only when hard deleted) which means that records are still
counted until the connection is hard deleted.
Since we delete connections from different places in the codebase it would require a
big refactoring to delete the record counts table when connections is
soft deleted. Main pain point is connections are soft-deleted when an
integration is soft-deleted, deep inside the shared package, which
hasn't any knowledge of the records packages :(
Instead I decided to account for the deleted connections when we report
the record counts. The logic was already quite cumbersome and wasn't
supporting pagination.
@TBonnin TBonnin requested a review from a team October 27, 2025 20:39
@linear
Copy link

linear bot commented Oct 27, 2025

case 'function_logs': {
const billingUsage = await this.getBillingUsage(accountId);
if (billingUsage.isErr()) {
logger.warning(`Failed to fetch billing usage for accountId: ${accountId}`, billingUsage.error);
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

unrelated. I just noticed we were logging the error twice. Here and in the catch

throw res.error;
}
for (const value of res.value) {
const recordCount = recordCounts.value.find((r) => r.connection_id === value.connection.id);
Copy link
Contributor

Choose a reason for hiding this comment

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

Potentially avoidable o(n^2), but probably negligible compared to queries?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This entire analytics logic only works because the scale is small. We are gonna need to come up with a better solution as our user base of customers saving records expands

@TBonnin TBonnin added this pull request to the merge queue Oct 28, 2025
Merged via the queue into master with commit d6f0b37 Oct 28, 2025
24 checks passed
@TBonnin TBonnin deleted the tbonnin/nan-4233/record-count-deleted-connections branch October 28, 2025 13:31
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.

3 participants