Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 626455
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 13, 20262026-05-13T19:25:16+00:00 2026-05-13T19:25:16+00:00

Consider a GAE (python) app that lets users comment on songs. The expected number

  • 0

Consider a GAE (python) app that lets users comment on songs. The expected number of users is 1,000,000+. The expected number of songs is 5,000.

The app must be able to:

  • Give the number of songs a user has commented on
  • Give the number of users who have commented on a song

Counter management must be transactional so that they always reflect the underlying data.

It seems GAE apps must keep these types of counts calculated at all times since querying for them at request time would be inefficient.

My Data Model

class Song(BaseModel):
    name = db.StringProperty()
    # Number of users commenting on the song
    user_count = db.IntegerProperty('user count', default=0, required=True)
    date_added = db.DateTimeProperty('date added', False, True)
    date_updated = db.DateTimeProperty('date updated', True, False)

class User(BaseModel):
    email = db.StringProperty()
    # Number of songs commented on by the user
    song_count = db.IntegerProperty('song count', default=0, required=True)
    date_added = db.DateTimeProperty('date added', False, True)
    date_updated = db.DateTimeProperty('date updated', True, False)

class SongUser(BaseModel):
    # Will be child of User
    song = db.ReferenceProperty(Song, required=True, collection_name='songs')
    comment = db.StringProperty('comment', required=True)
    date_added = db.DateTimeProperty('date added', False, True)
    date_updated = db.DateTimeProperty('date updated', True, False)

Code
This handles the user’s song count transactionally but not the song’s user count.

s = Song(name='Hey Jude')
s.put()

u = User(email='me@example.com')
u.put()

def add_mapping(song_key, song_comment, user_key):
    u = User.get(user_key)

    su = SongUser(parent=u, song=song_key, song_comment=song_comment, user=u);
    u.song_count += 1

    u.put()
    su.put()

# Transactionally add mapping and increase user's song count
db.run_in_transaction(add_mapping, s.key(), 'Awesome', u.key())

# Increase song's user count (non-transactional)
s.user_count += 1
s.put()

The question is: How can I manage both counters transactionally?

Based on my understanding this would be impossible since User, Song, and SongUser would have to be a part of the same entity group. They can’t be in one entity group because then all my data would be in one group and it could not be distributed by user.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-13T19:25:16+00:00Added an answer on May 13, 2026 at 7:25 pm

    You really shouldn’t have to worry about handling the user’s count of songs on which they have commented inside a transaction because it seems unlikely that a User would be able to comment on more than one song at a time, right?

    Now, it is definitely the case that many users could be commenting on the same song at one time, so that is where you have to worry about making sure that the data isn’t made invalid by a race condition.

    However, if you keep the count of the number of users who have commented on a song inside the Song entity, and lock the entity with a transaction, you are going to get very high contention for that entity and datastore timeouts will make you application have lots of problems.

    This answer for this problem is Sharded Counters.

    In order to make sure that you can create a new SongUser entity and update the related Song’s sharded counter, you should consider having the SongUser entity have the related Song as a parent. That will put them in the same entity group and you can both create the SongUser and updated the sharded counter in the same transaction. The SongUser’s relationship to the User who created it can be held in a ReferenceProperty.

    Regarding your concern about the two updates (the transactional one and the User update) not both succeeding, that is always a possibility, but given that either update can fail, you will need to have proper exception-handling to ensure that both succeed. That’s an important point: the in-transaction-updates are not guaranteed to succeed. You may get a TransactionfailedError exception if the transaction can not complete for any reason.

    So, if your transaction completes without raising an exception, run the update to User in a transaction. That will get you automatic retries of the update to User, should some error occur. Unless there’s something about possible contention on the User entity that I don’t understand, the possiblity that it will not eventually succeed is surpassingly small. If that is an unacceptable risk, then I don’t think that that AppEngine has a perfect solution to this problem for you.

    First ask yourself: is it really that bad if the count of songs that someone has commented on is off by one? Is this as critical as updating a bank account balance or completing a stock sale?

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

Consider this scenario. We have an internal Rails 2 app that connects to a
I'm about to embark on some large Python-based App Engine projects, and I think
Consider an ASP.NET Web API service that redirects public class ThisController : ApiController {
Consider the following Python script, which uses SQLAlchemy and the Python multiprocessing module. This
I need to read a 5Mb file on Google App Engine (Python 2.7) and
Consider that we are given an isometric grid (consider something like Diablo) of tiles.
Consider an article inside a div that has many <p> tag. Is there any
Consider the following function that implements non-blocking access to only the one thread. public
Consider that I have a complex class structure where many elements inherit from other
Consider the following MySQL tables: APPLICATIONS (contains all applications by all users) unique_id |

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.