Skip to content
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

Leaderboard Update on Submission #161

Merged
merged 26 commits into from
May 3, 2024

Conversation

Gehrkej
Copy link
Contributor

@Gehrkej Gehrkej commented Apr 19, 2024

Changes:

In this PR I have implemented functionality that will update the "best_attempts" table upon submitting a drill attempt. Currently, it covers the case where it is a users first time completing the drill as well as comparing if an attempt is already in existence.

Related issues: #150 #95

Concerns:

Our current structure of "best_attempts" requires us to upload a completely new map/object for any given drill document. With this structure, a race case could occur where two users get a new high score and upon each of the uploading a new map/object with their updated score, it could erase one of the records.

Proposed fix:

If we structure each of the users within the drill document as a document itself instead of a map/object, we can update the user document directly which would eliminate the case brought up previously although I am unsure what effects this would have on the current leaderboard implementation.

@FrankreedX
Copy link
Contributor

The reason it’s an object/map is cuz firebase needs a document to be followed by a collection, and then a document, etc. It didn’t line up for best attempts.

@solderq35
Copy link
Contributor

solderq35 commented Apr 19, 2024

Seems to be working atm except for the potential race condition listed above, as well as the leaderboard updates not working quite right in cases where the order of leaderboard sorting does not match the "lowerisbetter" value from drills table.

E.g. Short Putting, 5-15 feet, which sorts by lowest first on the leaderboard while having "lowerisbetter: false" in drills table. It does not update correctly at the moment (checking for lower rather than higher value in new attempts).

Working use cases tested on new commit (previously not working):

  • New submission on leaderboard you have not submitted for yet
  • Updating your best score on a leaderboard you have submitted to before (Tested on Short Putting, 3-6 feet, which has "lowerisbetter: true" in drills table)

@solderq35
Copy link
Contributor

Would something from here fix the race conditioned mentioned above?

https://firebase.google.com/docs/firestore/manage-data/add-data#update-data

updateDoc seems to be designed to avoid overwriting existing fields, and also see the "Update fields in nested objects" section

@solderq35 solderq35 force-pushed the Gehrkej/update-leaderboard-on-submit branch from ebc99be to 56a29f5 Compare April 24, 2024 08:01
@solderq35
Copy link
Contributor

solderq35 commented Apr 24, 2024

Sorting by lower / higher on the leaderboard now seems to work properly, as does updating best score (based on lowerIsBetter flag)

  • sort + update by lowest

    • initial score
      • image
    • updated score (lower)
      • image
  • sort + update by highest

    • initial score
      • image
    • updated score (higher)
      • image

@Gehrkej
Copy link
Contributor Author

Gehrkej commented Apr 25, 2024

I have added numbers to the leaderboard and have accounted for the case there is a tie. For the tie, this is using the full attempt value as of right now and not the truncated display value.

image

** 2 way Tie Example**
leaderboard

3 way Tie Example
image

@Gehrkej Gehrkej mentioned this pull request Apr 26, 2024
6 tasks
@solderq35
Copy link
Contributor

Need to test this more in actual race case conditions (try to submit from 2 diff accounts at same time). One on emulator, one on iphone or something.

@solderq35
Copy link
Contributor

solderq35 commented Apr 26, 2024

It seems that setDoc only needs to be called when best_attempts > drillId doesn't exist yet (which should be out of scope for now, only relevant if we want to give the coach ability to create new leaderboards and drills on the fly in the future).

In all other use cases (empty leaderboard, user's first submission on a non-empty leaderboard, user updating their best time), updateDoc can be used. Since only setDoc triggers the race condition between different users, this issue ought to be resolved.

I also removed unused code and the old updateLeaderboard hook to avoid confusion / make it easier to delete existing leaderboard entries for testing (just delete any entries from best_attempts > drillId doc if needed, from Firebase console)

I did a little bit of manual testing (open 2 terminals on PC, run 1 terminal for ios and 1 terminal for android, try to submit from 2 user accounts on the 2 devices at the same time). Everything seemed to update as expected with no race case, both for empty leaderboards and leaderboards with existing entries (although Android emulator does lag a bit, so I wasn't sure if they really uploaded at same time).

@solderq35 solderq35 marked this pull request as ready for review April 26, 2024 20:51
Copy link
Contributor

@FrankreedX FrankreedX left a comment

Choose a reason for hiding this comment

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

Great work!

app/segments/drill/[id]/submission/input.js Outdated Show resolved Hide resolved
app/segments/drill/[id]/submission/input.js Outdated Show resolved Hide resolved
app/segments/drill/[id]/submission/input.js Outdated Show resolved Hide resolved
app/segments/drill/[id]/submission/input.js Outdated Show resolved Hide resolved
app/segments/drill/[id]/submission/input.js Outdated Show resolved Hide resolved
app/segments/drill/[id]/submission/input.js Outdated Show resolved Hide resolved
app/content/drill/[id]/leaderboard.js Outdated Show resolved Hide resolved
app/content/drill/[id]/leaderboard.js Outdated Show resolved Hide resolved
app/segments/drill/[id]/submission/input.js Outdated Show resolved Hide resolved
app/segments/drill/[id]/submission/input.js Outdated Show resolved Hide resolved
@solderq35
Copy link
Contributor

Firebase transactions work for get + update, should avoid race conditions in future

Reference: First example code here: https://firebase.google.com/docs/firestore/manage-data/transactions#transactions

Screenshots
image
image
image

app/segments/drill/[id]/submission/input.js Outdated Show resolved Hide resolved
app/segments/drill/[id]/submission/input.js Outdated Show resolved Hide resolved
app/segments/drill/[id]/submission/input.js Outdated Show resolved Hide resolved
app/segments/drill/[id]/submission/input.js Outdated Show resolved Hide resolved
app/segments/drill/[id]/submission/input.js Outdated Show resolved Hide resolved
app/segments/drill/[id]/submission/input.js Outdated Show resolved Hide resolved
@solderq35
Copy link
Contributor

solderq35 commented May 3, 2024

I refactored the functionality for invalidating multiple query keys to a hook (previously all inside the refreshInvalidate component): #149

In addition, I reworked invalidateMultipleQueries hook to only log the successfully invalidated queries, and filter out duplicates:

image

I kept the original logs commented out as a potential tool for more thorough debugging
image

@solderq35 solderq35 force-pushed the Gehrkej/update-leaderboard-on-submit branch from c46d4c9 to faed74d Compare May 3, 2024 01:49
@solderq35
Copy link
Contributor

rebased (no conflicts)

Copy link
Contributor

@FrankreedX FrankreedX left a comment

Choose a reason for hiding this comment

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

I added a commit so check it before merging

@solderq35
Copy link
Contributor

solderq35 commented May 3, 2024

added back react-native-gesture-handler due to this error:
image

Everything else looked good when testing leaderboard functionality

EDIT:
Ended up installing it via npx as shown: https://stackoverflow.com/a/77962693

@solderq35 solderq35 merged commit e3a4929 into layout May 3, 2024
1 check passed
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.

4 participants