-
Notifications
You must be signed in to change notification settings - Fork 115
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(affiliates): Add table affiliate-referee-stats
and implement table methods
#2685
base: main
Are you sure you want to change the base?
Conversation
WalkthroughThis pull request introduces a comprehensive implementation for tracking and managing affiliate referee statistics in a PostgreSQL database. The changes span multiple files and include creating a new database migration, defining a model and types for affiliate statistics, implementing store functions for querying and updating these statistics, and adding test cases to validate the functionality. The implementation allows for detailed tracking of affiliate performance metrics such as earnings, trades, volumes, and fees. Changes
Sequence DiagramsequenceDiagram
participant App as Application
participant Store as AffiliateRefereeStatsStore
participant DB as PostgreSQL Database
App->>Store: updateStats(windowStartTs, windowEndTs)
Store->>DB: Construct complex query with CTEs
DB-->>Store: Aggregate affiliate statistics
Store->>DB: Upsert aggregated stats
DB-->>Store: Confirm update
Store-->>App: Return updated stats
Possibly related PRs
Suggested labels
Suggested reviewers
Poem
Finishing Touches
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
const transaction: Knex.Transaction | undefined = Transaction.get(txId); | ||
|
||
const query = ` | ||
-- Get metadata for all affiliates |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ran query on internal mainnet indexer DB and confirmed result is consistent with output of current affiliate-info
table.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How fast is the query?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 4
🧹 Nitpick comments (7)
indexer/packages/postgres/src/stores/affiliate-referee-stats-table.ts (1)
304-328
: Consider Using Cursor-Based Pagination for EfficiencyThe
paginatedFindWithAffiliateAddress
function uses offset-based pagination, which can become inefficient with large datasets. Consider implementing cursor-based pagination usingaffiliateEarnings
andrefereeAddress
as cursors to improve performance.Example implementation:
// Modify the function signature to include cursor parameters export async function paginatedFindWithAffiliateAddress( affiliateAddress: string, afterCursor: string | null, limit: number, options: Options = DEFAULT_POSTGRES_OPTIONS, ): Promise<AffiliateRefereeStatsFromDatabase[]> { let baseQuery = setupBaseQuery<AffiliateRefereeStatsModel>( AffiliateRefereeStatsModel, options, ); baseQuery = baseQuery.where(AffiliateRefereeStatsColumns.affiliateAddress, affiliateAddress); if (afterCursor) { baseQuery = baseQuery.where('refereeAddress', '>', afterCursor); } baseQuery = baseQuery.orderBy('refereeAddress', Ordering.ASC).limit(limit); return baseQuery.returning('*'); }indexer/packages/postgres/src/types/affiliate-referee-stats-types.ts (1)
1-27
: Ensure Consistent Mapping Between Interface and Database ColumnsThe
AffiliateRefereeStatsCreateObject
interface uses camelCase for property names, while database columns are typically snake_case. Ensure that the model correctly maps these properties to the corresponding database columns to maintain consistency and prevent any mapping issues.Example adjustment in the model:
static get columnNameMappers() { return snakeCaseMappers(); }indexer/packages/postgres/src/models/affiliate-referee-stats-model.ts (2)
14-44
: Consider adding field descriptions in the JSON schema.While the schema is comprehensive with proper validation patterns, adding descriptions for each field would improve maintainability and documentation.
properties: { - refereeAddress: { type: 'string' }, + refereeAddress: { + type: 'string', + description: 'The address of the referee user' + }, // Add descriptions for other fields similarly }
33-41
: Consider using constants for numeric patterns.The validation patterns for numeric fields are repeated. Consider extracting them into named constants for better maintainability.
+ const EARNINGS_PATTERN = NonNegativeNumericPattern; + const FEES_PATTERN = NonNegativeNumericPattern; + const REBATES_PATTERN = NumericPattern; properties: { // ... - affiliateEarnings: { type: 'string', pattern: NonNegativeNumericPattern }, + affiliateEarnings: { type: 'string', pattern: EARNINGS_PATTERN }, // Apply similar changes to other numeric fields }indexer/packages/postgres/src/types/db-model-types.ts (1)
286-298
: Consider grouping related interfaces together.The interface looks good with proper types. Consider moving it next to other affiliate-related interfaces (like AffiliateInfoFromDatabase) for better code organization.
Move this interface next to other affiliate-related interfaces around line 300.
indexer/packages/postgres/__tests__/stores/affiliate-referee-stats-table.test.ts (2)
229-229
: Remove or implement the TODO comment.The TODO comment suggests a potential improvement to the query functionality.
Would you like me to help implement the query improvement or create a GitHub issue to track this task?
304-403
: Consider refactoring the test helper function.The
populateFillsAndReferrals
function is quite long and handles multiple responsibilities. Consider breaking it down into smaller, focused helper functions for better maintainability.Example refactor:
-async function populateFillsAndReferrals(): Promise<DateTime> { +async function createReferrals(referredAtBlock: number): Promise<void> { + await AffiliateReferredUsersTable.create({ + affiliateAddress: affiliateStatDefaultAddrReferredByAddr2.affiliateAddress, + refereeAddress: affiliateStatDefaultAddrReferredByAddr2.refereeAddress, + referredAtBlock: `${referredAtBlock}`, + }); + // ... other referral creations +} + +async function createFills(referenceDt: DateTime, referredAtBlock: number): Promise<void> { + await Promise.all([ + createTakerFill(referenceDt, referredAtBlock), + createMakerFill(referenceDt, referredAtBlock), + // ... other fill creations + ]); +} + +async function populateFillsAndReferrals(): Promise<DateTime> { + const referenceDt = DateTime.utc(); + const referredAtBlock = 1; + + await seedData(); + await createReferrals(referredAtBlock); + await createFills(referenceDt, referredAtBlock); + + return referenceDt; +}
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (10)
indexer/packages/postgres/__tests__/helpers/constants.ts
(3 hunks)indexer/packages/postgres/__tests__/stores/affiliate-referee-stats-table.test.ts
(1 hunks)indexer/packages/postgres/src/db/migrations/migration_files/20241126173317_affiliate_referee_stats.ts
(1 hunks)indexer/packages/postgres/src/helpers/db-helpers.ts
(1 hunks)indexer/packages/postgres/src/models/affiliate-referee-stats-model.ts
(1 hunks)indexer/packages/postgres/src/stores/affiliate-referee-stats-table.ts
(1 hunks)indexer/packages/postgres/src/types/affiliate-referee-stats-types.ts
(1 hunks)indexer/packages/postgres/src/types/db-model-types.ts
(1 hunks)indexer/packages/postgres/src/types/index.ts
(1 hunks)indexer/packages/postgres/src/types/query-types.ts
(1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (1)
- GitHub Check: Summary
🔇 Additional comments (10)
indexer/packages/postgres/src/stores/affiliate-referee-stats-table.ts (2)
78-87
: Verify the Use of.upsert()
MethodThe use of
.upsert()
on line 83 may not be a standard method provided by Objection.js. Ensure that there is a custom implementation forAffiliateRefereeStatsModel
or adjust the code to use supported methods likeinsert
withonConflict().merge()
to achieve upsert functionality.Please confirm that the
upsert
method exists or modify the code to use an alternative approach. For example:await AffiliateRefereeStatsModel.query(Transaction.get(options.txId)) .insert(AffiliateRefereeStatsToUpsert) .onConflict('refereeAddress') .merge() .returning('*');
38-66
: ValidateorderBy
Parameters to Prevent SQL InjectionIn the
findAll
function, theoptions.orderBy
values are directly used in the query builder. Ensure that thecolumn
names andorder
directions are validated against a whitelist of allowed values to prevent potential SQL injection attacks.Consider implementing validation for
options.orderBy
:const allowedColumns = Object.values(AffiliateRefereeStatsColumns); const allowedOrderings = [Ordering.ASC, Ordering.DESC]; for (const [column, order] of options.orderBy) { if (!allowedColumns.includes(column) || !allowedOrderings.includes(order)) { throw new Error('Invalid orderBy parameters'); } baseQuery = baseQuery.orderBy(column, order); }indexer/packages/postgres/src/types/index.ts (1)
34-34
: LGTM!The new export statement is correctly placed and maintains the alphabetical ordering of the exports.
indexer/packages/postgres/src/models/affiliate-referee-stats-model.ts (2)
5-12
: LGTM!The model configuration is correct with proper table name and primary key definition.
50-50
: Address the TODO comment regarding schema validation.The TODO comment (IND-239) indicates a need to ensure consistency between jsonSchema, sqlToJsonConversions, and model fields.
Run this script to verify the consistency:
✅ Verification successful
Schema validation is complete - all components are consistent ✅
The TODO comment can be safely removed as the verification confirms perfect consistency between:
- All field names and their order in
jsonSchema()
,sqlToJsonConversions()
, and model fields- Type mappings across all three sections (string/int types properly aligned)
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Check consistency between schema, conversions, and model fields # Extract field names from different sections echo "Analyzing AffiliateRefereeStatsModel..." # Get fields from jsonSchema echo "Fields in jsonSchema:" rg -A 30 'jsonSchema.*properties:' | rg '^\s+\w+:' # Get fields from sqlToJsonConversions echo "Fields in sqlToJsonConversions:" rg -A 15 'sqlToJsonConversions.*return' | rg '^\s+\w+:' # Get model property declarations echo "Model property declarations:" rg -A 30 'QueryBuilderType!' | rg '^\s+\w+!:'Length of output: 440
Script:
#!/bin/bash # View the complete file content to analyze schema consistency cat "indexer/packages/postgres/src/models/affiliate-referee-stats-model.ts"Length of output: 2772
indexer/packages/postgres/src/helpers/db-helpers.ts (1)
35-35
: LGTM!The addition of 'affiliate_referee_stats' to layer1Tables is correct and maintains consistency with the database schema.
indexer/packages/postgres/src/types/query-types.ts (1)
344-346
: LGTM! The interface follows the established pattern.The new
AffiliateRefereeStatsQueryConfig
interface is well-structured and consistent with other query configuration interfaces in the file.indexer/packages/postgres/__tests__/stores/affiliate-referee-stats-table.test.ts (2)
1-38
: LGTM! Test setup is well-structured.The test file has proper lifecycle hooks for database setup and cleanup.
39-124
: LGTM! Comprehensive CRUD test coverage.The test cases cover essential scenarios:
- Creation of stats
- Duplicate prevention
- Upsert functionality
- Retrieval by ID and query parameters
indexer/packages/postgres/__tests__/helpers/constants.ts (1)
76-76
: LGTM! Well-structured test constants.The new constants are:
- Well-organized and properly grouped
- Include realistic test values
- Cover different scenarios for affiliate stats
Also applies to: 1020-1060
filtered_fills | ||
INNER JOIN | ||
affiliate_referred_subaccounts | ||
ON | ||
filtered_fills."subaccountId" = affiliate_referred_subaccounts."subaccountId" | ||
WHERE | ||
filtered_fills."createdAtHeight" >= affiliate_referred_subaccounts."referredAtBlock" | ||
), | ||
|
||
-- Step 2d: Aggregate stats per affiliate-referee tuple | ||
affiliate_stats_per_referee AS ( | ||
SELECT | ||
affiliate_fills."affiliateAddress", | ||
affiliate_fills."refereeAddress", | ||
SUM(affiliate_fills."fee") AS "totalReferredFees", | ||
SUM(affiliate_fills."affiliateRevShare") AS "affiliateEarnings", | ||
SUM(CASE WHEN affiliate_fills."liquidity" = '${Liquidity.MAKER}' AND affiliate_fills."fee" > 0 THEN affiliate_fills."fee" ELSE 0 END) AS "referredMakerFees", | ||
SUM(CASE WHEN affiliate_fills."liquidity" = '${Liquidity.TAKER}' AND affiliate_fills."type" = '${FillType.LIMIT}' THEN affiliate_fills."fee" ELSE 0 END) AS "referredTakerFees", | ||
SUM(CASE WHEN affiliate_fills."liquidity" = '${Liquidity.MAKER}' AND affiliate_fills."fee" < 0 THEN affiliate_fills."fee" ELSE 0 END) AS "referredMakerRebates", | ||
SUM(CASE WHEN affiliate_fills."liquidity" = '${Liquidity.TAKER}' AND affiliate_fills."type" = '${FillType.LIQUIDATED}' THEN affiliate_fills."fee" ELSE 0 END) AS "referredLiquidationFees", | ||
COUNT(CASE WHEN affiliate_fills."liquidity" = '${Liquidity.MAKER}' THEN 1 END) AS "referredMakerTrades", | ||
COUNT(CASE WHEN affiliate_fills."liquidity" = '${Liquidity.TAKER}' THEN 1 END) AS "referredTakerTrades", | ||
SUM(affiliate_fills."price" * affiliate_fills."size") AS "referredTotalVolume" | ||
FROM | ||
affiliate_fills | ||
GROUP BY | ||
affiliate_fills."affiliateAddress", | ||
affiliate_fills."refereeAddress" | ||
), | ||
|
||
-- Step 3a: Prepare data for updating or inserting into the affiliate_referee_stats table | ||
-- Combine metadata with aggregated stats for each affiliate-referee pair | ||
affiliate_referee_stats_update AS ( | ||
SELECT | ||
affiliate_metadata_per_referee."affiliateAddress", | ||
affiliate_metadata_per_referee."refereeAddress", | ||
affiliate_metadata_per_referee."referralBlockHeight", | ||
COALESCE(affiliate_stats_per_referee."affiliateEarnings", 0) AS "affiliateEarnings", | ||
COALESCE(affiliate_stats_per_referee."referredMakerTrades", 0) AS "referredMakerTrades", | ||
COALESCE(affiliate_stats_per_referee."referredTakerTrades", 0) AS "referredTakerTrades", | ||
COALESCE(affiliate_stats_per_referee."referredMakerFees", 0) AS "referredMakerFees", | ||
COALESCE(affiliate_stats_per_referee."referredTakerFees", 0) AS "referredTakerFees", | ||
COALESCE(affiliate_stats_per_referee."referredLiquidationFees", 0) AS "referredLiquidationFees", | ||
COALESCE(affiliate_stats_per_referee."referredMakerRebates", 0) AS "referredMakerRebates", | ||
COALESCE(affiliate_stats_per_referee."referredTotalVolume", 0) AS "referredTotalVolume" | ||
FROM | ||
affiliate_metadata_per_referee | ||
LEFT JOIN | ||
affiliate_stats_per_referee | ||
ON | ||
affiliate_metadata_per_referee."affiliateAddress" = affiliate_stats_per_referee."affiliateAddress" | ||
AND affiliate_metadata_per_referee."refereeAddress" = affiliate_stats_per_referee."refereeAddress" | ||
) | ||
|
||
-- Step 3b: Insert or update the affiliate_referee_stats table | ||
-- Update existing rows with new data or insert new rows if they don't exist | ||
INSERT INTO affiliate_referee_stats ( | ||
"affiliateAddress", | ||
"refereeAddress", | ||
"referralBlockHeight", | ||
"affiliateEarnings", | ||
"referredMakerTrades", | ||
"referredTakerTrades", | ||
"referredMakerFees", | ||
"referredTakerFees", | ||
"referredLiquidationFees", | ||
"referredMakerRebates", | ||
"referredTotalVolume" | ||
) | ||
SELECT | ||
"affiliateAddress", | ||
"refereeAddress", | ||
"referralBlockHeight", | ||
"affiliateEarnings", | ||
"referredMakerTrades", | ||
"referredTakerTrades", | ||
"referredMakerFees", | ||
"referredTakerFees", | ||
"referredLiquidationFees", | ||
"referredMakerRebates", | ||
"referredTotalVolume" | ||
FROM | ||
affiliate_referee_stats_update | ||
ON CONFLICT ("refereeAddress") | ||
DO UPDATE SET | ||
"referralBlockHeight" = EXCLUDED."referralBlockHeight", | ||
"affiliateEarnings" = affiliate_referee_stats."affiliateEarnings" + EXCLUDED."affiliateEarnings", | ||
"referredMakerTrades" = affiliate_referee_stats."referredMakerTrades" + EXCLUDED."referredMakerTrades", | ||
"referredTakerTrades" = affiliate_referee_stats."referredTakerTrades" + EXCLUDED."referredTakerTrades", | ||
"referredMakerFees" = affiliate_referee_stats."referredMakerFees" + EXCLUDED."referredMakerFees", | ||
"referredTakerFees" = affiliate_referee_stats."referredTakerFees" + EXCLUDED."referredTakerFees", | ||
"referredLiquidationFees" = affiliate_referee_stats."referredLiquidationFees" + EXCLUDED."referredLiquidationFees", | ||
"referredMakerRebates" = affiliate_referee_stats."referredMakerRebates" + EXCLUDED."referredMakerRebates", | ||
"referredTotalVolume" = affiliate_referee_stats."referredTotalVolume" + EXCLUDED."referredTotalVolume"; | ||
`; | ||
|
||
return transaction | ||
? knexPrimary.raw(query).transacting(transaction) | ||
: knexPrimary.raw(query); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Potential SQL Injection Vulnerability in updateStats
Function
The updateStats
function constructs a raw SQL query by directly interpolating windowStartTs
and windowEndTs
into the query string. If these parameters are not properly sanitized, this can lead to SQL injection vulnerabilities. It's recommended to use parameterized queries to safely include these values.
Apply this diff to use parameterized queries:
- fills."createdAt" > '${windowStartTs}'
- AND fills."createdAt" <= '${windowEndTs}'
+ fills."createdAt" > ? AND fills."createdAt" <= ?
Then, pass the parameters securely when executing the query:
const query = `
-- Your SQL query with placeholders for windowStartTs and windowEndTs
`;
const bindings = [windowStartTs, windowEndTs];
return transaction
? knexPrimary.raw(query, bindings).transacting(transaction)
: knexPrimary.raw(query, bindings);
table.string('refereeAddress').primary().notNullable(); | ||
table.string('affiliateAddress').notNullable(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reconsider the Primary Key Definition
Setting refereeAddress
as the primary key may not accurately represent the relationship if a referee can be associated with multiple affiliates. Consider using a composite primary key consisting of both affiliateAddress
and refereeAddress
.
Apply this diff to adjust the primary key:
- table.string('refereeAddress').primary().notNullable();
- table.string('affiliateAddress').notNullable();
+ table.string('refereeAddress').notNullable();
+ table.string('affiliateAddress').notNullable();
+ table.primary(['affiliateAddress', 'refereeAddress']);
This change ensures that each affiliate-referee pair is unique and correctly modeled.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
table.string('refereeAddress').primary().notNullable(); | |
table.string('affiliateAddress').notNullable(); | |
table.string('refereeAddress').notNullable(); | |
table.string('affiliateAddress').notNullable(); | |
table.primary(['affiliateAddress', 'refereeAddress']); |
table.string('refereeAddress').primary().notNullable(); | ||
table.string('affiliateAddress').notNullable(); | ||
table.decimal('affiliateEarnings', null).notNullable().defaultTo(0); | ||
table.integer('referredMakerTrades').notNullable().defaultTo(0); | ||
table.integer('referredTakerTrades').notNullable().defaultTo(0); | ||
table.decimal('referredTotalVolume', null).notNullable().defaultTo(0); | ||
table.bigInteger('referralBlockHeight').notNullable(); | ||
table.decimal('referredTakerFees', null).notNullable().defaultTo(0); | ||
table.decimal('referredMakerFees', null).notNullable().defaultTo(0); | ||
table.decimal('referredMakerRebates', null).notNullable().defaultTo(0); | ||
table.decimal('referredLiquidationFees', null).notNullable().defaultTo(0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Specify Precision and Scale for Decimal Columns
Passing null
for precision in table.decimal()
may lead to inconsistent behavior across different database systems. It's recommended to specify precision and scale explicitly for decimal columns to ensure data consistency.
Apply this diff to define precision and scale:
- table.decimal('affiliateEarnings', null).notNullable().defaultTo(0);
+ table.decimal('affiliateEarnings', 38, 18).notNullable().defaultTo(0);
Repeat for all decimal columns, setting appropriate precision and scale based on your requirements.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
table.string('refereeAddress').primary().notNullable(); | |
table.string('affiliateAddress').notNullable(); | |
table.decimal('affiliateEarnings', null).notNullable().defaultTo(0); | |
table.integer('referredMakerTrades').notNullable().defaultTo(0); | |
table.integer('referredTakerTrades').notNullable().defaultTo(0); | |
table.decimal('referredTotalVolume', null).notNullable().defaultTo(0); | |
table.bigInteger('referralBlockHeight').notNullable(); | |
table.decimal('referredTakerFees', null).notNullable().defaultTo(0); | |
table.decimal('referredMakerFees', null).notNullable().defaultTo(0); | |
table.decimal('referredMakerRebates', null).notNullable().defaultTo(0); | |
table.decimal('referredLiquidationFees', null).notNullable().defaultTo(0); | |
table.string('refereeAddress').primary().notNullable(); | |
table.string('affiliateAddress').notNullable(); | |
table.decimal('affiliateEarnings', 38, 18).notNullable().defaultTo(0); | |
table.integer('referredMakerTrades').notNullable().defaultTo(0); | |
table.integer('referredTakerTrades').notNullable().defaultTo(0); | |
table.decimal('referredTotalVolume', 38, 18).notNullable().defaultTo(0); | |
table.bigInteger('referralBlockHeight').notNullable(); | |
table.decimal('referredTakerFees', 38, 18).notNullable().defaultTo(0); | |
table.decimal('referredMakerFees', 38, 18).notNullable().defaultTo(0); | |
table.decimal('referredMakerRebates', 38, 18).notNullable().defaultTo(0); | |
table.decimal('referredLiquidationFees', 38, 18).notNullable().defaultTo(0); |
}); | ||
}); | ||
|
||
// TODO(CT-1341): Add paginated query tests similar to `affiliate-info-table.test.ts` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Codebase verification
Add pagination tests as mentioned in the TODO comment.
The reference file affiliate-info-table.test.ts
contains a comprehensive test suite for the paginatedFindWithAddressFilter
functionality that should be replicated in this file. The tests should cover filtering, sorting, pagination (offset/limit), and edge cases.
🔗 Analysis chain
Address the TODO comment for pagination tests.
The comment references ticket CT-1341 for adding pagination query tests.
Let's verify if this ticket exists and its status:
Would you like me to help implement the pagination tests or create a GitHub issue if it doesn't exist?
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Check if the ticket exists in GitHub issues
gh issue list --search "CT-1341 in:title,body"
Length of output: 48
Script:
#!/bin/bash
# Find and show the referenced test file content
fd -t f "affiliate-info-table.test.ts" --exec cat {}
# Show the current test file content for comparison
cat indexer/packages/postgres/__tests__/stores/affiliate-referee-stats-table.test.ts
Length of output: 30046
-- Step 2c: Inner join filtered_fills with affiliate_referred_subaccounts and filter | ||
affiliate_fills AS ( | ||
SELECT | ||
filtered_fills."subaccountId", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: Could simply the query by using filtered_fills.*
to select all columns from the subquery.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that's a smell for prod.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Valid point, could go either way, *
leads to less failures due to changes to fields, but also hides issues due to schema changes.
Changelist
affiliate-referee-stats
which records per referee stats (similar/parallel to existing tableaffilaite-info
which aggregates per-affiliateTest Plan
Unit tests
Author/Reviewer Checklist
state-breaking
label.indexer-postgres-breaking
label.PrepareProposal
orProcessProposal
, manually add the labelproposal-breaking
.feature:[feature-name]
.backport/[branch-name]
.refactor
,chore
,bug
.Summary by CodeRabbit
New Features
Database Changes
affiliate_referee_stats
table with comprehensive tracking of referral performanceTechnical Improvements