Skip to content

Commit 0965df6

Browse files
authored
Fix double reaction bug (#13329)
Indexing was getting stalled from the previous fix because the primary key would already exist. This change reverts #13282 and fixes it a different way by moving the check for existing deleted comments to the validation logic, and adding the code to handle that case in the reaction creation logic. Also adds commands for `audius-cmd` and tested locally. **NOTE**: Re-liking a comment will _not_ trigger a new notification. Made a call that we probably don't want to spam notifs every time it toggles.
1 parent 40e5b07 commit 0965df6

File tree

6 files changed

+136
-4
lines changed

6 files changed

+136
-4
lines changed
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import chalk from 'chalk'
2+
import { Command } from '@commander-js/extra-typings'
3+
4+
import { getCurrentUserId, initializeAudiusSdk } from '../utils.js'
5+
import { decodeHashId, EntityType } from '@audius/sdk'
6+
import { outputFormatOption } from '../common-options.js'
7+
8+
export const createCommentCommand = new Command('create')
9+
.description('Create a new comment')
10+
.argument('<entityId>', 'The ID of the entity to comment on', (value) => {
11+
return decodeHashId(value)!
12+
})
13+
.argument('[comment]', 'The content of the comment', 'This is a comment')
14+
.option(
15+
'-t, --entity-type <entityType>',
16+
'The type of entity to comment on',
17+
(value) => value as EntityType,
18+
EntityType.TRACK
19+
)
20+
.option(
21+
'-p, --parent-comment-id <parentCommentId>',
22+
'The ID of the parent comment',
23+
(value) => {
24+
return decodeHashId(value)!
25+
}
26+
)
27+
.option(
28+
'-m, --mentions <mentions...>',
29+
'List of user IDs to mention',
30+
(values) => {
31+
return values.split(',').map((value) => decodeHashId(value)!)
32+
}
33+
)
34+
.option('-f, --from <from>', 'The account to create the comment from')
35+
.addOption(outputFormatOption)
36+
.action(
37+
async (
38+
entityId,
39+
comment,
40+
{ from, entityType, parentCommentId, mentions }
41+
) => {
42+
const audiusSdk = await initializeAudiusSdk({ handle: from })
43+
const userId = await getCurrentUserId()
44+
45+
const commentId = await audiusSdk.comments.postComment({
46+
userId: decodeHashId(userId)!,
47+
entityId,
48+
entityType,
49+
body: comment,
50+
parentCommentId,
51+
mentions
52+
})
53+
console.log(chalk.green('Success!'))
54+
console.log(chalk.yellow.bold(`Comment ID: `), commentId)
55+
console.log(
56+
chalk.yellow.bold(`Comment ID #: `),
57+
decodeHashId(commentId!)
58+
)
59+
console.log(chalk.yellow.bold(`Comment Body: `), comment)
60+
}
61+
)
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import { Command } from '@commander-js/extra-typings'
2+
import { createCommentCommand } from './create-comment'
3+
import { reactCommentCommand } from './react-comment'
4+
5+
export const commentCommand = new Command('comment')
6+
.description('Commands for creating and managing comments')
7+
.addCommand(createCommentCommand)
8+
.addCommand(reactCommentCommand)
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import chalk from 'chalk'
2+
import { Command } from '@commander-js/extra-typings'
3+
4+
import {
5+
getCurrentUserId,
6+
initializeAudiusSdk,
7+
parseBoolean
8+
} from '../utils.js'
9+
import { decodeHashId } from '@audius/sdk'
10+
import { outputFormatOption } from '../common-options.js'
11+
12+
export const reactCommentCommand = new Command('react')
13+
.description('React to a comment')
14+
.argument('<commentId>', 'The ID of the comment to react to', (value) => {
15+
return decodeHashId(value)!
16+
})
17+
.argument('entityId', 'The ID of the entity to comment on', (value) => {
18+
return decodeHashId(value)!
19+
})
20+
.argument(
21+
'[isLiked]',
22+
'Whether to like (true) or dislike (false) the comment',
23+
parseBoolean,
24+
true
25+
)
26+
.option('-f, --from <from>', 'The account to create the comment from')
27+
.addOption(outputFormatOption)
28+
.action(async (commentId, entityId, isLiked, { from }) => {
29+
const audiusSdk = await initializeAudiusSdk({ handle: from })
30+
const userId = await getCurrentUserId()
31+
await audiusSdk.comments.reactComment({
32+
userId: decodeHashId(userId)!,
33+
commentId,
34+
isLiked,
35+
trackId: entityId
36+
})
37+
console.log(chalk.green('Success!'))
38+
console.log(chalk.yellow.bold(`Comment Liked: `), isLiked)
39+
})

packages/commands/src/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import { userCommand } from './user/index.js'
2121
import { albumCommand } from './album/index.js'
2222
import { entropyCommand } from './misc/entropy.js'
2323
import { aaoCommand } from './misc/aao.js'
24+
import { commentCommand } from './comments/index.js'
2425

2526
async function main() {
2627
program.name('audius-cmd')
@@ -31,6 +32,7 @@ async function main() {
3132
program.addCommand(trackCommand)
3233
program.addCommand(playlistCommand)
3334
program.addCommand(albumCommand)
35+
program.addCommand(commentCommand)
3436
program.addCommand(managerCommand)
3537
program.addCommand(authHeadersCommand)
3638
program.addCommand(claimRewardCommand)

packages/discovery-provider/src/tasks/entity_manager/entities/comment.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -533,6 +533,9 @@ def validate_comment_reaction_tx(params: ManageEntityParameters):
533533
params.action == Action.REACT
534534
and (user_id, comment_id)
535535
in params.existing_records[EntityType.COMMENT_REACTION.value]
536+
and not params.existing_records[EntityType.COMMENT_REACTION.value][
537+
(user_id, comment_id)
538+
].is_delete
536539
):
537540
raise IndexingValidationError(
538541
f"User {user_id} already reacted to comment {comment_id}"
@@ -555,6 +558,25 @@ def react_comment(params: ManageEntityParameters):
555558
entity_id = metadata.get("entity_id")
556559
entity_type = metadata.get("entity_type", EntityType.TRACK.value)
557560

561+
existing_reaction = params.existing_records[EntityType.COMMENT_REACTION.value].get(
562+
(user_id, comment_id)
563+
)
564+
if existing_reaction and existing_reaction.is_delete:
565+
reactivated_reaction = copy_record(
566+
existing_reaction,
567+
params.block_number,
568+
params.event_blockhash,
569+
params.txhash,
570+
params.block_datetime,
571+
)
572+
reactivated_reaction.is_delete = False
573+
params.add_record(
574+
(user_id, comment_id),
575+
reactivated_reaction,
576+
EntityType.COMMENT_REACTION,
577+
)
578+
return
579+
558580
comment_reaction_record = CommentReaction(
559581
comment_id=comment_id,
560582
user_id=user_id,

packages/discovery-provider/src/tasks/entity_manager/entity_manager.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1394,7 +1394,7 @@ def fetch_existing_entities(session: Session, entities_to_fetch: EntitiesToFetch
13941394
CommentReaction,
13951395
literal_column(f"row_to_json({CommentReaction.__tablename__})"),
13961396
)
1397-
.filter(or_(*or_queries), CommentReaction.is_delete == False)
1397+
.filter(or_(*or_queries))
13981398
.all()
13991399
)
14001400
existing_entities[EntityType.COMMENT_REACTION] = {
@@ -1441,7 +1441,7 @@ def fetch_existing_entities(session: Session, entities_to_fetch: EntitiesToFetch
14411441
CommentMention,
14421442
literal_column(f"row_to_json({CommentMention.__tablename__})"),
14431443
)
1444-
.filter(or_(*or_queries), CommentMention.is_delete == False)
1444+
.filter(or_(*or_queries))
14451445
.all()
14461446
)
14471447

@@ -1473,7 +1473,7 @@ def fetch_existing_entities(session: Session, entities_to_fetch: EntitiesToFetch
14731473
MutedUser,
14741474
literal_column(f"row_to_json({MutedUser.__tablename__})"),
14751475
)
1476-
.filter(or_(*or_queries), MutedUser.is_delete == False)
1476+
.filter(or_(*or_queries))
14771477
.all()
14781478
)
14791479
existing_entities[EntityType.MUTED_USER] = {
@@ -1506,7 +1506,7 @@ def fetch_existing_entities(session: Session, entities_to_fetch: EntitiesToFetch
15061506
CommentReport,
15071507
literal_column(f"row_to_json({CommentReport.__tablename__})"),
15081508
)
1509-
.filter(or_(*or_queries), CommentReport.is_delete == False)
1509+
.filter(or_(*or_queries))
15101510
.all()
15111511
)
15121512
existing_entities[EntityType.COMMENT_REPORT] = {

0 commit comments

Comments
 (0)