Skip to content

Commit

Permalink
[AUD-1345] Fix favorite playlist profile completion challenge (#2366)
Browse files Browse the repository at this point in the history
* [AUD-1345] Fix favorite playlist profile completion challenge

* Update comment
  • Loading branch information
raymondjacobson committed Jan 22, 2022
1 parent 0a5f4e0 commit 483c942
Show file tree
Hide file tree
Showing 3 changed files with 292 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
"""fix_profile_completion_challenge_playlist_favorite
Revision ID: 8e4dda8255fd
Revises: a6d2e50a8efa
Create Date: 2022-01-21 20:19:05.992646
"""
import sqlalchemy as sa
from alembic import op

# revision identifiers, used by Alembic.
revision = "8e4dda8255fd"
down_revision = "a6d2e50a8efa"
branch_labels = None
depends_on = None


def upgrade():
pass
connection = op.get_bind()
connection.execute(
"""
begin;
-- This migration serves to repair missing state in
-- challenge_profile_completion where previously playlist favorites (saves)
-- did not update the challenge.
--
-- First, update challenge_profile_completion rows to account
-- for playlist saves.
-- By joining against the saves table for all playlist saves,
-- we can achieve this and only modify rows where users have done
-- a playlist save.
--
-- Second, use that result to update (recalculate) user_challenges
-- for users that were updated in the first step.
--
with updated as (
update challenge_profile_completion
set favorites = true
from saves
where
challenge_profile_completion.user_id = saves.user_id and
saves.is_current = true and
(saves.save_type = 'playlist' or saves.save_type = 'album') and
challenge_profile_completion.favorites = false
returning challenge_profile_completion.*
)
update user_challenges
set
is_complete=(
updated.profile_description and
updated.profile_name and
updated.profile_picture and
updated.profile_cover_photo and
updated.follows and
updated.favorites and
updated.reposts
),
current_step_count=(
cast(updated.profile_description as int) +
cast(updated.profile_name as int) +
cast(updated.profile_picture as int) +
cast(updated.profile_cover_photo as int) +
cast(updated.follows as int) +
cast(updated.favorites as int) +
cast(updated.reposts as int)
)
from updated
where
user_challenges.user_id = updated.user_id;
commit;
"""
)


def downgrade():
# This migration mutates state and has no relevant down migration
pass
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
BLOCK_NUMBER = 10


def test_profile_completion_challenge(app):
def test_profile_completion_challenge_with_tracks(app):

redis_conn = redis.Redis.from_url(url=REDIS_URL)

Expand Down Expand Up @@ -218,3 +218,211 @@ def test_profile_completion_challenge(app):
bus.process_events(session)
state = profile_challenge_manager.get_user_challenge_state(session, ["1"])[0]
assert state.current_step_count == 7 and state.is_complete == True


def test_profile_completion_challenge_with_playlists(app):

redis_conn = redis.Redis.from_url(url=REDIS_URL)

# create user
with app.app_context():
db = get_db()

block = Block(blockhash="0x1", number=BLOCK_NUMBER)
user = User(
blockhash="0x1",
blocknumber=BLOCK_NUMBER,
txhash="xyz",
user_id=1,
is_current=True,
handle="TestHandle",
handle_lc="testhandle",
wallet="0x123",
is_creator=False,
is_verified=False,
name="test_name",
created_at=datetime.now(),
updated_at=datetime.now(),
)

with db.scoped_session() as session:
bus = ChallengeEventBus(redis_conn)

# set challenge as active for purposes of test
session.query(Challenge).filter(Challenge.id == "profile-completion").update(
{"active": True, "starting_block": BLOCK_NUMBER}
)

# Register events with the bus
bus.register_listener(ChallengeEvent.profile_update, profile_challenge_manager)
bus.register_listener(ChallengeEvent.repost, profile_challenge_manager)
bus.register_listener(ChallengeEvent.follow, profile_challenge_manager)
bus.register_listener(ChallengeEvent.favorite, profile_challenge_manager)

session.add(block)
session.flush()
session.add(user)

# Process dummy event just to get this thing initted
bus.dispatch(ChallengeEvent.profile_update, BLOCK_NUMBER, 1)
bus.flush()
bus.process_events(session)
state = profile_challenge_manager.get_user_challenge_state(session, ["1"])[0]

# We should have completed a single step (name)
assert state.current_step_count == 1 and not state.is_complete

# Do a repost
repost = Repost(
blockhash="0x1",
blocknumber=BLOCK_NUMBER,
user_id=1,
repost_item_id=1,
repost_type=RepostType.playlist,
is_current=True,
is_delete=False,
created_at=datetime.now(),
)
session.add(repost)
session.flush()
bus.dispatch(ChallengeEvent.repost, BLOCK_NUMBER, 1)
bus.flush()
bus.process_events(session)
state = profile_challenge_manager.get_user_challenge_state(session, ["1"])[0]
assert state.current_step_count == 2 and not state.is_complete

# Do a save
save = Save(
blockhash="0x1",
blocknumber=BLOCK_NUMBER,
user_id=1,
save_item_id=1,
save_type=SaveType.playlist,
is_current=True,
is_delete=False,
created_at=datetime.now(),
)
session.add(save)
session.flush()
bus.dispatch(ChallengeEvent.favorite, BLOCK_NUMBER, 1)
bus.flush()
bus.process_events(session)
session.flush()
state = profile_challenge_manager.get_user_challenge_state(session, ["1"])[0]
assert state.current_step_count == 3 and not state.is_complete

# Do 1 follow, then 5 total follows
follow = Follow(
blockhash="0x1",
blocknumber=BLOCK_NUMBER,
is_current=True,
is_delete=False,
created_at=datetime.now(),
follower_user_id=1,
followee_user_id=2,
)
session.add(follow)
session.flush()
bus.dispatch(ChallengeEvent.follow, BLOCK_NUMBER, 1)
bus.flush()
bus.process_events(session)
session.flush()
state = profile_challenge_manager.get_user_challenge_state(session, ["1"])[0]
# Assert 1 follow didn't do anything
assert state.current_step_count == 3 and not state.is_complete
follows = [
Follow(
blockhash="0x1",
blocknumber=BLOCK_NUMBER,
is_current=True,
is_delete=False,
created_at=datetime.now(),
follower_user_id=1,
followee_user_id=3,
),
Follow(
blockhash="0x1",
blocknumber=BLOCK_NUMBER,
is_current=True,
is_delete=False,
created_at=datetime.now(),
follower_user_id=1,
followee_user_id=4,
),
Follow(
blockhash="0x1",
blocknumber=BLOCK_NUMBER,
is_current=True,
is_delete=False,
created_at=datetime.now(),
follower_user_id=1,
followee_user_id=5,
),
Follow(
blockhash="0x1",
blocknumber=BLOCK_NUMBER,
is_current=True,
is_delete=False,
created_at=datetime.now(),
follower_user_id=1,
followee_user_id=6,
),
]
session.add_all(follows)
session.flush()
bus.dispatch(ChallengeEvent.follow, BLOCK_NUMBER, 1)
bus.flush()
bus.process_events(session)
state = profile_challenge_manager.get_user_challenge_state(session, ["1"])[0]
assert state.current_step_count == 4 and not state.is_complete

# profile_picture
session.query(User).filter(User.user_id == 1).update(
{"profile_picture": "profilepictureurl"}
)
session.flush()
bus.dispatch(ChallengeEvent.profile_update, BLOCK_NUMBER, 1)
bus.flush()
bus.process_events(session)
state = profile_challenge_manager.get_user_challenge_state(session, ["1"])[0]
assert state.current_step_count == 5 and not state.is_complete

# profile description
session.query(User).filter(User.user_id == 1).update(
{"bio": "profiledescription"}
)
session.flush()
bus.dispatch(ChallengeEvent.profile_update, BLOCK_NUMBER, 1)
bus.flush()
bus.process_events(session)
state = profile_challenge_manager.get_user_challenge_state(session, ["1"])[0]
assert state.current_step_count == 6 and not state.is_complete

# Undo it, ensure that our count goes down
session.query(User).filter(User.user_id == 1).update({"bio": None})
session.flush()
bus.dispatch(ChallengeEvent.profile_update, BLOCK_NUMBER, 1)
bus.flush()
bus.process_events(session)
state = profile_challenge_manager.get_user_challenge_state(session, ["1"])[0]
assert state.current_step_count == 5 and not state.is_complete

# profile_cover_photo
session.query(User).filter(User.user_id == 1).update(
{"bio": "profiledescription", "cover_photo": "test_cover_photo"}
)
session.flush()
bus.dispatch(ChallengeEvent.profile_update, BLOCK_NUMBER, 1)
bus.flush()
bus.process_events(session)
state = profile_challenge_manager.get_user_challenge_state(session, ["1"])[0]
assert state.current_step_count == 7 and state.is_complete == True

# ensure that if we lose some data now that the thing is complete, we don't change the status of the challenge
session.query(User).filter(User.user_id == 1).update({"cover_photo": None})
session.flush()
bus.dispatch(ChallengeEvent.profile_update, BLOCK_NUMBER, 1)
bus.flush()
bus.process_events(session)
state = profile_challenge_manager.get_user_challenge_state(session, ["1"])[0]
assert state.current_step_count == 7 and state.is_complete == True
4 changes: 3 additions & 1 deletion discovery-provider/src/tasks/user_library.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,9 @@ def user_library_state_update(
playlist_id,
playlist_ids[playlist_id].save_type,
)
session.add(playlist_ids[playlist_id])
save = playlist_ids[playlist_id]
session.add(save)
dispatch_favorite(challenge_bus, save, block_number)
num_total_changes += len(playlist_ids)

return num_total_changes
Expand Down

0 comments on commit 483c942

Please sign in to comment.