public IHttpActionResult CleanDataFolders(string apiAdminKey, int daysToKeepOnDaily = 4 * 7 + 7, int daysToKeepOnWeekly = 3 * 4 * 7 + 7, int daysToKeepClanFiles = 2 * 4 * 7 + 7, int daysToKeepPlayerFiles = 2 * 4 * 7 + 7) { try { if (apiAdminKey != ApiAdminKey) { Log.Warn($"Invalid API key on {nameof(CleanDataFolders)}: {apiAdminKey}"); throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.Unauthorized) { Content = new StringContent("Incorrect key! Your try was logged."), ReasonPhrase = "Incorrect key" }); } if (daysToKeepOnDaily < 7) { throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.BadRequest) { Content = new StringContent($"{nameof(daysToKeepOnDaily)} must be at least 7."), ReasonPhrase = "Incorrect parameters" }); } if (daysToKeepOnWeekly < 28) { throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.BadRequest) { Content = new StringContent($"{nameof(daysToKeepOnWeekly)} must be at least 28."), ReasonPhrase = "Incorrect parameters" }); } if (daysToKeepClanFiles < 28) { throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.BadRequest) { Content = new StringContent($"{nameof(daysToKeepClanFiles)} must be at least 28."), ReasonPhrase = "Incorrect parameters" }); } if (daysToKeepPlayerFiles < 28) { throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.BadRequest) { Content = new StringContent($"{nameof(daysToKeepPlayerFiles)} must be at least 28."), ReasonPhrase = "Incorrect parameters" }); } var sw = Stopwatch.StartNew(); var rootFolder = GlobalHelper.DataFolder; long deleted = 0; long bytes = 0; var errors = new List <string>(); void DeletedFileLocal(FileInfo fi) { var b = fi.Length; if (!DeleteFile(fi, out var e)) { errors.Add(e); if (errors.Count > 1000) { throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.InternalServerError) { Content = new StringContent("Too many errors deleting the files."), ReasonPhrase = "Clean failed" }); } } else { deleted++; bytes += b; } } // The root directory should be always empty of files var di = new DirectoryInfo(rootFolder); foreach (var fi in di.EnumerateFiles()) { DeletedFileLocal(fi); } var regex = new Regex(@"\d{4}-\d{2}-\d{2}", RegexOptions.Compiled); // MoE, is a daily file di = new DirectoryInfo(Path.Combine(rootFolder, "MoE")); foreach (var fi in di.EnumerateFiles()) { var m = regex.Match(fi.Name); if (!m.Success) { continue; } var date = DateTime.ParseExact(m.Value, "yyyy-MM-dd", CultureInfo.InvariantCulture); var age = (DateTime.UtcNow.Date - date).TotalDays; if (age > daysToKeepOnDaily) { DeletedFileLocal(fi); } } // Tanks are weekly files di = new DirectoryInfo(Path.Combine(rootFolder, "Tanks")); foreach (var fi in di.EnumerateFiles()) { var m = regex.Match(fi.Name); if (!m.Success) { continue; } var date = DateTime.ParseExact(m.Value, "yyyy-MM-dd", CultureInfo.InvariantCulture); var age = (DateTime.UtcNow.Date - date).TotalDays; if (age > daysToKeepOnWeekly) { DeletedFileLocal(fi); } } // Clans without any updates di = new DirectoryInfo(Path.Combine(rootFolder, "Clans")); foreach (var fi in di.EnumerateFiles()) { var date = fi.LastWriteTimeUtc; var age = (DateTime.UtcNow.Date - date).TotalDays; if (age > daysToKeepClanFiles) { DeletedFileLocal(fi); } } // Players without any updates on files (old way) di = new DirectoryInfo(Path.Combine(rootFolder, "Players")); foreach (var fi in di.EnumerateFiles()) { var date = fi.LastWriteTimeUtc; var age = (DateTime.UtcNow.Date - date).TotalDays; if (age > daysToKeepPlayerFiles) { DeletedFileLocal(fi); } } // Players without any updates on the database (current way) var connectionString = ConfigurationManager.ConnectionStrings["Store"].ConnectionString; var db = new KeyStore(connectionString); db.CleanOldPlayers(daysToKeepPlayerFiles); sw.Stop(); var result = new { TimeTaken = sw.ElapsedMilliseconds, Deleted = deleted, DeletedBytes = bytes, Errors = errors }; return(Ok(result)); } catch (HttpResponseException) { throw; } catch (Exception ex) { Log.Error($"Error in {nameof(CleanDataFolders)}", ex); throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.InternalServerError) { Content = new StringContent(ex.Message), ReasonPhrase = "Clean failed" }); } }