def _write_rides(self, start, end, athlete, rewrite=False): sess = db.session api_ride_entries = data.list_rides( athlete=athlete, start_date=start, end_date=end, exclude_keywords=app.config.get("BAFS_EXCLUDE_KEYWORDS") ) start_notz = start.replace( tzinfo=None ) # Because MySQL doesn't like it and we are not storing tz info in the db. q = sess.query(model.Ride) q = q.filter(and_(model.Ride.athlete_id == athlete.id, model.Ride.start_date >= start_notz)) db_rides = q.all() # Quickly filter out only the rides that are not in the database. returned_ride_ids = set([r.id for r in api_ride_entries]) stored_ride_ids = set([r.id for r in db_rides]) new_ride_ids = list(returned_ride_ids - stored_ride_ids) removed_ride_ids = list(stored_ride_ids - returned_ride_ids) num_rides = len(api_ride_entries) for (i, strava_activity) in enumerate(api_ride_entries): self.logger.debug("Processing ride: {0} ({1}/{2})".format(strava_activity.id, i + 1, num_rides)) if rewrite or not strava_activity.id in stored_ride_ids: try: ride = data.write_ride(strava_activity) self.logger.info( "[NEW RIDE]: {id} {name!r} ({i}/{num}) ".format( id=strava_activity.id, name=strava_activity.name, i=i + 1, num=num_rides ) ) sess.commit() except Exception as x: self.logger.debug( "Error writing out ride, will attempt to add/update RideError: {0}".format(strava_activity.id) ) sess.rollback() try: ride_error = sess.query(model.RideError).get(strava_activity.id) if ride_error is None: self.logger.exception( "[ERROR] Unable to write ride (skipping): {0}".format(strava_activity.id) ) ride_error = model.RideError() else: # We already have a record of the error, so log that message with less verbosity. self.logger.warning( "[ERROR] Unable to write ride (skipping): {0}".format(strava_activity.id) ) ride_error.athlete_id = athlete.id ride_error.id = strava_activity.id ride_error.name = strava_activity.name ride_error.start_date = strava_activity.start_date_local ride_error.reason = str(x) ride_error.last_seen = datetime.now() # FIXME: TZ? sess.add(ride_error) sess.commit() except: self.logger.exception("Error adding ride-error entry.") else: sess.commit() try: # If there is an error entry, then we should remove it. q = sess.query(model.RideError) q = q.filter(model.RideError.id == ride.id) deleted = q.delete(synchronize_session=False) if deleted: self.logger.info("Removed matching error-ride entry for {0}".format(strava_activity.id)) sess.commit() except: self.logger.exception("Error maybe-clearing ride-error entry.") else: self.logger.info( "[SKIPPED EXISTING]: {id} {name!r} ({i}/{num}) ".format( id=strava_activity.id, name=strava_activity.name, i=i + 1, num=num_rides ) ) # Remove any rides that are in the database for this athlete that were not in the returned list. if removed_ride_ids: q = sess.query(model.Ride) q = q.filter(model.Ride.id.in_(removed_ride_ids)) deleted = q.delete(synchronize_session=False) self.logger.info("Removed {0} no longer present rides for athlete {1}.".format(deleted, athlete)) else: self.logger.info("(No removed rides for athlete {0}.)".format(athlete)) sess.commit()
def _write_rides(self, start, end, athlete, rewrite=False): sess = db.session api_ride_entries = data.list_rides(athlete=athlete, start_date=start, end_date=end, exclude_keywords=app.config.get('BAFS_EXCLUDE_KEYWORDS')) start_notz = start.replace( tzinfo=None) # Because MySQL doesn't like it and we are not storing tz info in the db. q = sess.query(model.Ride) q = q.filter(and_(model.Ride.athlete_id == athlete.id, model.Ride.start_date >= start_notz)) db_rides = q.all() # Quickly filter out only the rides that are not in the database. returned_ride_ids = set([r.id for r in api_ride_entries]) stored_ride_ids = set([r.id for r in db_rides]) new_ride_ids = list(returned_ride_ids - stored_ride_ids) removed_ride_ids = list(stored_ride_ids - returned_ride_ids) num_rides = len(api_ride_entries) for (i, strava_activity) in enumerate(api_ride_entries): self.logger.debug("Processing ride: {0} ({1}/{2})".format(strava_activity.id, i + 1, num_rides)) if rewrite or not strava_activity.id in stored_ride_ids: try: ride = data.write_ride(strava_activity) self.logger.info("[NEW RIDE]: {id} {name!r} ({i}/{num}) ".format(id=strava_activity.id, name=strava_activity.name, i=i + 1, num=num_rides)) sess.commit() except Exception as x: self.logger.debug("Error writing out ride, will attempt to add/update RideError: {0}".format(strava_activity.id)) sess.rollback() try: ride_error = sess.query(model.RideError).get(strava_activity.id) if ride_error is None: self.logger.exception("[ERROR] Unable to write ride (skipping): {0}".format(strava_activity.id)) ride_error = model.RideError() else: # We already have a record of the error, so log that message with less verbosity. self.logger.warning("[ERROR] Unable to write ride (skipping): {0}".format(strava_activity.id)) ride_error.athlete_id = athlete.id ride_error.id = strava_activity.id ride_error.name = strava_activity.name ride_error.start_date = strava_activity.start_date_local ride_error.reason = str(x) ride_error.last_seen = datetime.now() # FIXME: TZ? sess.add(ride_error) sess.commit() except: self.logger.exception("Error adding ride-error entry.") else: sess.commit() try: # If there is an error entry, then we should remove it. q = sess.query(model.RideError) q = q.filter(model.RideError.id == ride.id) deleted = q.delete(synchronize_session=False) if deleted: self.logger.info("Removed matching error-ride entry for {0}".format(strava_activity.id)) sess.commit() except: self.logger.exception("Error maybe-clearing ride-error entry.") else: self.logger.info("[SKIPPED EXISTING]: {id} {name!r} ({i}/{num}) ".format(id=strava_activity.id, name=strava_activity.name, i=i + 1, num=num_rides)) # Remove any rides that are in the database for this athlete that were not in the returned list. if removed_ride_ids: q = sess.query(model.Ride) q = q.filter(model.Ride.id.in_(removed_ride_ids)) deleted = q.delete(synchronize_session=False) self.logger.info("Removed {0} no longer present rides for athlete {1}.".format(deleted, athlete)) else: self.logger.info("(No removed rides for athlete {0}.)".format(athlete)) sess.commit()
def _write_rides(start, team=None, athlete_id=None, rewrite=False): logger = logging.getLogger('sync') if team and athlete_id: raise ValueError("team and athlete params are mutually exclusive") elif team is None and athlete_id is None: raise ValueError("either team or athlete_id param is required") sess = db.session if team: api_ride_entries = data.list_rides(club_id=team.id, start_date=start, exclude_keywords=app.config.get('BAFS_EXCLUDE_KEYWORDS')) q = sess.query(model.Ride) q = q.filter(and_(model.Ride.athlete_id.in_(sess.query(model.Athlete.id).filter(model.Athlete.team_id==team.id)), model.Ride.start_date >= start)) db_rides = q.all() else: api_ride_entries = data.list_rides(athlete_id=athlete_id, start_date=start, exclude_keywords=app.config.get('BAFS_EXCLUDE_KEYWORDS')) q = sess.query(model.Ride) q = q.filter(and_(model.Ride.athlete_id == athlete_id, model.Ride.start_date >= start)) db_rides = q.all() # Quickly filter out only the rides that are not in the database. returned_ride_ids = set([r.id for r in api_ride_entries]) stored_ride_ids = set([r.id for r in db_rides]) new_ride_ids = list(returned_ride_ids - stored_ride_ids) removed_ride_ids = list(stored_ride_ids - returned_ride_ids) if rewrite: num_rides = len(api_ride_entries) else: num_rides = len(new_ride_ids) # If we are "clearing" the system, then we'll just use all the returned rides as the "new" rides. for (i, ri_entry) in enumerate(api_ride_entries): logger.info("Processing ride: {0} ({1}/{2})".format(ri_entry.id, i, num_rides)) if rewrite or not ri_entry.id in stored_ride_ids: ride = data.write_ride(ri_entry.id, team=team) logger.debug("Wrote ride: %r" % (ride,)) else: logger.debug("Skipping existing ride: {id} - {name!r}".format(name=ri_entry.name,id=ri_entry.id)) # Remove any rides that are in the database for this team that were not in the returned list. if removed_ride_ids: q = sess.query(model.Ride) q = q.filter(model.Ride.id.in_(removed_ride_ids)) deleted = q.delete(synchronize_session=False) if team: logger.info("Removed {0} no longer present rides for team {1}.".format(deleted, team.id)) else: logger.info("Removed {0} no longer present rides for athlete {1}.".format(deleted, athlete_id)) else: if team: logger.info("(No removed rides for team {0!r}.)".format(team)) else: logger.info("(No removed rides for athlete {0}.)".format(athlete_id)) sess.commit() # Write out any efforts associated with these rides (not already in database) q = sess.query(model.Ride).filter_by(efforts_fetched=False) for ride in q.all(): logger.info("Writing out efforts for {0!r}".format(ride)) data.write_ride_efforts(ride)