Exemple #1
0
        static int queryRange(StravaXApi stravaXApi, StravaXApiContext db, IList <ActivityRangeQuery> queries, bool doVerbose)
        {
            int ret = 0;

            foreach (ActivityRangeQuery arq in queries)
            {
                try
                {
                    // https://docs.microsoft.com/en-us/ef/core/saving/concurrency
                    try
                    {
                        // reserve query, mark it as run.
                        arq.Status        = QueryStatus.Run;
                        arq.StatusChanged = DateTime.Now;
                        db.SaveChanges();
                    }
                    catch (DbUpdateConcurrencyException)
                    {
                        // Just skip this entry if some conflict exists.
                        logger.LogInformation($"skip conflicted entry for {arq.AthleteId} at {arq.DateFrom.Year:D4}/{arq.DateFrom.Month:D2}");
                        continue;
                    }
                    var ActivitiesList        = stravaXApi.getActivities(arq.AthleteId, $"{arq.DateFrom.Year:D4}", $"{arq.DateFrom.Month:D2}");
                    int EnterredActivityCount = 0;
                    foreach (ActivityShort ActivityShort in ActivitiesList)
                    {
                        // Console.WriteLine($"JSON={ActivityShort.SerializePrettyPrint(ActivityShort)}");
                        if (db.ActivityShortDB.Find(ActivityShort.ActivityId) == null)
                        {
                            db.ActivityShortDB.Add(ActivityShort);
                            try{
                                // do it better after foreach, but first check how it works with the concurrentcy exception
                                db.SaveChanges();
                                EnterredActivityCount++;
                            }
                            catch (DbUpdateConcurrencyException)
                            {
                                // Just skip this entry if some conflict exists.
                                logger.LogInformation($"❌ skip conflicted activity {ActivityShort}");
                                continue;
                            }
                        }
                        else
                        {
                            logger.LogInformation($"❌ {ActivityShort.ActivityId} allready in database");
                        }
                    }
                    arq.Status        = QueryStatus.Done;
                    arq.StatusChanged = DateTime.Now;
                    // should not have to save anything.
                    db.SaveChanges();
                    if (doVerbose)
                    {
                        logger.LogInformation($"enterred activity count: {EnterredActivityCount}/{db.ActivityShortDB.Count()} for {arq.AthleteId} at {arq.DateFrom.Year:D4}/{arq.DateFrom.Month:D2}");
                    }
                    else // '.Count()' is pretty expensive, skip it if verbose should be minimal.
                    {
                        logger.LogInformation($"enterred activity count: {EnterredActivityCount} for {arq.AthleteId} at {arq.DateFrom.Year:D4}/{arq.DateFrom.Month:D2}");
                    }
                    ErrorCountConsecutive = 0;
                }
                catch (Exception e)
                {
                    ErrorCountConsecutive++;
                    ErrorCount++;
                    logger.LogInformation($"Error: {ErrorCountConsecutive}/3 total:{ErrorCount} -> skip:{arq} {e.Message}");
                    arq.Status        = QueryStatus.Error;
                    arq.StatusChanged = DateTime.Now;
                    arq.Message       = $"Error: {ErrorCountConsecutive}/3 total:{ErrorCount} -> skip:{arq} {e.Message}";
                    if (ErrorCountConsecutive > 2)
                    {
                        // After 3 consecutive errors, I assume the selenium driver is down. Stop it all.
                        throw e;
                    }
                }

                if (doVerbose)
                {
                    logger.LogInformation($"activities stored:{db.ActivityShortDB.Count()}/{QueryStatus.Created}:{db.ActivityQueriesDB.Count(a => a.Status==QueryStatus.Created)}/{QueryStatus.Reserved}:{db.ActivityQueriesDB.Count(a => a.Status==QueryStatus.Reserved)}");
                }

                Count++;

                // Exist when KeepRunning is false (from the debugger),
                // or the file 'QueryActivities.quit' exists.
                //   *Program will exit with "touch QueryActivities.quit" in /app directory in container.
                Boolean KeepRunning = true;
                if (!KeepRunning || File.Exists("QueryActivities.quit.immediatly"))
                {
                    logger.LogInformation($"break {KeepRunning} {Count}");
                    // regular exit, container should ended.
                    throw new CancelExecution("break {KeepRunning} {Count}");
                }
            }
            return(ret);
        }
        static internal int ReadActivitiesForAthlete(StravaXApi stravaXApi, string[] args)
        {
            int ret = -1;

            Console.WriteLine("Read athlete activities with Strava-X-API.");

            String AthleteId = null;
            var    p         = new OptionSet()
            {
                { "a|athleteid=", v => { AthleteId = v; } },
            };

            p.Parse(args);
            if (AthleteId == null)
            {
                p.WriteOptionDescriptions(Console.Out);
                throw new ArgumentException("missing athlete id");
            }

            try
            {
                stravaXApi.signIn();
                List <ActivityShort> ActivitiesList = new List <ActivityShort>();

                DateTime FirstActivityDate = stravaXApi.getActivityRange(AthleteId);
                System.Console.WriteLine($"First activity at {FirstActivityDate.Year}/{FirstActivityDate.Month}");

                int      FromYear  = int.Parse(Environment.GetEnvironmentVariable("FROM_YEAR"));
                int      FromMonth = int.Parse(Environment.GetEnvironmentVariable("FROM_MONTH"));
                int      ToYear    = int.Parse(Environment.GetEnvironmentVariable("TO_YEAR"));
                int      ToMonth   = int.Parse(Environment.GetEnvironmentVariable("TO_MONTH"));
                DateTime now       = DateTime.Now;
                for (int year = FromYear; year <= ToYear; year++)
                {
                    for (int month = 01; month <= 12; month++)
                    {
                        if ((year <= FromYear && month < FromMonth) ||  (year >= ToYear && month > ToMonth))
                        {
                            continue;
                        }
                        List <ActivityShort> ActivitiesMonthList;
                        try
                        {
                            ActivitiesMonthList = stravaXApi.getActivities(AthleteId, $"{year:D4}", $"{month:D2}");
                        }
                        catch (StaleElementReferenceException)
                        {
                            // Wait and try again.
                            Thread.Sleep(2000);
                            ActivitiesMonthList = stravaXApi.getActivities(AthleteId, $"{year:D4}", $"{month:D2}");
                        }
                        ActivitiesList.AddRange(ActivitiesMonthList);
                        using (StravaXApiContext db = new StravaXApiContext())
                        {
                            foreach (ActivityShort ActivityShort in ActivitiesList)
                            {
                                Console.WriteLine($"JSON={ActivityShort.SerializePrettyPrint(ActivityShort)}");
                                if (db.ActivityShortDB.Find(ActivityShort.ActivityId) == null)
                                {
                                    db.ActivityShortDB.Add(ActivityShort);
                                    db.SaveChanges();
                                    Console.WriteLine($"Enterred Activities: {db.ActivityShortDB.OrderBy(b => b.ActivityId).Count()}");
                                }
                                else
                                {
                                    Console.WriteLine($"{ActivityShort.ActivityId} allready in database");
                                }
                            }
                            Console.WriteLine($"total read = {ActivitiesList.Count}");
                            Console.WriteLine($"total stored = {db.ActivityShortDB.OrderBy(b => b.ActivityId).Count()}");
                            ActivitiesList.Clear();
                        }
                    }
                }
                ret = 0;
            }
            catch (Exception e)
            {
                Console.WriteLine($"ERROR:{e.ToString()}");
                ret = 1;
            }
            finally
            {
                stravaXApi.Dispose();
            }
            return(ret);
        }